diff --git a/src/fragment_store/backends/filesystem_storage.cpp b/src/fragment_store/backends/filesystem_storage.cpp index 64049bf..45bfe00 100644 --- a/src/fragment_store/backends/filesystem_storage.cpp +++ b/src/fragment_store/backends/filesystem_storage.cpp @@ -89,6 +89,59 @@ FilesystemStorage::FilesystemStorage(ObjectStore2& os, std::string_view storage_ FilesystemStorage::~FilesystemStorage(void) { } +ObjectHandle FilesystemStorage::newObject(MetaFileType mft, ByteSpan id) { + { // first check if id is already used (TODO: solve the multi obj/backend problem) + auto exising_oh = _os.getOneObjectByID(id); + if (static_cast(exising_oh)) { + return {}; + } + } + + std::filesystem::create_directories(_storage_path); + + if (!std::filesystem::is_directory(_storage_path)) { + std::cerr << "FS error: failed to create storage path dir '" << _storage_path << "'\n"; + return {}; + } + + const auto id_hex = bin2hex(id); + std::filesystem::path object_file_path; + + // TODO: refactor this magic somehow + if (id_hex.size() < 6) { + object_file_path = std::filesystem::path{_storage_path}/id_hex; + } else { + // use the first 2hex (1byte) as a subfolder + std::filesystem::create_directories(std::string{_storage_path} + id_hex.substr(0, 2)); + object_file_path = std::filesystem::path{std::string{_storage_path} + id_hex.substr(0, 2)} / id_hex.substr(2); + } + + if (std::filesystem::exists(object_file_path)) { + std::cerr << "FS error: object already exists in path '" << id_hex << "'\n"; + return {}; + } + + ObjectHandle oh{_os.registry(), _os.registry().create()}; + + oh.emplace(this); + oh.emplace(std::vector{id}); + oh.emplace(object_file_path.generic_u8string()); + oh.emplace(mft); + + // meta needs to be synced to file + std::function empty_data_cb = [](auto*, auto) -> uint64_t { return 0; }; + if (!write(oh, empty_data_cb)) { + std::cerr << "FS error: write failed while creating new object file\n"; + oh.destroy(); + return {}; + } + + // while new metadata might be created here, making sure the file could be created is more important + _os.throwEventConstruct(oh); + + return oh; +} + bool FilesystemStorage::write(Object o, std::function& data_cb) { auto& reg = _os.registry(); @@ -454,11 +507,10 @@ size_t FilesystemStorage::scanPath(std::string_view path) { // (merge into step 3 and do more error checking?) // TODO: properly handle duplicates, dups form different backends might be legit // important -#if 0 for (auto it = file_obj_list.begin(); it != file_obj_list.end();) { auto id = hex2bin(it->id_str); - auto fid = getFragmentByID(id); - if (_reg.valid(fid)) { + auto oh = _os.getOneObjectByID(ByteSpan{id}); + if (static_cast(oh)) { // pre exising (handle differently??) // check if store differs? it = file_obj_list.erase(it); @@ -466,7 +518,6 @@ size_t FilesystemStorage::scanPath(std::string_view path) { it++; } } -#endif std::vector scanned_objs; // step 3: parse meta and insert into reg of non preexising diff --git a/src/fragment_store/backends/filesystem_storage.hpp b/src/fragment_store/backends/filesystem_storage.hpp index dc0c803..17c1c48 100644 --- a/src/fragment_store/backends/filesystem_storage.hpp +++ b/src/fragment_store/backends/filesystem_storage.hpp @@ -1,5 +1,6 @@ #pragma once +#include "../types.hpp" #include "../object_store.hpp" namespace backend { @@ -9,8 +10,11 @@ struct FilesystemStorage : public StorageBackendI { ~FilesystemStorage(void); // TODO: fix the path for this specific fs? + // for now we assume a single storage path per backend (there can be multiple per type) std::string _storage_path; + ObjectHandle newObject(MetaFileType mft, ByteSpan id); + bool write(Object o, std::function& data_cb) override; bool read(Object o, std::function& data_cb) override; diff --git a/src/fragment_store/object_store.cpp b/src/fragment_store/object_store.cpp index 146f677..663d1f9 100644 --- a/src/fragment_store/object_store.cpp +++ b/src/fragment_store/object_store.cpp @@ -36,6 +36,18 @@ ObjectHandle ObjectStore2::objectHandle(const Object o) { return {_reg, o}; } +ObjectHandle ObjectStore2::getOneObjectByID(const ByteSpan id) { + // TODO: accelerate + // maybe keep it sorted and binary search? hash table lookup? + for (const auto& [obj, id_comp] : _reg.view().each()) { + if (id == ByteSpan{id_comp.v}) { + return {_reg, obj}; + } + } + + return {_reg, entt::null}; +} + void ObjectStore2::throwEventConstruct(const Object o) { std::cout << "OS debug: event construct " << entt::to_integral(o) << "\n"; dispatch( diff --git a/src/fragment_store/object_store.hpp b/src/fragment_store/object_store.hpp index 3ce56bb..6b48ade 100644 --- a/src/fragment_store/object_store.hpp +++ b/src/fragment_store/object_store.hpp @@ -83,6 +83,9 @@ struct ObjectStore2 : public ObjectStoreEventProviderI { ObjectRegistry& registry(void); ObjectHandle objectHandle(const Object o); + // TODO: properly think about multiple objects witht he same id / different backends + ObjectHandle getOneObjectByID(const ByteSpan id); + // sync? void throwEventConstruct(const Object o); diff --git a/src/tox_client.hpp b/src/tox_client.hpp index dc412b6..f09e5e0 100644 --- a/src/tox_client.hpp +++ b/src/tox_client.hpp @@ -48,4 +48,3 @@ class ToxClient : public ToxDefaultImpl, public ToxEventProviderBase { void saveToxProfile(void); }; -