#ifndef LIBPKG_DATA_STORAGE_PRIVATE_H #define LIBPKG_DATA_STORAGE_PRIVATE_H #include "./package.h" #include "../lmdb-safe/lmdb-reflective.hh" #include "../lmdb-safe/lmdb-safe.hh" #include "../lmdb-safe/lmdb-typed.hh" #include #include #include #include #include #include namespace LibPkg { using StorageID = std::uint32_t; template struct StorageCacheRef { using Storage = StorageType; explicit StorageCacheRef(const StorageType &relatedStorage, const std::shared_ptr &entry); explicit StorageCacheRef(const StorageType &relatedStorage, const std::string &entryName); bool operator==(const StorageCacheRef &other) const; const StorageType *relatedStorage = nullptr; const std::string *entryName; }; template inline StorageCacheRef::StorageCacheRef(const StorageType &relatedStorage, const std::shared_ptr &entry) : relatedStorage(&relatedStorage) , entryName(&entry->name) { } template inline StorageCacheRef::StorageCacheRef(const StorageType &relatedStorage, const std::string &entryName) : relatedStorage(&relatedStorage) , entryName(&entryName) { } template inline bool StorageCacheRef::operator==(const StorageCacheRef &other) const { return relatedStorage == other.relatedStorage && *entryName == *other.entryName; } template struct StorageCacheEntry { using Ref = StorageRefType; using Entry = EntryType; using Storage = typename Ref::Storage; explicit StorageCacheEntry(const StorageRefType &ref); StorageRefType ref; StorageID id; std::shared_ptr entry; }; template inline StorageCacheEntry::StorageCacheEntry(const StorageRefType &ref) : ref(ref) , id(0) { } template class StorageCacheEntries { public: using Ref = typename StorageEntryType::Ref; using Entry = typename StorageEntryType::Entry; using Storage = typename StorageEntryType::Storage; using StorageEntry = StorageEntryType; using EntryList = boost::multi_index::multi_index_container, boost::multi_index::hashed_unique, BOOST_MULTI_INDEX_MEMBER(StorageEntryType, Ref, ref)>>>; using iterator = typename EntryList::iterator; explicit StorageCacheEntries(std::size_t limit = 1000); StorageEntry &findOrCreate(const Ref &ref); void undo(); std::size_t erase(const Ref &ref); std::size_t clear(const Storage &storage); iterator begin(); iterator end(); private: EntryList m_entries; std::size_t m_limit; }; template inline StorageCacheEntries::StorageCacheEntries(std::size_t limit) : m_limit(limit) { } template inline void StorageCacheEntries::undo() { m_entries.pop_front(); } template inline std::size_t StorageCacheEntries::erase(const Ref &ref) { return m_entries.template get().erase(ref); } template inline auto StorageCacheEntries::begin() -> iterator { return m_entries.begin(); } template inline auto StorageCacheEntries::end() -> iterator { return m_entries.end(); } template struct StorageCache { using Entries = StorageEntriesType; using Entry = typename Entries::Entry; using Txn = TransactionType; using Storage = typename Entries::Storage; struct StoreResult { StorageID id = 0; bool updated = false; std::shared_ptr oldEntry; }; SpecType retrieve(Storage &storage, const std::string &entryName); StoreResult store(Storage &storage, const std::shared_ptr &entry, bool force); StoreResult store(Storage &storage, Txn &txn, const std::shared_ptr &entry); bool invalidate(Storage &storage, const std::string &entryName); void clear(Storage &storage); void clearCacheOnly(Storage &storage); private: Entries m_entries; std::mutex m_mutex; }; using PackageStorage = LMDBSafe::TypedDBI>; using DependencyStorage = LMDBSafe::TypedDBI>; using LibraryDependencyStorage = LMDBSafe::TypedDBI>; using PackageCacheRef = StorageCacheRef; using PackageCacheEntry = StorageCacheEntry; using PackageCacheEntries = StorageCacheEntries; using PackageCache = StorageCache; extern template struct StorageCacheRef; extern template struct StorageCacheEntry; extern template class StorageCacheEntries; extern template struct StorageCache; struct StorageDistribution { explicit StorageDistribution(const char *path, std::uint32_t maxDbs); std::unique_ptr forDatabase(std::string_view uniqueDatabaseName); private: std::shared_ptr m_env; PackageCache m_packageCache; }; inline std::unique_ptr StorageDistribution::forDatabase(std::string_view uniqueDatabaseName) { return std::make_unique(m_env, m_packageCache, uniqueDatabaseName); } struct DatabaseStorage { explicit DatabaseStorage(const std::shared_ptr &env, PackageCache &packageCache, std::string_view uniqueDatabaseName); PackageCache &packageCache; PackageStorage packages; DependencyStorage providedDeps; DependencyStorage requiredDeps; LibraryDependencyStorage providedLibs; LibraryDependencyStorage requiredLibs; private: std::shared_ptr m_env; }; std::size_t hash_value(const PackageCacheRef &ref); } // namespace LibPkg #endif // LIBPKG_DATA_STORAGE_PRIVATE_H