Skip to content

Commit

Permalink
Start scaffolding.
Browse files Browse the repository at this point in the history
  • Loading branch information
szmyd committed Jul 31, 2024
1 parent d45e87e commit 9848178
Show file tree
Hide file tree
Showing 11 changed files with 319 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required (VERSION 3.11)
project (homeobject LANGUAGES CXX)
project (homeblocks LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)

Expand Down
25 changes: 24 additions & 1 deletion src/include/homeblocks/common.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#pragma once

#include <boost/uuid/uuid.hpp>
#include <folly/Expected.h>
#include <folly/Unit.h>
#include <folly/futures/Future.h>
#include <sisl/logging/logging.h>

SISL_LOGGING_DECL(homeblocks);
Expand All @@ -16,4 +20,23 @@ constexpr uint64_t Mi = Ki * Ki;
constexpr uint64_t Gi = Ki * Mi;
#endif

namespace homeblocks {} // namespace homeblocks
namespace homeblocks {

using peer_id_t = boost::uuids::uuid;
using volume_id_t = boost::uuids::uuid;

template < class E >
class Manager {
public:
template < typename T >
using Result = folly::Expected< T, E >;
template < typename T >
using AsyncResult = folly::SemiFuture< Result< T > >;

using NullResult = Result< folly::Unit >;
using NullAsyncResult = AsyncResult< folly::Unit >;

virtual ~Manager() = default;
};

} // namespace homeblocks
64 changes: 63 additions & 1 deletion src/include/homeblocks/homeblocks.hpp
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
62 changes: 62 additions & 0 deletions src/include/homeblocks/volume_manager.hpp
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
1 change: 1 addition & 0 deletions src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ add_flags("-Wno-unused-parameter")
add_library(${PROJECT_NAME}_core OBJECT)
target_sources(${PROJECT_NAME}_core PRIVATE
homeblocks_impl.cpp
volume_manager.cpp
)
target_link_libraries(${PROJECT_NAME}_core
${COMMON_DEPS}
Expand Down
20 changes: 18 additions & 2 deletions src/lib/homeblocks_impl.cpp
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
92 changes: 92 additions & 0 deletions src/lib/homeblocks_impl.hpp
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
1 change: 1 addition & 0 deletions src/lib/memory_backend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ cmake_minimum_required (VERSION 3.11)

add_library ("${PROJECT_NAME}_memory")
target_sources("${PROJECT_NAME}_memory" PRIVATE
mem_homeblocks.cpp
$<TARGET_OBJECTS:${PROJECT_NAME}_core>
)
target_link_libraries("${PROJECT_NAME}_memory"
Expand Down
15 changes: 15 additions & 0 deletions src/lib/memory_backend/mem_homeblocks.cpp
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
25 changes: 25 additions & 0 deletions src/lib/memory_backend/mem_homeblocks.hpp
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
17 changes: 17 additions & 0 deletions src/lib/volume_manager.cpp
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

0 comments on commit 9848178

Please sign in to comment.