-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
319 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,67 @@ | ||
#pragma once | ||
|
||
#include <list> | ||
|
||
#include <sisl/utility/enum.hpp> | ||
|
||
#include "common.hpp" | ||
|
||
namespace homeblocks {} // namespace homeblocks | ||
namespace homeblocks { | ||
|
||
class VolumeManager; | ||
|
||
ENUM(DevType, uint8_t, AUTO_DETECT = 1, HDD, NVME, UNSUPPORTED); | ||
struct device_info_t { | ||
explicit device_info_t(std::string name, DevType dtype = DevType::AUTO_DETECT) : | ||
path{std::filesystem::canonical(name)}, type{dtype} {} | ||
device_info_t() = default; | ||
bool operator==(device_info_t const& rhs) const { return path == rhs.path && type == rhs.type; } | ||
friend std::istream& operator>>(std::istream& input, device_info_t& di) { | ||
std::string i_path, i_type; | ||
std::getline(input, i_path, ':'); | ||
std::getline(input, i_type); | ||
di.path = std::filesystem::canonical(i_path); | ||
if (i_type == "HDD") { | ||
di.type = DevType::HDD; | ||
} else if (i_type == "NVME") { | ||
di.type = DevType::NVME; | ||
} else { | ||
di.type = DevType::AUTO_DETECT; | ||
} | ||
return input; | ||
} | ||
std::filesystem::path path; | ||
DevType type; | ||
}; | ||
|
||
class HomeBlocksApplication { | ||
public: | ||
virtual ~HomeBlocksApplication() = default; | ||
|
||
virtual bool spdk_mode() const = 0; | ||
virtual uint32_t threads() const = 0; | ||
virtual std::list< device_info_t > devices() const = 0; | ||
|
||
// Callback made after determining if a SvcId exists or not during initialization, will consume response | ||
virtual peer_id_t discover_svcid(std::optional< peer_id_t > const& found) const = 0; | ||
}; | ||
|
||
struct HomeBlocksStats { | ||
uint64_t total_capacity_bytes{0}; | ||
uint64_t used_capacity_bytes{0}; | ||
std::string to_string() const { | ||
return fmt::format("total_capacity_bytes={}, used_capacity_bytes={}", total_capacity_bytes, | ||
used_capacity_bytes); | ||
} | ||
}; | ||
|
||
class HomeBlocks { | ||
public: | ||
virtual ~HomeBlocks() = default; | ||
virtual peer_id_t our_uuid() const = 0; | ||
virtual std::shared_ptr< VolumeManager > volume_manager() = 0; | ||
virtual HomeBlocksStats get_stats() const = 0; | ||
}; | ||
|
||
extern std::shared_ptr< HomeBlocks > init_homeobject(std::weak_ptr< HomeBlocksApplication >&& application); | ||
} // namespace homeblocks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
#pragma once | ||
#include <compare> | ||
#include <string> | ||
|
||
#include <boost/uuid/uuid_io.hpp> | ||
#include <sisl/utility/enum.hpp> | ||
|
||
#include "common.hpp" | ||
|
||
namespace homeblocks { | ||
|
||
ENUM(VolumeError, uint16_t, UNKNOWN = 1, INVALID_ARG, TIMEOUT, UNKNOWN_VOLUME, UNSUPPORTED_OP, CRC_MISMATCH, | ||
NO_SPACE_LEFT, DRIVE_WRITE_ERROR); | ||
|
||
struct VolumeInfo { | ||
VolumeInfo(volume_id_t _id, uint64_t _num_bytes) : id(_id), size_bytes(_num_bytes) {} | ||
|
||
volume_id_t id; | ||
uint64_t size_bytes{0}; | ||
|
||
auto operator<=>(VolumeInfo const& rhs) const { | ||
return boost::uuids::hash_value(id) <=> boost::uuids::hash_value(rhs.id); | ||
} | ||
auto operator==(VolumeInfo const& rhs) const { return id == rhs.id; } | ||
}; | ||
|
||
struct VolumeStats { | ||
volume_id_t id; | ||
|
||
uint64_t used_bytes; // total number of bytes used by all shards on this Volume; | ||
uint64_t avail_bytes; // total number of bytes available on this Volume; | ||
|
||
std::string to_string() { | ||
return fmt::format("VolumeStats: id={} used_bytes={}, avail_bytes={}", boost::uuids::to_string(id), used_bytes, | ||
avail_bytes); | ||
} | ||
}; | ||
|
||
class VolumeManager : public Manager< VolumeError > { | ||
public: | ||
virtual NullAsyncResult create_volume(VolumeInfo&& volume_info) = 0; | ||
|
||
/** | ||
* Retrieves the statistics for a specific Volume identified by its ID. | ||
* | ||
* @param id The ID of the Volume. | ||
* @param stats The reference to the VolumeStats object where the statistics will be stored. | ||
* @return True if the statistics were successfully retrieved, false otherwise (e.g. id not found). | ||
*/ | ||
virtual bool get_stats(volume_id_t id, VolumeStats& stats) const = 0; | ||
|
||
/** | ||
* @brief Retrieves the list of volume_ids. | ||
* | ||
* This function retrieves the list of volume_ids and stores them in the provided vector. | ||
* | ||
* @param vol_ids The vector to store the volume ids. | ||
*/ | ||
virtual void get_volume_ids(std::vector< volume_id_t >& vol_ids) const = 0; | ||
}; | ||
|
||
} // namespace homeblocks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,28 @@ | ||
#include <algorithm> | ||
|
||
#include <sisl/options/options.h> | ||
#include <homeblocks/homeblocks.hpp> | ||
#include "homeblocks_impl.hpp" | ||
|
||
SISL_OPTION_GROUP(homeblocks, | ||
(executor_type, "", "executor", "Executor to use for Future deferal", | ||
::cxxopts::value< std::string >()->default_value("immediate"), "immediate|cpu|io")); | ||
|
||
SISL_LOGGING_DEF(HOMEBLOCKS_LOG_MODS) | ||
|
||
namespace homeobject {} // namespace homeobject | ||
namespace homeblocks { | ||
HomeBlocksImpl::HomeBlocksImpl(std::weak_ptr< HomeBlocksApplication >&& application) : | ||
_application(std::move(application)) { | ||
auto exe_type = SISL_OPTIONS["executor"].as< std::string >(); | ||
std::transform(exe_type.begin(), exe_type.end(), exe_type.begin(), ::tolower); | ||
|
||
if ("immediate" == exe_type) [[likely]] | ||
executor_ = &folly::QueuedImmediateExecutor::instance(); | ||
else if ("io" == exe_type) | ||
executor_ = folly::getGlobalIOExecutor(); | ||
else if ("cpu" == exe_type) | ||
executor_ = folly::getGlobalCPUExecutor(); | ||
else | ||
RELEASE_ASSERT(false, "Unknown Folly Executor type: [{}]", exe_type); | ||
LOGI("initialized with [executor={}]", exe_type); | ||
} | ||
} // namespace homeblocks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#pragma once | ||
|
||
#include <boost/intrusive_ptr.hpp> | ||
#include <sisl/logging/logging.h> | ||
|
||
#include <homeblocks/homeblocks.hpp> | ||
#include <homeblocks/volume_manager.hpp> | ||
|
||
#define LOGT(...) LOGTRACEMOD(homeblocks, ##__VA_ARGS__) | ||
#define LOGD(...) LOGDEBUGMOD(homeblocks, ##__VA_ARGS__) | ||
#define LOGI(...) LOGINFOMOD(homeblocks, ##__VA_ARGS__) | ||
#define LOGW(...) LOGWARNMOD(homeblocks, ##__VA_ARGS__) | ||
#define LOGE(...) LOGERRORMOD(homeblocks, ##__VA_ARGS__) | ||
#define LOGC(...) LOGCRITICALMOD(homeblocks, ##__VA_ARGS__) | ||
|
||
namespace homeblocks { | ||
|
||
template < typename T > | ||
using shared = std::shared_ptr< T >; | ||
|
||
template < typename T > | ||
using cshared = const std::shared_ptr< T >; | ||
|
||
template < typename T > | ||
using unique = std::unique_ptr< T >; | ||
|
||
template < typename T > | ||
using intrusive = boost::intrusive_ptr< T >; | ||
|
||
template < typename T > | ||
using cintrusive = const boost::intrusive_ptr< T >; | ||
|
||
struct Volume { | ||
explicit Volume(VolumeInfo info) : volume_info_(std::move(info)) {} | ||
Volume(Volume const& volume) = delete; | ||
Volume(Volume&& volume) = default; | ||
Volume& operator=(Volume const& volume) = delete; | ||
Volume& operator=(Volume&& volume) = default; | ||
virtual ~Volume() = default; | ||
|
||
VolumeInfo volume_info_; | ||
}; | ||
|
||
class HomeBlocksImpl : public HomeBlocks, public VolumeManager, public std::enable_shared_from_this< HomeBlocksImpl > { | ||
virtual VolumeManager::NullAsyncResult _create_volume(VolumeInfo&& volume_info) = 0; | ||
virtual bool _get_stats(volume_id_t id, VolumeStats& stats) const = 0; | ||
virtual void _get_volume_ids(std::vector< volume_id_t >& vol_ids) const = 0; | ||
|
||
virtual HomeBlocksStats _get_stats() const = 0; | ||
|
||
protected: | ||
peer_id_t _our_id; | ||
|
||
/// Our SvcId retrieval and SvcId->IP mapping | ||
std::weak_ptr< HomeBlocksApplication > _application; | ||
|
||
folly::Executor::KeepAlive<> executor_; | ||
|
||
/// | ||
mutable std::shared_mutex _volume_lock; | ||
std::map< volume_id_t, unique< Volume > > _volume_map; | ||
|
||
|
||
auto _defer() const { return folly::makeSemiFuture().via(executor_); } | ||
|
||
public: | ||
explicit HomeBlocksImpl(std::weak_ptr< HomeBlocksApplication >&& application); | ||
|
||
~HomeBlocksImpl() override = default; | ||
HomeBlocksImpl(const HomeBlocksImpl&) = delete; | ||
HomeBlocksImpl(HomeBlocksImpl&&) noexcept = delete; | ||
HomeBlocksImpl& operator=(const HomeBlocksImpl&) = delete; | ||
HomeBlocksImpl& operator=(HomeBlocksImpl&&) noexcept = delete; | ||
|
||
std::shared_ptr< VolumeManager > volume_manager() final; | ||
|
||
/// HomeBlocks | ||
/// Returns the UUID of this HomeBlocks. | ||
peer_id_t our_uuid() const final { return _our_id; } | ||
HomeBlocksStats get_stats() const final { return _get_stats(); } | ||
|
||
/// VolumeManager | ||
VolumeManager::NullAsyncResult create_volume(VolumeInfo&& vol_info) final; | ||
|
||
// see api comments in base class; | ||
bool get_stats(volume_id_t id, VolumeStats& stats) const final; | ||
void get_volume_ids(std::vector< volume_id_t >& vol_ids) const final; | ||
|
||
uint64_t get_current_timestamp(); | ||
}; | ||
|
||
} // namespace homeblocks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include "mem_homeblocks.hpp" | ||
|
||
namespace homeblocks { | ||
|
||
/// NOTE: We give ourselves the option to provide a different HR instance here than libhomeblocks.a | ||
extern std::shared_ptr< HomeBlocks > init_homeblocks(std::weak_ptr< HomeBlocksApplication >&& application) { | ||
return std::make_shared< MemoryHomeBlocks >(std::move(application)); | ||
} | ||
|
||
MemoryHomeBlocks::MemoryHomeBlocks(std::weak_ptr< HomeBlocksApplication >&& application) : | ||
HomeBlocksImpl::HomeBlocksImpl(std::move(application)) { | ||
_our_id = _application.lock()->discover_svcid(std::nullopt); | ||
} | ||
|
||
} // namespace homeblocks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#pragma once | ||
|
||
#include <atomic> | ||
#include <utility> | ||
|
||
#include <folly/concurrency/ConcurrentHashMap.h> | ||
#include "lib/homeblocks_impl.hpp" | ||
|
||
namespace homeblocks { | ||
|
||
class MemoryHomeBlocks : public HomeBlocksImpl { | ||
// VolumeManager | ||
VolumeManager::NullAsyncResult _create_volume(VolumeInfo&& vol_info) override; | ||
|
||
bool _get_stats(volume_id_t id, VolumeStats& stats) const override; | ||
void _get_volume_ids(std::vector< volume_id_t >& volume_ids) const override; | ||
|
||
HomeBlocksStats _get_stats() const override; | ||
|
||
public: | ||
MemoryHomeBlocks(std::weak_ptr< HomeBlocksApplication >&& application); | ||
~MemoryHomeBlocks() override = default; | ||
}; | ||
|
||
} // namespace homeblocks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <boost/uuid/uuid_io.hpp> | ||
|
||
#include "homeblocks_impl.hpp" | ||
|
||
namespace homeblocks { | ||
|
||
std::shared_ptr< VolumeManager > HomeBlocksImpl::volume_manager() { return shared_from_this(); } | ||
|
||
VolumeManager::NullAsyncResult HomeBlocksImpl::create_volume(VolumeInfo&& vol_info) { | ||
LOGI("[vol={}] is of capacity [{}B]", boost::uuids::to_string(vol_info.id), vol_info.size_bytes); | ||
return _create_volume(std::move(vol_info)); | ||
} | ||
|
||
bool HomeBlocksImpl::get_stats(volume_id_t id, VolumeStats& stats) const { return _get_stats(id, stats); } | ||
void HomeBlocksImpl::get_volume_ids(std::vector< volume_id_t >& vol_ids) const { return _get_volume_ids(vol_ids); } | ||
|
||
} // namespace homeobject |