slight backend refactor, splitting it up
This commit is contained in:
parent
18d2888e34
commit
e5b3546292
@ -33,13 +33,13 @@ FilesystemStorage::FilesystemStorage(
|
|||||||
ObjectStore2& os,
|
ObjectStore2& os,
|
||||||
std::string_view storage_path,
|
std::string_view storage_path,
|
||||||
MetaFileType mft_new
|
MetaFileType mft_new
|
||||||
) : StorageBackendI::StorageBackendI(os), _storage_path(storage_path), _mft_new(mft_new) {
|
) : _os(os), _storage_path(storage_path), _mft_new(mft_new) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FilesystemStorage::~FilesystemStorage(void) {
|
FilesystemStorage::~FilesystemStorage(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectHandle FilesystemStorage::newObject(ByteSpan id) {
|
ObjectHandle FilesystemStorage::newObject(ByteSpan id, bool throw_construct) {
|
||||||
{ // first check if id is already used (TODO: solve the multi obj/backend problem)
|
{ // first check if id is already used (TODO: solve the multi obj/backend problem)
|
||||||
auto exising_oh = _os.getOneObjectByID(id);
|
auto exising_oh = _os.getOneObjectByID(id);
|
||||||
if (static_cast<bool>(exising_oh)) {
|
if (static_cast<bool>(exising_oh)) {
|
||||||
@ -74,7 +74,8 @@ ObjectHandle FilesystemStorage::newObject(ByteSpan id) {
|
|||||||
|
|
||||||
ObjectHandle oh{_os.registry(), _os.registry().create()};
|
ObjectHandle oh{_os.registry(), _os.registry().create()};
|
||||||
|
|
||||||
oh.emplace<ObjComp::Ephemeral::Backend>(this);
|
oh.emplace<ObjComp::Ephemeral::BackendMeta>(this);
|
||||||
|
oh.emplace<ObjComp::Ephemeral::BackendAtomic>(this);
|
||||||
oh.emplace<ObjComp::ID>(std::vector<uint8_t>{id});
|
oh.emplace<ObjComp::ID>(std::vector<uint8_t>{id});
|
||||||
oh.emplace<ObjComp::Ephemeral::FilePath>(object_file_path.generic_u8string());
|
oh.emplace<ObjComp::Ephemeral::FilePath>(object_file_path.generic_u8string());
|
||||||
oh.emplace<ObjComp::Ephemeral::MetaFileType>(_mft_new);
|
oh.emplace<ObjComp::Ephemeral::MetaFileType>(_mft_new);
|
||||||
@ -87,8 +88,10 @@ ObjectHandle FilesystemStorage::newObject(ByteSpan id) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// while new metadata might be created here, making sure the file could be created is more important
|
if (throw_construct) {
|
||||||
_os.throwEventConstruct(oh);
|
// while new metadata might be created here, making sure the file could be created is more important
|
||||||
|
_os.throwEventConstruct(oh);
|
||||||
|
}
|
||||||
|
|
||||||
return oh;
|
return oh;
|
||||||
}
|
}
|
||||||
@ -579,7 +582,8 @@ size_t FilesystemStorage::scanPath(std::string_view path) {
|
|||||||
// TODO: existing fragment file
|
// TODO: existing fragment file
|
||||||
//newFragmentFile();
|
//newFragmentFile();
|
||||||
ObjectHandle oh{_os.registry(), _os.registry().create()};
|
ObjectHandle oh{_os.registry(), _os.registry().create()};
|
||||||
oh.emplace<ObjComp::Ephemeral::Backend>(this);
|
oh.emplace<ObjComp::Ephemeral::BackendMeta>(this);
|
||||||
|
oh.emplace<ObjComp::Ephemeral::BackendAtomic>(this);
|
||||||
oh.emplace<ObjComp::ID>(hex2bin(it.id_str));
|
oh.emplace<ObjComp::ID>(hex2bin(it.id_str));
|
||||||
oh.emplace<ObjComp::Ephemeral::MetaFileType>(mft);
|
oh.emplace<ObjComp::Ephemeral::MetaFileType>(mft);
|
||||||
oh.emplace<ObjComp::Ephemeral::MetaEncryptionType>(meta_enc);
|
oh.emplace<ObjComp::Ephemeral::MetaEncryptionType>(meta_enc);
|
||||||
|
@ -7,7 +7,11 @@
|
|||||||
|
|
||||||
namespace Backends {
|
namespace Backends {
|
||||||
|
|
||||||
struct FilesystemStorage : public StorageBackendI {
|
// TODO: rename to atomic filesystem store?
|
||||||
|
// provides meta and atomic read/write on your filesystem
|
||||||
|
struct FilesystemStorage : public StorageBackendIMeta, public StorageBackendIAtomic {
|
||||||
|
ObjectStore2& _os;
|
||||||
|
|
||||||
FilesystemStorage(
|
FilesystemStorage(
|
||||||
ObjectStore2& os,
|
ObjectStore2& os,
|
||||||
std::string_view storage_path = "test_obj_store",
|
std::string_view storage_path = "test_obj_store",
|
||||||
@ -22,14 +26,11 @@ struct FilesystemStorage : public StorageBackendI {
|
|||||||
// meta file type for new objects
|
// meta file type for new objects
|
||||||
MetaFileType _mft_new {MetaFileType::BINARY_MSGPACK};
|
MetaFileType _mft_new {MetaFileType::BINARY_MSGPACK};
|
||||||
|
|
||||||
ObjectHandle newObject(ByteSpan id) override;
|
ObjectHandle newObject(ByteSpan id, bool throw_construct = true) override;
|
||||||
|
|
||||||
bool write(Object o, std::function<write_to_storage_fetch_data_cb>& data_cb) override;
|
bool write(Object o, std::function<write_to_storage_fetch_data_cb>& data_cb) override;
|
||||||
bool read(Object o, std::function<read_from_storage_put_data_cb>& data_cb) override;
|
bool read(Object o, std::function<read_from_storage_put_data_cb>& data_cb) override;
|
||||||
|
|
||||||
//// convenience function
|
|
||||||
//nlohmann::json loadFromStorageNJ(FragmentID fid);
|
|
||||||
|
|
||||||
void scanAsync(void);
|
void scanAsync(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -8,7 +8,9 @@ using ObjectRegistry = entt::basic_registry<Object>;
|
|||||||
using ObjectHandle = entt::basic_handle<ObjectRegistry>;
|
using ObjectHandle = entt::basic_handle<ObjectRegistry>;
|
||||||
|
|
||||||
// fwd
|
// fwd
|
||||||
struct StorageBackendI;
|
struct StorageBackendIMeta;
|
||||||
|
struct StorageBackendIAtomic;
|
||||||
|
struct StorageBackendIFile2;
|
||||||
struct ObjectStore2;
|
struct ObjectStore2;
|
||||||
struct File2I;
|
struct File2I;
|
||||||
|
|
||||||
|
@ -39,9 +39,14 @@ namespace ObjectStore::Components {
|
|||||||
Compression comp {Compression::NONE};
|
Compression comp {Compression::NONE};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Backend {
|
struct BackendMeta {
|
||||||
// TODO: shared_ptr instead??
|
StorageBackendIMeta* ptr;
|
||||||
StorageBackendI* ptr;
|
};
|
||||||
|
struct BackendAtomic {
|
||||||
|
StorageBackendIAtomic* ptr;
|
||||||
|
};
|
||||||
|
struct BackendFile2 {
|
||||||
|
StorageBackendIFile2* ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// excluded from file meta
|
// excluded from file meta
|
||||||
|
@ -25,7 +25,9 @@ DEFINE_COMP_ID(ObjComp::DataCompressionType)
|
|||||||
DEFINE_COMP_ID(ObjComp::Ephemeral::MetaFileType)
|
DEFINE_COMP_ID(ObjComp::Ephemeral::MetaFileType)
|
||||||
DEFINE_COMP_ID(ObjComp::Ephemeral::MetaEncryptionType)
|
DEFINE_COMP_ID(ObjComp::Ephemeral::MetaEncryptionType)
|
||||||
DEFINE_COMP_ID(ObjComp::Ephemeral::MetaCompressionType)
|
DEFINE_COMP_ID(ObjComp::Ephemeral::MetaCompressionType)
|
||||||
DEFINE_COMP_ID(ObjComp::Ephemeral::Backend)
|
DEFINE_COMP_ID(ObjComp::Ephemeral::BackendMeta)
|
||||||
|
DEFINE_COMP_ID(ObjComp::Ephemeral::BackendAtomic)
|
||||||
|
DEFINE_COMP_ID(ObjComp::Ephemeral::BackendFile2)
|
||||||
DEFINE_COMP_ID(ObjComp::Ephemeral::FilePath)
|
DEFINE_COMP_ID(ObjComp::Ephemeral::FilePath)
|
||||||
DEFINE_COMP_ID(ObjComp::Ephemeral::DirtyTag) // ??
|
DEFINE_COMP_ID(ObjComp::Ephemeral::DirtyTag) // ??
|
||||||
|
|
||||||
|
@ -51,19 +51,7 @@ static bool deserl_json_data_comp_type(ObjectHandle oh, const nlohmann::json& in
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageBackendI::StorageBackendI(ObjectStore2& os) : _os(os) {
|
bool StorageBackendIAtomic::write(Object o, const ByteSpan data) {
|
||||||
}
|
|
||||||
|
|
||||||
ObjectHandle StorageBackendI::newObject(ByteSpan) {
|
|
||||||
//return {_os.registry(), entt::null};
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StorageBackendI::write(Object, std::function<write_to_storage_fetch_data_cb>&) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StorageBackendI::write(Object o, const ByteSpan data) {
|
|
||||||
std::function<write_to_storage_fetch_data_cb> fn_cb = [read = 0ull, data](uint8_t* request_buffer, uint64_t buffer_size) mutable -> uint64_t {
|
std::function<write_to_storage_fetch_data_cb> fn_cb = [read = 0ull, data](uint8_t* request_buffer, uint64_t buffer_size) mutable -> uint64_t {
|
||||||
uint64_t i = 0;
|
uint64_t i = 0;
|
||||||
for (; i+read < data.size && i < buffer_size; i++) {
|
for (; i+read < data.size && i < buffer_size; i++) {
|
||||||
@ -76,14 +64,6 @@ bool StorageBackendI::write(Object o, const ByteSpan data) {
|
|||||||
return write(o, fn_cb);
|
return write(o, fn_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StorageBackendI::read(Object, std::function<read_from_storage_put_data_cb>&) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<File2I> StorageBackendI::file2(Object o, FILE2_FLAGS flags) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectStore2::ObjectStore2(void) {
|
ObjectStore2::ObjectStore2(void) {
|
||||||
// HACK: set them up independently
|
// HACK: set them up independently
|
||||||
auto& sjc = _reg.ctx().emplace<SerializerJsonCallbacks<Object>>();
|
auto& sjc = _reg.ctx().emplace<SerializerJsonCallbacks<Object>>();
|
||||||
|
@ -8,24 +8,39 @@
|
|||||||
#include <entt/entity/registry.hpp>
|
#include <entt/entity/registry.hpp>
|
||||||
#include <entt/entity/handle.hpp>
|
#include <entt/entity/handle.hpp>
|
||||||
|
|
||||||
struct StorageBackendI {
|
// the different backend components
|
||||||
// OR or OS ?
|
// depending on what a backend (or composed backends) provide
|
||||||
ObjectStore2& _os;
|
// different component (pointers) might be provided
|
||||||
|
|
||||||
StorageBackendI(ObjectStore2& os);
|
// provides metadata storage(?)
|
||||||
|
struct StorageBackendIMeta {
|
||||||
|
virtual ~StorageBackendIMeta(void) = default;
|
||||||
|
virtual ObjectHandle newObject(ByteSpan id, bool throw_construct = true) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// default impl fails, acting like a read only store
|
// provides atomic-ish read write
|
||||||
virtual ObjectHandle newObject(ByteSpan id);
|
// simplest backend strategy to implement data encryption for
|
||||||
|
//
|
||||||
|
// collides with file backend and implementers providing both need to
|
||||||
|
// orchestrate access.
|
||||||
|
struct StorageBackendIAtomic {
|
||||||
|
using write_to_storage_fetch_data_cb = uint64_t(uint8_t* request_buffer, uint64_t buffer_size);
|
||||||
|
using read_from_storage_put_data_cb = void(const ByteSpan buffer);
|
||||||
|
|
||||||
|
virtual ~StorageBackendIAtomic(void) = default;
|
||||||
|
|
||||||
|
// calls data_cb with a buffer to be filled in, cb returns actual count of data. if returned < max, its the last buffer.
|
||||||
|
|
||||||
// ========== write object to storage (atomic-ish) ==========
|
// ========== write object to storage (atomic-ish) ==========
|
||||||
using write_to_storage_fetch_data_cb = uint64_t(uint8_t* request_buffer, uint64_t buffer_size);
|
virtual bool write(Object o, std::function<write_to_storage_fetch_data_cb>& data_cb) = 0;
|
||||||
// calls data_cb with a buffer to be filled in, cb returns actual count of data. if returned < max, its the last buffer.
|
bool write(Object o, const ByteSpan data); // helper, calls cb variant internally
|
||||||
virtual bool write(Object o, std::function<write_to_storage_fetch_data_cb>& data_cb);
|
|
||||||
bool write(Object o, const ByteSpan data);
|
|
||||||
|
|
||||||
// ========== read object from storage (atomic-ish) ==========
|
// ========== read object from storage (atomic-ish) ==========
|
||||||
using read_from_storage_put_data_cb = void(const ByteSpan buffer);
|
virtual bool read(Object o, std::function<read_from_storage_put_data_cb>& data_cb) = 0;
|
||||||
virtual bool read(Object o, std::function<read_from_storage_put_data_cb>& data_cb);
|
};
|
||||||
|
|
||||||
|
struct StorageBackendIFile2 {
|
||||||
|
virtual ~StorageBackendIFile2(void) = default;
|
||||||
|
|
||||||
// ========== File2 interop ==========
|
// ========== File2 interop ==========
|
||||||
enum FILE2_FLAGS : uint32_t {
|
enum FILE2_FLAGS : uint32_t {
|
||||||
@ -43,7 +58,7 @@ struct StorageBackendI {
|
|||||||
// TODO: stronger requirements
|
// TODO: stronger requirements
|
||||||
// the backend might decide to not support writing using file2, if it's eg. zstd compressed
|
// the backend might decide to not support writing using file2, if it's eg. zstd compressed
|
||||||
// backends might only support a single file2 instance per object!
|
// backends might only support a single file2 instance per object!
|
||||||
virtual std::unique_ptr<File2I> file2(Object o, FILE2_FLAGS flags); // default does nothing
|
virtual std::unique_ptr<File2I> file2(Object o, FILE2_FLAGS flags) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ObjectStore::Events {
|
namespace ObjectStore::Events {
|
||||||
@ -80,7 +95,7 @@ struct ObjectStoreEventI {
|
|||||||
using ObjectStoreEventProviderI = EventProviderI<ObjectStoreEventI>;
|
using ObjectStoreEventProviderI = EventProviderI<ObjectStoreEventI>;
|
||||||
|
|
||||||
struct ObjectStore2 : public ObjectStoreEventProviderI {
|
struct ObjectStore2 : public ObjectStoreEventProviderI {
|
||||||
static constexpr const char* version {"3"};
|
static constexpr const char* version {"4"};
|
||||||
|
|
||||||
ObjectRegistry _reg;
|
ObjectRegistry _reg;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user