diff --git a/Src/Client/ResourceCache.cpp b/Src/Client/ResourceCache.cpp index a815a42..b6c1622 100644 --- a/Src/Client/ResourceCache.cpp +++ b/Src/Client/ResourceCache.cpp @@ -156,7 +156,7 @@ std::pair CacheDatabase::getAllHash() { return {out, readed}; } -void CacheDatabase::updateTimeFor(HASH hash) { +void CacheDatabase::updateTimeFor(Hash_t hash) { sqlite3_bind_blob(STMT_UPDATE_TIME, 1, (const void*) hash.data(), 32, SQLITE_STATIC); sqlite3_bind_int(STMT_UPDATE_TIME, 2, time(nullptr)); if(sqlite3_step(STMT_UPDATE_TIME) != SQLITE_DONE) { @@ -167,7 +167,7 @@ void CacheDatabase::updateTimeFor(HASH hash) { sqlite3_reset(STMT_UPDATE_TIME); } -void CacheDatabase::insert(HASH hash, size_t size) { +void CacheDatabase::insert(Hash_t hash, size_t size) { assert(size < (size_t(1) << 31)-1 && size > 0); sqlite3_bind_blob(STMT_INSERT, 1, (const void*) hash.data(), 32, SQLITE_STATIC); @@ -181,8 +181,8 @@ void CacheDatabase::insert(HASH hash, size_t size) { sqlite3_reset(STMT_INSERT); } -std::vector CacheDatabase::findExcessHashes(size_t bytesToFree, int timeBefore = time(nullptr)-604800) { - std::vector out; +std::vector CacheDatabase::findExcessHashes(size_t bytesToFree, int timeBefore = time(nullptr)-604800) { + std::vector out; size_t removed = 0; sqlite3_bind_int(STMT_OLD, 1, timeBefore); @@ -197,7 +197,7 @@ std::vector CacheDatabase::findExcessHashes(size_t bytesToF const uint8_t *hash = (const uint8_t*) sqlite3_column_blob(STMT_OLD, 0); removed += sqlite3_column_int(STMT_OLD, 1); - HASH obj; + Hash_t obj; for(int iter = 0; iter < 32; iter++) obj[iter] = hash[iter]; @@ -221,7 +221,7 @@ std::vector CacheDatabase::findExcessHashes(size_t bytesToF } const uint8_t *hash = (const uint8_t*) sqlite3_column_blob(STMT_TO_FREE, 0); - HASH obj; + Hash_t obj; for(int iter = 0; iter < 32; iter++) obj[iter] = hash[iter]; @@ -232,7 +232,7 @@ std::vector CacheDatabase::findExcessHashes(size_t bytesToF return out; } -void CacheDatabase::remove(HASH hash) { +void CacheDatabase::remove(Hash_t hash) { sqlite3_bind_blob(STMT_REMOVE, 1, (const void*) hash.data(), 32, SQLITE_STATIC); if(sqlite3_step(STMT_REMOVE) != SQLITE_DONE) { sqlite3_reset(STMT_REMOVE); @@ -242,7 +242,7 @@ void CacheDatabase::remove(HASH hash) { sqlite3_reset(STMT_REMOVE); } -std::string CacheDatabase::hashToString(HASH hash) { +std::string CacheDatabase::hashToString(Hash_t hash) { std::string text; text.reserve(64); @@ -263,125 +263,41 @@ std::string CacheDatabase::hashToString(HASH hash) { return text; } -int CacheDatabase::hexCharToInt(char c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'a' && c <= 'f') return c - 'a' + 10; - throw std::invalid_argument("Invalid hexadecimal character"); +// int CacheDatabase::hexCharToInt(char c) { +// if (c >= '0' && c <= '9') return c - '0'; +// if (c >= 'a' && c <= 'f') return c - 'a' + 10; +// throw std::invalid_argument("Invalid hexadecimal character"); +// } + +// Hash_t CacheDatabase::stringToHash(const std::string_view view) { +// if (view.size() != 64) +// throw std::invalid_argument("Hex string must be exactly 64 characters long"); + +// Hash_t hash; + +// for (size_t i = 0; i < 32; ++i) { +// size_t offset = 62 - i * 2; +// int high = hexCharToInt(view[offset]); +// int low = hexCharToInt(view[offset + 1]); +// hash[i] = (high << 4) | low; +// } + +// return hash; +// } + +coro<> ResourceHandler::asyncDestructor() { + assert(NeedShutdown); // Нормальный shutdown должен быть вызван + co_await IAsyncDestructible::asyncDestructor(); } -CacheDatabase::HASH CacheDatabase::stringToHash(const std::string_view view) { - if (view.size() != 64) - throw std::invalid_argument("Hex string must be exactly 64 characters long"); - - HASH hash; - - for (size_t i = 0; i < 32; ++i) { - size_t offset = 62 - i * 2; - int high = hexCharToInt(view[offset]); - int low = hexCharToInt(view[offset + 1]); - hash[i] = (high << 4) | low; - } - - return hash; -} - -CacheHandler::CacheHandler(boost::asio::io_context &ioc, const fs::path &cachePath, - size_t maxCacheDirectorySize, size_t maxLifeTime) - : IAsyncDestructible(ioc), Path(cachePath), DB(Path), - MaxCacheDirectorySize(maxCacheDirectorySize), MaxLifeTime(maxLifeTime) -{ -} - -CacheHandler::~CacheHandler() = default; - -std::pair CacheHandler::getAll() { - return DB.getAllHash(); -} - -size_t CacheHandler::getCacheSize() { - return DB.getCacheSize(); -} - -coro<> CacheHandlerBasic::asyncDestructor() { - NeedShutdown = true; - co_await CacheHandler::asyncDestructor(); -} - -void CacheHandlerBasic::readThread(AsyncUseControl::Lock lock) { - LOG.info() << "Поток чтения запущен"; - - while(!NeedShutdown) { - if(ReadQueue.get_read().empty()) - goto wait; - else { - auto lock = ReadQueue.lock(); - if(lock->empty()) - goto wait; - - CacheDatabase::HASH hash = lock->front(); - lock->pop(); - lock.unlock(); - - std::string name = CacheDatabase::hashToString(hash); - fs::path path = Path / name.substr(0, 2) / name.substr(2, 2) / name.substr(4); - - std::shared_ptr data; - - { - auto lock_wc = WriteCache.lock(); - auto iter = lock_wc->begin(); - while(iter != lock_wc->end()) { - if(iter->first == hash) { - // Копируем - data = std::make_shared(*iter->second); - break; - } - } - } - - if(!data) { - data = std::make_shared(); - - try { - std::ifstream fd(path, std::ios::binary | std::ios::ate); - if (!fd.is_open()) - MAKE_ERROR("!is_open(): " << fd.exceptions()); - - if (fd.fail()) - MAKE_ERROR("fail(): " << fd.exceptions()); - - std::ifstream::pos_type size = fd.tellg(); - fd.seekg(0, std::ios::beg); - data->resize(size); - fd.read(data->data(), size); - - if (!fd.good()) - MAKE_ERROR("!good(): " << fd.exceptions()); - } catch(const std::exception &exc) { - LOG.error() << "Не удалось считать ресурс " << path.c_str() << ": " << exc.what(); - } - } - - ReadedQueue.lock()->emplace_back(hash, std::move(data)); - continue; - } - - wait: - TOS::Time::sleep3(20); - } - - LOG.info() << "Поток чтения остановлен"; - lock.unlock(); -} - -void CacheHandlerBasic::readWriteThread(AsyncUseControl::Lock lock) { +void ResourceHandler::readWriteThread(AsyncUseControl::Lock lock) { LOG.info() << "Поток чтения/записи запущен"; while(!NeedShutdown || !WriteQueue.get_read().empty()) { if(!ReadQueue.get_read().empty()) { auto lock = ReadQueue.lock(); if(!lock->empty()) { - CacheDatabase::HASH hash = lock->front(); + Hash_t hash = lock->front(); lock->pop(); lock.unlock(); @@ -448,11 +364,11 @@ void CacheHandlerBasic::readWriteThread(AsyncUseControl::Lock lock) { if(ssize_t free = ssize_t(MaxCacheDirectorySize)-DB.getCacheSize(); free < task.Data->size()) { // Недостаточно места, сколько необходимо освободить с запасом ssize_t need = task.Data->size()-free + 64*1024*1024; - std::vector hashes = DB.findExcessHashes(need, time(nullptr)-MaxLifeTime); + std::vector hashes = DB.findExcessHashes(need, time(nullptr)-MaxLifeTime); LOG.warn() << "Удаление устаревшего кеша в количестве " << hashes.size() << "..."; - for(CacheDatabase::HASH hash : hashes) { + for(Hash_t hash : hashes) { std::string name = CacheDatabase::hashToString(hash); fs::path path = Path / name.substr(0, 2) / name.substr(2, 2) / name.substr(4); DB.remove(hash); @@ -496,80 +412,46 @@ void CacheHandlerBasic::readWriteThread(AsyncUseControl::Lock lock) { lock.unlock(); } -CacheHandlerBasic::CacheHandlerBasic(boost::asio::io_context &ioc, const fs::path &cachePath, +ResourceHandler::ResourceHandler(boost::asio::io_context &ioc, const fs::path &cachePath, size_t maxCacheDirectorySize, size_t maxLifeTime) - : CacheHandler(ioc, cachePath, maxCacheDirectorySize, maxLifeTime), - ReadThread(&CacheHandlerBasic::readThread, this, AUC.use()), - ReadWriteThread(&CacheHandlerBasic::readWriteThread, this, AUC.use()) + : IAsyncDestructible(ioc), + OffThread(&ResourceHandler::readWriteThread, this, AUC.use()) { LOG.info() << "Инициализировано хранилище кеша: " << cachePath.c_str(); } -CacheHandlerBasic::~CacheHandlerBasic() { - ReadThread.join(); - ReadWriteThread.join(); - LOG.info() << "ДеИнициализировано хранилище кеша: " << Path.c_str(); -} -void CacheHandlerBasic::pushWrite(std::string &&data, CacheDatabase::HASH hash) { - std::shared_ptr dat = std::make_shared(std::move(data)); - WriteCache.lock()->push_back({hash, dat}); - WriteQueue.lock()->push({hash, dat}); -} - -void CacheHandlerBasic::pushRead(CacheDatabase::HASH hash) { - ReadQueue.lock()->push(hash); -} - -std::vector> CacheHandlerBasic::pullReads() { - std::vector data; - - { - auto lock = ReadedQueue.lock(); - data = std::move(*lock); - } - - std::vector> out; - out.reserve(data.size()); - - for(auto &value : data) { - out.emplace_back(value.Hash, std::move(*value.Data)); - } - - return out; -} - -void CacheHandlerBasic::updateParams(size_t maxLifeTime, size_t maxCacheDirectorySize) { - MaxLifeTime = maxLifeTime; +// void ResourceHandler::updateParams(size_t maxLifeTime, size_t maxCacheDirectorySize) { +// MaxLifeTime = maxLifeTime; - if(MaxCacheDirectorySize != maxCacheDirectorySize) { - MaxCacheDirectorySize = maxCacheDirectorySize; +// if(MaxCacheDirectorySize != maxCacheDirectorySize) { +// MaxCacheDirectorySize = maxCacheDirectorySize; - size_t size = DB.getCacheSize(); - if(size > maxCacheDirectorySize) { - size_t needToFree = size-maxCacheDirectorySize+64*1024*1024; - try { - LOG.info() << "Начата вычистка кеша на сумму " << needToFree/1024/1024 << " Мб"; - std::vector hashes = DB.findExcessHashes(needToFree, time(nullptr)-MaxLifeTime); - LOG.warn() << "Удаление кеша в количестве " << hashes.size() << "..."; +// size_t size = DB.getCacheSize(); +// if(size > maxCacheDirectorySize) { +// size_t needToFree = size-maxCacheDirectorySize+64*1024*1024; +// try { +// LOG.info() << "Начата вычистка кеша на сумму " << needToFree/1024/1024 << " Мб"; +// std::vector hashes = DB.findExcessHashes(needToFree, time(nullptr)-MaxLifeTime); +// LOG.warn() << "Удаление кеша в количестве " << hashes.size() << "..."; - for(CacheDatabase::HASH hash : hashes) { - std::string name = CacheDatabase::hashToString(hash); - fs::path path = Path / name.substr(0, 2) / name.substr(2, 2) / name.substr(4); - DB.remove(hash); - fs::remove(path); +// for(Hash_t hash : hashes) { +// std::string name = CacheDatabase::hashToString(hash); +// fs::path path = Path / name.substr(0, 2) / name.substr(2, 2) / name.substr(4); +// DB.remove(hash); +// fs::remove(path); - fs::path up1 = path.parent_path(); - LOG.info() << "В директории " << up1.c_str() << " не осталось файлов, удаляем..."; - size_t count = std::distance(fs::directory_iterator(up1), fs::directory_iterator()); - if(count == 0) - fs::remove(up1); - } - } catch(const std::exception &exc) { - LOG.error() << "Не удалось очистить кеш до новой границы: " << exc.what(); - } - } - } -} +// fs::path up1 = path.parent_path(); +// LOG.info() << "В директории " << up1.c_str() << " не осталось файлов, удаляем..."; +// size_t count = std::distance(fs::directory_iterator(up1), fs::directory_iterator()); +// if(count == 0) +// fs::remove(up1); +// } +// } catch(const std::exception &exc) { +// LOG.error() << "Не удалось очистить кеш до новой границы: " << exc.what(); +// } +// } +// } +// } } \ No newline at end of file diff --git a/Src/Client/ResourceCache.hpp b/Src/Client/ResourceCache.hpp index 7d45f3b..0f9a910 100644 --- a/Src/Client/ResourceCache.hpp +++ b/Src/Client/ResourceCache.hpp @@ -1,7 +1,11 @@ #pragma once +#include "Common/Abstract.hpp" #include +#include #include +#include +#include #include #include #include @@ -10,6 +14,8 @@ #include #include #include +#include +#include namespace LV::Client { @@ -38,7 +44,7 @@ public: CacheDatabase(const CacheDatabase&) = delete; CacheDatabase(CacheDatabase&&) = delete; CacheDatabase& operator=(const CacheDatabase&) = delete; - CacheDatabase& operator=(CacheDatabase&&) = delete; + CacheDatabase& operator=(CacheDatabase&&) = delete; /* Выдаёт размер занимаемый всем хранимым кешем @@ -50,134 +56,141 @@ public: /* Создаёт линейный массив в котором подряд указаны все хэш суммы в бинарном виде и возвращает их количество */ - std::pair getAllHash(); - - using HASH = std::array; + // std::pair getAllHash(); /* Обновляет время использования кеша */ - void updateTimeFor(HASH hash); + void updateTimeFor(Hash_t hash); /* Добавляет запись */ - void insert(HASH hash, size_t size); + void insert(Hash_t hash, size_t size); /* Выдаёт хэши на удаление по размеру в сумме больше bytesToFree. Сначала удаляется старьё, потом по приоритету дата использования + размер */ - std::vector findExcessHashes(size_t bytesToFree, int timeBefore); + std::vector findExcessHashes(size_t bytesToFree, int timeBefore); /* Удаление записи */ - void remove(HASH hash); + void remove(Hash_t hash); - static std::string hashToString(HASH hash); + static std::string hashToString(Hash_t hash); static int hexCharToInt(char c); - static HASH stringToHash(const std::string_view view); + static Hash_t stringToHash(const std::string_view view); }; /* - Читает и пишет ресурсы на диск - В приоритете чтение + Менеджер предоставления ресурсов. Управляет ресурс паками + и хранением кешированных ресурсов сервера. + Интерфейс однопоточный. - Кодировки только на стороне сервера, на клиенте уже готовые данные - - NOT ThreadSafe + Обработка файлов в отдельном потоке */ -class CacheHandler : public IAsyncDestructible { -protected: - const fs::path Path; - CacheDatabase DB; - size_t MaxCacheDirectorySize; - size_t MaxLifeTime; - +class ResourceHandler : public IAsyncDestructible { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; -protected: - CacheHandler(boost::asio::io_context &ioc, const fs::path &cachePath, - size_t maxCacheDirectorySize, size_t maxLifeTime); - -public: - virtual ~CacheHandler(); - - // Добавить задачу на запись - virtual void pushWrite(std::string &&data, CacheDatabase::HASH hash) = 0; - - // Добавить задачу на чтение - virtual void pushRead(CacheDatabase::HASH hash) = 0; - - // Получить считанные данные - virtual std::vector> pullReads() = 0; - - // Получить список доступных ресурсов - std::pair getAll(); - - // Размер всего хранимого кеша - size_t getCacheSize(); - - // Обновить параметры хранилища - virtual void updateParams(size_t maxLifeTime, size_t maxCacheDirectorySize) = 0; -}; - -class CacheHandlerBasic : public CacheHandler { - Logger LOG = "CacheHandlerBasic"; - - struct DataTask { - CacheDatabase::HASH Hash; - std::shared_ptr Data; + struct ResourceKey { + Hash_t Hash; + EnumAssets Type; + std::string Domain, Key; }; - // Очередь задач на чтение - SpinlockObject> ReadQueue; - // Кэш данных, которые ещё не записались - SpinlockObject>>> WriteCache; - // Очередь записи данных на диск - SpinlockObject> WriteQueue; - // Список полностью считанных файлов - SpinlockObject> ReadedQueue; - bool NeedShutdown = false; - - std::thread ReadThread, ReadWriteThread; - -public: - using Ptr = std::shared_ptr; - -private: - virtual coro<> asyncDestructor() override; - - void readThread(AsyncUseControl::Lock lock); - - void readWriteThread(AsyncUseControl::Lock lock); - protected: - CacheHandlerBasic(boost::asio::io_context &ioc, const fs::path& cachePath, - size_t maxCacheDirectorySize, size_t maxLifeTime); + ResourceHandler(boost::asio::io_context &ioc, const fs::path &cachePath, + size_t maxCacheDatabaseSize, size_t maxLifeTime); public: - virtual ~CacheHandlerBasic(); - - static std::shared_ptr Create(asio::io_context &ioc, const fs::path& cachePath, + virtual ~ResourceHandler(); + static std::shared_ptr Create(asio::io_context &ioc, const fs::path& cachePath, size_t maxCacheDirectorySize = 8*1024*1024*1024ULL, size_t maxLifeTime = 7*24*60*60) { - return createShared(ioc, new CacheHandlerBasic(ioc, cachePath, maxCacheDirectorySize, maxLifeTime)); + return createShared(ioc, new ResourceHandler(ioc, cachePath, maxCacheDirectorySize, maxLifeTime)); } - virtual void pushWrite(std::string &&data, CacheDatabase::HASH hash) override; - virtual void pushRead(CacheDatabase::HASH hash) override; - virtual std::vector> pullReads() override; - virtual void updateParams(size_t maxLifeTime, size_t maxCacheDirectorySize) override; + // Добавить новый полученный с сервера ресурс + void pushResources(std::vector resources) { + WriteQueue.lock()->push_range(resources); + } + + // Добавить задачи на чтение + void pushReads(std::vector keys) { + ReadQueue.lock()->push_range(keys); + } + + // Получить считанные данные + std::vector>> pullReads() { + return std::move(*ReadyQueue.lock()); + } + + // Размер всего хранимого кеша + size_t getCacheSize() { + return DatabaseSize; + } + + // Обновить параметры хранилища кеша + void updateParams(size_t maxLifeTime, size_t maxCacheDirectorySize) { + auto lock = Changes.lock(); + lock->MaxLifeTime = maxLifeTime; + lock->MaxCacheDatabaseSize = maxCacheDirectorySize; + lock->MaxChange = true; + } + + // Установка путей до папок assets + void setResourcePacks(std::vector packsAssets) { + auto lock = Changes.lock(); + lock->Assets = std::move(packsAssets); + lock->AssetsChange = true; + } + + // Запуск процедуры проверки хешей всего хранимого кеша + void runFullDatabaseRecheck(std::move_only_function&& func) { + auto lock = Changes.lock(); + lock->OnRecheckEnd = std::move(func); + lock->FullRecheck = true; + } + + // Уведомление о завершении работы + void prepareShutdown() { + NeedShutdown = true; + } + + // После этого вызова уже нельзя будет обращатся ко внешним ресурсам + void shutdown() { + OffThread.join(); + } + +private: + Logger LOG = "Client>ResourceHandler"; + const fs::path CachePath; + volatile size_t DatabaseSize = 0; + + // Очередь задач на чтение + TOS::SpinlockObject> ReadQueue; + // Очередь на запись ресурсов + TOS::SpinlockObject> WriteQueue; + // Очередь на выдачу результатов чтения + TOS::SpinlockObject>>> ReadyQueue; + + struct Changes_t { + std::vector Assets; + volatile bool AssetsChange = false; + size_t MaxCacheDatabaseSize, MaxLifeTime; + volatile bool MaxChange = false; + std::optional> OnRecheckEnd; + volatile bool FullRecheck = false; + }; + + TOS::SpinlockObject Changes; + + bool NeedShutdown = false; + std::thread OffThread; + + void readWriteThread(AsyncUseControl::Lock lock); }; -#ifdef LUAVOX_HAVE_LIBURING - -class CacheHandlerUring : public CacheHandler { - -}; - -#endif - } \ No newline at end of file diff --git a/Src/Common/Abstract.cpp b/Src/Common/Abstract.cpp index ab0538f..b6aa1fd 100644 --- a/Src/Common/Abstract.cpp +++ b/Src/Common/Abstract.cpp @@ -1,7 +1,10 @@ #include "Abstract.hpp" #include "Common/Net.hpp" #include "TOSLib.hpp" +#include +#include #include "boost/json.hpp" +#include "sha2.hpp" #include #include #include @@ -16,6 +19,8 @@ namespace LV { +namespace fs = std::filesystem; + CompressedVoxels compressVoxels_byte(const std::vector& voxels) { std::u8string compressed; @@ -1970,4 +1975,49 @@ std::u8string PreparedModel::dump() const { return result.complite(); } +struct Resource::InlineMMap { + boost::interprocess::file_mapping MMap; + boost::interprocess::mapped_region Region; + Hash_t Hash; + + InlineMMap(fs::path path) + : MMap(path.c_str(), boost::interprocess::read_only), + Region(MMap, boost::interprocess::read_only) + { + Hash = sha2::sha256((const uint8_t*) Region.get_address(), Region.get_size()); + } + + const std::byte* data() const { return (const std::byte*) Region.get_address(); } + size_t size() const { return Region.get_size(); } +}; + +struct Resource::InlinePtr { + std::vector Data; + Hash_t Hash; + + InlinePtr(const uint8_t* data, size_t size) { + Data.resize(size); + std::copy(data, data+size, Data.data()); + Hash = sha2::sha256(data, size); + } + + const std::byte* data() const { return (const std::byte*) Data.data(); } + size_t size() const { return Data.size(); } +}; + + +Resource::Resource(fs::path path) + : In(std::make_shared>(InlineMMap(path))) +{} + +Resource::Resource(const uint8_t* data, size_t size) + : In(std::make_shared>(InlinePtr(data, size))) +{} + +const std::byte* Resource::data() const { assert(In); return std::visit([](auto& obj){ return obj.data(); }, *In); } +size_t Resource::size() const { assert(In); return std::visit([](auto& obj){ return obj.size(); }, *In); } +Hash_t Resource::hash() const { assert(In); return std::visit([](auto& obj){ return obj.Hash; }, *In); } + +auto Resource::operator<=>(const Resource&) const = default; + } \ No newline at end of file diff --git a/Src/Common/Abstract.hpp b/Src/Common/Abstract.hpp index 619a729..07975e1 100644 --- a/Src/Common/Abstract.hpp +++ b/Src/Common/Abstract.hpp @@ -691,6 +691,29 @@ inline std::pair parseDomainKey(const std::string& val } } + +struct Resource { +private: + struct InlineMMap; + struct InlinePtr; + + std::shared_ptr> In; + +public: + Resource(std::filesystem::path path); + Resource(const uint8_t* data, size_t size); + + Resource(const Resource&) = default; + Resource(Resource&&) = default; + Resource& operator=(const Resource&) = default; + Resource& operator=(Resource&&) = default; + auto operator<=>(const Resource&) const; + + const std::byte* data() const; + size_t size() const; + Hash_t hash() const; +}; + } diff --git a/Src/Server/AssetsManager.hpp b/Src/Server/AssetsManager.hpp index bc5baa3..6075f8e 100644 --- a/Src/Server/AssetsManager.hpp +++ b/Src/Server/AssetsManager.hpp @@ -3,11 +3,8 @@ #include "Common/Abstract.hpp" #include "TOSLib.hpp" #include "Common/Net.hpp" -#include "assets.hpp" #include "sha2.hpp" #include -#include -#include #include #include #include @@ -18,60 +15,6 @@ namespace LV::Server { namespace fs = std::filesystem; -struct Resource { -private: - struct InlineMMap { - boost::interprocess::file_mapping MMap; - boost::interprocess::mapped_region Region; - Hash_t Hash; - - InlineMMap(fs::path path) - : MMap(path.c_str(), boost::interprocess::read_only), - Region(MMap, boost::interprocess::read_only) - { - Hash = sha2::sha256((const uint8_t*) Region.get_address(), Region.get_size()); - } - - const std::byte* data() const { return (const std::byte*) Region.get_address(); } - size_t size() const { return Region.get_size(); } - }; - - struct InlinePtr { - std::vector Data; - Hash_t Hash; - - InlinePtr(const uint8_t* data, size_t size) { - Data.resize(size); - std::copy(data, data+size, Data.data()); - Hash = sha2::sha256(data, size); - } - - const std::byte* data() const { return (const std::byte*) Data.data(); } - size_t size() const { return Data.size(); } - }; - - std::shared_ptr> In; - -public: - Resource(fs::path path) - : In(std::make_shared>(InlineMMap(path))) - {} - - Resource(const uint8_t* data, size_t size) - : In(std::make_shared>(InlinePtr(data, size))) - {} - - Resource(const Resource&) = default; - Resource(Resource&&) = default; - Resource& operator=(const Resource&) = default; - Resource& operator=(Resource&&) = default; - bool operator<=>(const Resource&) const = default; - - const std::byte* data() const { return std::visit([](auto& obj){ return obj.data(); }, *In); } - size_t size() const { return std::visit([](auto& obj){ return obj.size(); }, *In); } - Hash_t hash() const { return std::visit([](auto& obj){ return obj.Hash; }, *In); } -}; - /* Используется для расчёта коллизии, если это необходимо.