lmdb: Generalize caching to be able to use it for other types than packages
This commit is contained in:
parent
a8afccf081
commit
231571f2d1
|
@ -365,8 +365,8 @@ StorageID Database::updatePackage(const std::shared_ptr<Package> &package)
|
|||
if (!res.updated) {
|
||||
return res.id;
|
||||
}
|
||||
if (res.oldPackage) {
|
||||
removePackageDependencies(res.id, res.oldPackage);
|
||||
if (res.oldEntry) {
|
||||
removePackageDependencies(res.id, res.oldEntry);
|
||||
}
|
||||
addPackageDependencies(res.id, package);
|
||||
return res.id;
|
||||
|
@ -375,8 +375,8 @@ StorageID Database::updatePackage(const std::shared_ptr<Package> &package)
|
|||
StorageID Database::forceUpdatePackage(const std::shared_ptr<Package> &package)
|
||||
{
|
||||
const auto res = m_storage->packageCache.store(*m_storage, package, true);
|
||||
if (res.oldPackage) {
|
||||
removePackageDependencies(res.id, res.oldPackage);
|
||||
if (res.oldEntry) {
|
||||
removePackageDependencies(res.id, res.oldEntry);
|
||||
}
|
||||
addPackageDependencies(res.id, package);
|
||||
return res.id;
|
||||
|
@ -628,8 +628,8 @@ PackageUpdaterPrivate::PackageUpdaterPrivate(DatabaseStorage &storage)
|
|||
void PackageUpdaterPrivate::update(const PackageCache::StoreResult &res, const std::shared_ptr<Package> &package)
|
||||
{
|
||||
update(res.id, false, package);
|
||||
if (res.oldPackage) {
|
||||
update(res.id, true, res.oldPackage);
|
||||
if (res.oldEntry) {
|
||||
update(res.id, true, res.oldEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,102 +6,132 @@ using namespace CppUtilities;
|
|||
|
||||
namespace LibPkg {
|
||||
|
||||
StorageDistribution::StorageDistribution(const char *path, std::uint32_t maxDbs)
|
||||
template <typename StorageEntryType> auto StorageCacheEntries<StorageEntryType>::findOrCreate(const Ref &ref) -> StorageEntry &
|
||||
{
|
||||
m_env = LMDBSafe::getMDBEnv(path, MDB_NOSUBDIR, 0600, maxDbs);
|
||||
const auto &index = m_entries.template get<Ref>();
|
||||
if (auto i = index.find(ref); i != index.end()) {
|
||||
m_entries.relocate(m_entries.begin(), m_entries.template project<0>(i));
|
||||
return i.get_node()->value();
|
||||
}
|
||||
const auto [i, newItem] = m_entries.emplace_front(ref);
|
||||
if (!newItem) {
|
||||
m_entries.relocate(m_entries.begin(), i);
|
||||
} else if (m_entries.size() > m_limit) {
|
||||
m_entries.pop_back();
|
||||
}
|
||||
return i.get_node()->value();
|
||||
}
|
||||
|
||||
PackageSpec PackageCache::retrieve(DatabaseStorage &databaseStorage, const std::string &packageName)
|
||||
template <typename StorageEntryType> std::size_t StorageCacheEntries<StorageEntryType>::clear(const Storage &storage)
|
||||
{
|
||||
auto count = std::size_t();
|
||||
for (auto i = m_entries.begin(); i != m_entries.end();) {
|
||||
if (i->ref.relatedStorage == &storage) {
|
||||
i = m_entries.erase(i);
|
||||
++count;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename StorageEntriesType, typename TransactionType, typename SpecType>
|
||||
auto StorageCache<StorageEntriesType, TransactionType, SpecType>::retrieve(Storage &storage, const std::string &entryName) -> SpecType
|
||||
{
|
||||
// check for package in cache
|
||||
const auto ref = PackageCacheRef(databaseStorage, packageName);
|
||||
const auto ref = typename Entries::Ref(storage, entryName);
|
||||
const auto lock = std::unique_lock(m_mutex);
|
||||
auto &cacheEntry = m_packages.findOrCreate(ref);
|
||||
if (cacheEntry.package) {
|
||||
return PackageSpec(cacheEntry.id, cacheEntry.package);
|
||||
auto &cacheEntry = m_entries.findOrCreate(ref);
|
||||
if (cacheEntry.entry) {
|
||||
return PackageSpec(cacheEntry.id, cacheEntry.entry);
|
||||
}
|
||||
// check for package in storage, populate cache entry
|
||||
cacheEntry.package = std::make_unique<Package>();
|
||||
auto txn = databaseStorage.packages.getROTransaction();
|
||||
if ((cacheEntry.id = txn.get<0>(packageName, *cacheEntry.package))) {
|
||||
cacheEntry.ref.packageName = &cacheEntry.package->name;
|
||||
return PackageSpec(cacheEntry.id, cacheEntry.package);
|
||||
cacheEntry.entry = std::make_shared<Entry>();
|
||||
auto txn = storage.packages.getROTransaction();
|
||||
if ((cacheEntry.id = txn.template get<0>(entryName, *cacheEntry.entry))) {
|
||||
cacheEntry.ref.entryName = &cacheEntry.entry->name;
|
||||
return PackageSpec(cacheEntry.id, cacheEntry.entry);
|
||||
}
|
||||
m_packages.undo();
|
||||
return PackageSpec(0, std::shared_ptr<Package>());
|
||||
m_entries.undo();
|
||||
return PackageSpec(0, std::shared_ptr<Entry>());
|
||||
}
|
||||
|
||||
PackageCache::StoreResult PackageCache::store(DatabaseStorage &databaseStorage, const std::shared_ptr<Package> &package, bool force)
|
||||
template <typename StorageEntriesType, typename TransactionType, typename SpecType>
|
||||
auto StorageCache<StorageEntriesType, TransactionType, SpecType>::store(Storage &storage, const std::shared_ptr<Entry> &entry, bool force)
|
||||
-> StoreResult
|
||||
{
|
||||
// check for package in cache
|
||||
const auto ref = PackageCacheRef(databaseStorage, package->name);
|
||||
auto res = PackageCache::StoreResult();
|
||||
const auto ref = typename Entries::Ref(storage, entry->name);
|
||||
auto res = StorageCache::StoreResult();
|
||||
auto lock = std::unique_lock(m_mutex);
|
||||
auto &cacheEntry = m_packages.findOrCreate(ref);
|
||||
if (cacheEntry.package == package && !force) {
|
||||
auto &cacheEntry = m_entries.findOrCreate(ref);
|
||||
if (cacheEntry.entry == entry && !force) {
|
||||
// do nothing if cached package is the same as specified one
|
||||
res.id = cacheEntry.id;
|
||||
return res;
|
||||
} else if (cacheEntry.package) {
|
||||
} else if (cacheEntry.entry) {
|
||||
// retain certain information obtained from package contents if this is actually the same package as before
|
||||
package->addDepsAndProvidesFromOtherPackage(*(res.oldPackage = cacheEntry.package));
|
||||
entry->addDepsAndProvidesFromOtherPackage(*(res.oldEntry = cacheEntry.entry));
|
||||
} else {
|
||||
cacheEntry.package = std::make_shared<Package>();
|
||||
cacheEntry.entry = std::make_shared<Entry>();
|
||||
}
|
||||
// check for package in storage
|
||||
auto txn = databaseStorage.packages.getRWTransaction();
|
||||
if (!res.oldPackage && (cacheEntry.id = txn.get<0>(package->name, *cacheEntry.package))) {
|
||||
package->addDepsAndProvidesFromOtherPackage(*(res.oldPackage = cacheEntry.package));
|
||||
auto txn = storage.packages.getRWTransaction();
|
||||
if (!res.oldEntry && (cacheEntry.id = txn.template get<0>(entry->name, *cacheEntry.entry))) {
|
||||
entry->addDepsAndProvidesFromOtherPackage(*(res.oldEntry = cacheEntry.entry));
|
||||
}
|
||||
// update cache entry
|
||||
cacheEntry.ref.packageName = &package->name;
|
||||
cacheEntry.package = package;
|
||||
cacheEntry.ref.entryName = &entry->name;
|
||||
cacheEntry.entry = entry;
|
||||
// update package in storage
|
||||
cacheEntry.id = txn.put(*package, cacheEntry.id);
|
||||
cacheEntry.id = txn.put(*entry, cacheEntry.id);
|
||||
txn.commit();
|
||||
res.id = cacheEntry.id;
|
||||
res.updated = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
PackageCache::StoreResult PackageCache::store(
|
||||
DatabaseStorage &databaseStorage, PackageStorage::RWTransaction &txn, const std::shared_ptr<Package> &package)
|
||||
template <typename StorageEntriesType, typename TransactionType, typename SpecType>
|
||||
auto StorageCache<StorageEntriesType, TransactionType, SpecType>::store(Storage &storage, Txn &txn, const std::shared_ptr<Entry> &entry)
|
||||
-> StoreResult
|
||||
{
|
||||
// check for package in cache
|
||||
const auto ref = PackageCacheRef(databaseStorage, package->name);
|
||||
auto res = PackageCache::StoreResult();
|
||||
const auto ref = typename Entries::Ref(storage, entry->name);
|
||||
auto res = StorageCache::StoreResult();
|
||||
auto lock = std::unique_lock(m_mutex);
|
||||
auto &cacheEntry = m_packages.findOrCreate(ref);
|
||||
if (cacheEntry.package) {
|
||||
auto &cacheEntry = m_entries.findOrCreate(ref);
|
||||
if (cacheEntry.entry) {
|
||||
// retain certain information obtained from package contents if this is actually the same package as before
|
||||
res.id = cacheEntry.id;
|
||||
package->addDepsAndProvidesFromOtherPackage(*(res.oldPackage = cacheEntry.package));
|
||||
entry->addDepsAndProvidesFromOtherPackage(*(res.oldEntry = cacheEntry.entry));
|
||||
} else {
|
||||
// check for package in storage
|
||||
cacheEntry.package = std::make_shared<Package>();
|
||||
if ((cacheEntry.id = txn.get<0>(package->name, *cacheEntry.package))) {
|
||||
package->addDepsAndProvidesFromOtherPackage(*(res.oldPackage = cacheEntry.package));
|
||||
cacheEntry.entry = std::make_shared<Entry>();
|
||||
if ((cacheEntry.id = txn.template get<0>(entry->name, *cacheEntry.entry))) {
|
||||
entry->addDepsAndProvidesFromOtherPackage(*(res.oldEntry = cacheEntry.entry));
|
||||
}
|
||||
}
|
||||
// update cache entry
|
||||
cacheEntry.ref.packageName = &package->name;
|
||||
cacheEntry.package = package;
|
||||
cacheEntry.ref.entryName = &entry->name;
|
||||
cacheEntry.entry = entry;
|
||||
// update package in storage
|
||||
res.id = cacheEntry.id = txn.put(*package, cacheEntry.id);
|
||||
res.id = cacheEntry.id = txn.put(*entry, cacheEntry.id);
|
||||
res.updated = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool PackageCache::invalidate(DatabaseStorage &databaseStorage, const std::string &packageName)
|
||||
template <typename StorageEntriesType, typename TransactionType, typename SpecType>
|
||||
bool StorageCache<StorageEntriesType, TransactionType, SpecType>::invalidate(Storage &storage, const std::string &entryName)
|
||||
{
|
||||
// remove package from cache
|
||||
const auto ref = PackageCacheRef(databaseStorage, packageName);
|
||||
const auto ref = typename Entries::Ref(storage, entryName);
|
||||
auto lock = std::unique_lock(m_mutex);
|
||||
m_packages.erase(ref);
|
||||
m_entries.erase(ref);
|
||||
lock.unlock();
|
||||
// remove package from storage
|
||||
auto txn = databaseStorage.packages.getRWTransaction();
|
||||
if (auto i = txn.find<0>(packageName); i != txn.end()) {
|
||||
auto txn = storage.packages.getRWTransaction();
|
||||
if (auto i = txn.template find<0>(entryName); i != txn.end()) {
|
||||
i.del();
|
||||
txn.commit();
|
||||
return true;
|
||||
|
@ -109,30 +139,42 @@ bool PackageCache::invalidate(DatabaseStorage &databaseStorage, const std::strin
|
|||
return false;
|
||||
}
|
||||
|
||||
void PackageCache::clear(DatabaseStorage &databaseStorage)
|
||||
template <typename StorageEntriesType, typename TransactionType, typename SpecType>
|
||||
void StorageCache<StorageEntriesType, TransactionType, SpecType>::clear(Storage &storage)
|
||||
{
|
||||
clearCacheOnly(databaseStorage);
|
||||
auto packagesTxn = databaseStorage.packages.getRWTransaction();
|
||||
clearCacheOnly(storage);
|
||||
auto packagesTxn = storage.packages.getRWTransaction();
|
||||
packagesTxn.clear();
|
||||
packagesTxn.commit();
|
||||
auto providedDepsTxn = databaseStorage.providedDeps.getRWTransaction();
|
||||
auto providedDepsTxn = storage.providedDeps.getRWTransaction();
|
||||
providedDepsTxn.clear();
|
||||
providedDepsTxn.commit();
|
||||
auto requiredDepsTxn = databaseStorage.requiredDeps.getRWTransaction();
|
||||
auto requiredDepsTxn = storage.requiredDeps.getRWTransaction();
|
||||
requiredDepsTxn.clear();
|
||||
requiredDepsTxn.commit();
|
||||
auto providedLibsTxn = databaseStorage.providedLibs.getRWTransaction();
|
||||
auto providedLibsTxn = storage.providedLibs.getRWTransaction();
|
||||
providedLibsTxn.clear();
|
||||
providedLibsTxn.commit();
|
||||
auto requiredLibsTxn = databaseStorage.requiredLibs.getRWTransaction();
|
||||
auto requiredLibsTxn = storage.requiredLibs.getRWTransaction();
|
||||
requiredLibsTxn.clear();
|
||||
requiredLibsTxn.commit();
|
||||
}
|
||||
|
||||
void PackageCache::clearCacheOnly(DatabaseStorage &databaseStorage)
|
||||
template <typename StorageEntriesType, typename TransactionType, typename SpecType>
|
||||
void StorageCache<StorageEntriesType, TransactionType, SpecType>::clearCacheOnly(Storage &storage)
|
||||
{
|
||||
const auto lock = std::unique_lock(m_mutex);
|
||||
m_packages.clear(databaseStorage);
|
||||
m_entries.clear(storage);
|
||||
}
|
||||
|
||||
template struct StorageCacheRef<DatabaseStorage, Package>;
|
||||
template struct StorageCacheEntry<PackageCacheRef, Package>;
|
||||
template class StorageCacheEntries<PackageCacheEntry>;
|
||||
template struct StorageCache<PackageCacheEntries, PackageStorage::RWTransaction, PackageSpec>;
|
||||
|
||||
StorageDistribution::StorageDistribution(const char *path, std::uint32_t maxDbs)
|
||||
{
|
||||
m_env = LMDBSafe::getMDBEnv(path, MDB_NOSUBDIR, 0600, maxDbs);
|
||||
}
|
||||
|
||||
DatabaseStorage::DatabaseStorage(const std::shared_ptr<LMDBSafe::MDBEnv> &env, PackageCache &packageCache, std::string_view uniqueDatabaseName)
|
||||
|
@ -150,37 +192,7 @@ std::size_t hash_value(const PackageCacheRef &ref)
|
|||
{
|
||||
const auto hasher1 = boost::hash<const LibPkg::DatabaseStorage *>();
|
||||
const auto hasher2 = boost::hash<std::string>();
|
||||
return ((hasher1(ref.databaseStorage) ^ (hasher2(*ref.packageName) << 1)) >> 1);
|
||||
}
|
||||
|
||||
PackageCacheEntry &RecentlyUsedPackages::findOrCreate(const PackageCacheRef &ref)
|
||||
{
|
||||
const auto &index = m_packages.get<PackageCacheRef>();
|
||||
if (auto i = index.find(ref); i != index.end()) {
|
||||
m_packages.relocate(m_packages.begin(), m_packages.project<0>(i));
|
||||
return i.get_node()->value();
|
||||
}
|
||||
const auto [i, newItem] = m_packages.emplace_front(ref);
|
||||
if (!newItem) {
|
||||
m_packages.relocate(m_packages.begin(), i);
|
||||
} else if (m_packages.size() > m_limit) {
|
||||
m_packages.pop_back();
|
||||
}
|
||||
return i.get_node()->value();
|
||||
}
|
||||
|
||||
std::size_t RecentlyUsedPackages::clear(const DatabaseStorage &databaseStorage)
|
||||
{
|
||||
auto count = std::size_t();
|
||||
for (auto i = m_packages.begin(); i != m_packages.end();) {
|
||||
if (i->ref.databaseStorage == &databaseStorage) {
|
||||
i = m_packages.erase(i);
|
||||
++count;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
return ((hasher1(ref.relatedStorage) ^ (hasher2(*ref.entryName) << 1)) >> 1);
|
||||
}
|
||||
|
||||
} // namespace LibPkg
|
||||
|
|
|
@ -18,132 +18,141 @@
|
|||
namespace LibPkg {
|
||||
|
||||
using StorageID = std::uint32_t;
|
||||
using PackageStorage = LMDBSafe::TypedDBI<Package, LMDBSafe::index_on<Package, std::string, &Package::name>>;
|
||||
using DependencyStorage = LMDBSafe::TypedDBI<DatabaseDependency, LMDBSafe::index_on<Dependency, std::string, &DatabaseDependency::name>>;
|
||||
using LibraryDependencyStorage
|
||||
= LMDBSafe::TypedDBI<DatabaseLibraryDependency, LMDBSafe::index_on<DatabaseLibraryDependency, std::string, &DatabaseLibraryDependency::name>>;
|
||||
|
||||
struct PackageCache;
|
||||
|
||||
struct DatabaseStorage {
|
||||
explicit DatabaseStorage(const std::shared_ptr<LMDBSafe::MDBEnv> &env, PackageCache &packageCache, std::string_view uniqueDatabaseName);
|
||||
PackageCache &packageCache;
|
||||
PackageStorage packages;
|
||||
DependencyStorage providedDeps;
|
||||
DependencyStorage requiredDeps;
|
||||
LibraryDependencyStorage providedLibs;
|
||||
LibraryDependencyStorage requiredLibs;
|
||||
|
||||
private:
|
||||
std::shared_ptr<LMDBSafe::MDBEnv> m_env;
|
||||
template <typename StorageType, typename EntryType> struct StorageCacheRef {
|
||||
using Storage = StorageType;
|
||||
explicit StorageCacheRef(const StorageType &relatedStorage, const std::shared_ptr<EntryType> &entry);
|
||||
explicit StorageCacheRef(const StorageType &relatedStorage, const std::string &entryName);
|
||||
bool operator==(const StorageCacheRef &other) const;
|
||||
const StorageType *relatedStorage = nullptr;
|
||||
const std::string *entryName;
|
||||
};
|
||||
|
||||
struct PackageCacheRef {
|
||||
explicit PackageCacheRef(const DatabaseStorage &databaseStorage, const std::shared_ptr<Package> &package);
|
||||
explicit PackageCacheRef(const DatabaseStorage &databaseStorage, const std::string &packageName);
|
||||
bool operator==(const PackageCacheRef &other) const;
|
||||
const DatabaseStorage *databaseStorage = nullptr;
|
||||
const std::string *packageName;
|
||||
};
|
||||
|
||||
inline PackageCacheRef::PackageCacheRef(const DatabaseStorage &databaseStorage, const std::shared_ptr<Package> &package)
|
||||
: databaseStorage(&databaseStorage)
|
||||
, packageName(&package->name)
|
||||
template <typename StorageType, typename EntryType>
|
||||
inline StorageCacheRef<StorageType, EntryType>::StorageCacheRef(const StorageType &relatedStorage, const std::shared_ptr<EntryType> &entry)
|
||||
: relatedStorage(&relatedStorage)
|
||||
, entryName(&entry->name)
|
||||
{
|
||||
}
|
||||
|
||||
inline PackageCacheRef::PackageCacheRef(const DatabaseStorage &databaseStorage, const std::string &packageName)
|
||||
: databaseStorage(&databaseStorage)
|
||||
, packageName(&packageName)
|
||||
template <typename StorageType, typename EntryType>
|
||||
inline StorageCacheRef<StorageType, EntryType>::StorageCacheRef(const StorageType &relatedStorage, const std::string &entryName)
|
||||
: relatedStorage(&relatedStorage)
|
||||
, entryName(&entryName)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool PackageCacheRef::operator==(const PackageCacheRef &other) const
|
||||
template <typename StorageType, typename EntryType>
|
||||
inline bool StorageCacheRef<StorageType, EntryType>::operator==(const StorageCacheRef<StorageType, EntryType> &other) const
|
||||
{
|
||||
return databaseStorage == other.databaseStorage && *packageName == *other.packageName;
|
||||
return relatedStorage == other.relatedStorage && *entryName == *other.entryName;
|
||||
}
|
||||
|
||||
std::size_t hash_value(const PackageCacheRef &ref);
|
||||
|
||||
struct PackageCacheEntry {
|
||||
explicit PackageCacheEntry(const PackageCacheRef &ref);
|
||||
PackageCacheRef ref;
|
||||
template <typename StorageRefType, typename EntryType> 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<Package> package;
|
||||
std::shared_ptr<EntryType> entry;
|
||||
};
|
||||
|
||||
inline PackageCacheEntry::PackageCacheEntry(const PackageCacheRef &ref)
|
||||
template <typename StorageRefType, typename EntryType>
|
||||
inline StorageCacheEntry<StorageRefType, EntryType>::StorageCacheEntry(const StorageRefType &ref)
|
||||
: ref(ref)
|
||||
, id(0)
|
||||
{
|
||||
}
|
||||
|
||||
class RecentlyUsedPackages {
|
||||
using PackageList = boost::multi_index::multi_index_container<PackageCacheEntry,
|
||||
boost::multi_index::indexed_by<boost::multi_index::sequenced<>,
|
||||
boost::multi_index::hashed_unique<boost::multi_index::tag<PackageCacheRef>,
|
||||
BOOST_MULTI_INDEX_MEMBER(PackageCacheEntry, PackageCacheRef, ref)>>>;
|
||||
using iterator = PackageList::iterator;
|
||||
|
||||
template <typename StorageEntryType> class StorageCacheEntries {
|
||||
public:
|
||||
explicit RecentlyUsedPackages(std::size_t limit = 1000);
|
||||
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<StorageEntry,
|
||||
boost::multi_index::indexed_by<boost::multi_index::sequenced<>,
|
||||
boost::multi_index::hashed_unique<boost::multi_index::tag<Ref>, BOOST_MULTI_INDEX_MEMBER(StorageEntryType, Ref, ref)>>>;
|
||||
using iterator = typename EntryList::iterator;
|
||||
|
||||
PackageCacheEntry &findOrCreate(const PackageCacheRef &ref);
|
||||
explicit StorageCacheEntries(std::size_t limit = 1000);
|
||||
|
||||
StorageEntry &findOrCreate(const Ref &ref);
|
||||
void undo();
|
||||
std::size_t erase(const PackageCacheRef &ref);
|
||||
std::size_t clear(const DatabaseStorage &databaseStorage);
|
||||
std::size_t erase(const Ref &ref);
|
||||
std::size_t clear(const Storage &storage);
|
||||
iterator begin();
|
||||
iterator end();
|
||||
|
||||
private:
|
||||
PackageList m_packages;
|
||||
EntryList m_entries;
|
||||
std::size_t m_limit;
|
||||
};
|
||||
|
||||
inline RecentlyUsedPackages::RecentlyUsedPackages(std::size_t limit)
|
||||
template <typename StorageEntryType>
|
||||
inline StorageCacheEntries<StorageEntryType>::StorageCacheEntries(std::size_t limit)
|
||||
: m_limit(limit)
|
||||
{
|
||||
}
|
||||
|
||||
inline void RecentlyUsedPackages::undo()
|
||||
template <typename StorageEntryType> inline void StorageCacheEntries<StorageEntryType>::undo()
|
||||
{
|
||||
m_packages.pop_front();
|
||||
m_entries.pop_front();
|
||||
}
|
||||
|
||||
inline std::size_t RecentlyUsedPackages::erase(const PackageCacheRef &ref)
|
||||
template <typename StorageEntryType> inline std::size_t StorageCacheEntries<StorageEntryType>::erase(const Ref &ref)
|
||||
{
|
||||
return m_packages.get<PackageCacheRef>().erase(ref);
|
||||
return m_entries.template get<typename StorageEntryType::Ref>().erase(ref);
|
||||
}
|
||||
|
||||
inline RecentlyUsedPackages::iterator RecentlyUsedPackages::begin()
|
||||
template <typename StorageEntryType> inline auto StorageCacheEntries<StorageEntryType>::begin() -> iterator
|
||||
{
|
||||
return m_packages.begin();
|
||||
return m_entries.begin();
|
||||
}
|
||||
|
||||
inline RecentlyUsedPackages::iterator RecentlyUsedPackages::end()
|
||||
template <typename StorageEntryType> inline auto StorageCacheEntries<StorageEntryType>::end() -> iterator
|
||||
{
|
||||
return m_packages.end();
|
||||
return m_entries.end();
|
||||
}
|
||||
|
||||
struct PackageCache {
|
||||
template <typename StorageEntriesType, typename TransactionType, typename SpecType> 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<Package> oldPackage;
|
||||
std::shared_ptr<typename Entries::Entry> oldEntry;
|
||||
};
|
||||
|
||||
PackageSpec retrieve(DatabaseStorage &databaseStorage, const std::string &packageName);
|
||||
StoreResult store(DatabaseStorage &databaseStorage, const std::shared_ptr<Package> &package, bool force);
|
||||
StoreResult store(DatabaseStorage &databaseStorage, PackageStorage::RWTransaction &txn, const std::shared_ptr<Package> &package);
|
||||
bool invalidate(DatabaseStorage &databaseStorage, const std::string &packageName);
|
||||
void clear(DatabaseStorage &databaseStorage);
|
||||
void clearCacheOnly(DatabaseStorage &databaseStorage);
|
||||
SpecType retrieve(Storage &storage, const std::string &entryName);
|
||||
StoreResult store(Storage &storage, const std::shared_ptr<Entry> &entry, bool force);
|
||||
StoreResult store(Storage &storage, Txn &txn, const std::shared_ptr<Entry> &entry);
|
||||
bool invalidate(Storage &storage, const std::string &entryName);
|
||||
void clear(Storage &storage);
|
||||
void clearCacheOnly(Storage &storage);
|
||||
|
||||
private:
|
||||
RecentlyUsedPackages m_packages;
|
||||
Entries m_entries;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
using PackageStorage = LMDBSafe::TypedDBI<Package, LMDBSafe::index_on<Package, std::string, &Package::name>>;
|
||||
using DependencyStorage = LMDBSafe::TypedDBI<DatabaseDependency, LMDBSafe::index_on<Dependency, std::string, &DatabaseDependency::name>>;
|
||||
using LibraryDependencyStorage
|
||||
= LMDBSafe::TypedDBI<DatabaseLibraryDependency, LMDBSafe::index_on<DatabaseLibraryDependency, std::string, &DatabaseLibraryDependency::name>>;
|
||||
using PackageCacheRef = StorageCacheRef<DatabaseStorage, Package>;
|
||||
using PackageCacheEntry = StorageCacheEntry<PackageCacheRef, Package>;
|
||||
using PackageCacheEntries = StorageCacheEntries<PackageCacheEntry>;
|
||||
using PackageCache = StorageCache<PackageCacheEntries, PackageStorage::RWTransaction, PackageSpec>;
|
||||
|
||||
extern template struct StorageCacheRef<DatabaseStorage, Package>;
|
||||
extern template struct StorageCacheEntry<PackageCacheRef, Package>;
|
||||
extern template class StorageCacheEntries<PackageCacheEntry>;
|
||||
extern template struct StorageCache<PackageCacheEntries, PackageStorage::RWTransaction, PackageSpec>;
|
||||
|
||||
struct StorageDistribution {
|
||||
explicit StorageDistribution(const char *path, std::uint32_t maxDbs);
|
||||
|
||||
|
@ -159,6 +168,21 @@ inline std::unique_ptr<DatabaseStorage> StorageDistribution::forDatabase(std::st
|
|||
return std::make_unique<DatabaseStorage>(m_env, m_packageCache, uniqueDatabaseName);
|
||||
}
|
||||
|
||||
struct DatabaseStorage {
|
||||
explicit DatabaseStorage(const std::shared_ptr<LMDBSafe::MDBEnv> &env, PackageCache &packageCache, std::string_view uniqueDatabaseName);
|
||||
PackageCache &packageCache;
|
||||
PackageStorage packages;
|
||||
DependencyStorage providedDeps;
|
||||
DependencyStorage requiredDeps;
|
||||
LibraryDependencyStorage providedLibs;
|
||||
LibraryDependencyStorage requiredLibs;
|
||||
|
||||
private:
|
||||
std::shared_ptr<LMDBSafe::MDBEnv> m_env;
|
||||
};
|
||||
|
||||
std::size_t hash_value(const PackageCacheRef &ref);
|
||||
|
||||
} // namespace LibPkg
|
||||
|
||||
#endif // LIBPKG_DATA_STORAGE_PRIVATE_H
|
||||
|
|
Loading…
Reference in New Issue