Update/remove packages from database in a whole transaction

This commit is contained in:
Martchus 2022-11-01 15:45:58 +01:00
parent 84ef92aaa2
commit 407e3159e0
4 changed files with 34 additions and 82 deletions

View File

@ -177,39 +177,36 @@ static void removeLibDependency(LibraryDependencyStorage::RWTransaction &txn, St
}
}
void Database::removePackageDependencies(StorageID packageID, const std::shared_ptr<Package> &package)
static void removePackageDependencies(DatabaseStorage &storage, const std::shared_ptr<LMDBSafe::MDBRWTransaction> &txnHandle, StorageID packageID,
const std::shared_ptr<Package> &package)
{
{
auto txn = m_storage->providedDeps.getRWTransaction();
auto txn = storage.providedDeps.getRWTransaction(txnHandle);
removeDependency(txn, packageID, package->name);
for (const auto &dep : package->provides) {
removeDependency(txn, packageID, dep.name);
}
txn.commit();
}
{
auto txn = m_storage->requiredDeps.getRWTransaction();
auto txn = storage.requiredDeps.getRWTransaction(txnHandle);
for (const auto &dep : package->dependencies) {
removeDependency(txn, packageID, dep.name);
}
for (const auto &dep : package->optionalDependencies) {
removeDependency(txn, packageID, dep.name);
}
txn.commit();
}
{
auto txn = m_storage->providedLibs.getRWTransaction();
auto txn = storage.providedLibs.getRWTransaction(txnHandle);
for (const auto &lib : package->libprovides) {
removeLibDependency(txn, packageID, lib);
}
txn.commit();
}
{
auto txn = m_storage->requiredLibs.getRWTransaction();
auto txn = storage.requiredLibs.getRWTransaction(txnHandle);
for (const auto &lib : package->libdepends) {
removeLibDependency(txn, packageID, lib);
}
txn.commit();
}
}
@ -253,39 +250,36 @@ static void addLibDependency(LibraryDependencyStorage::RWTransaction &txn, Stora
txn.put(newDependency);
}
void Database::addPackageDependencies(StorageID packageID, const std::shared_ptr<Package> &package)
static void addPackageDependencies(DatabaseStorage &storage, const std::shared_ptr<LMDBSafe::MDBRWTransaction> &txnHandle, StorageID packageID,
const std::shared_ptr<Package> &package)
{
{
auto txn = m_storage->providedDeps.getRWTransaction();
auto txn = storage.providedDeps.getRWTransaction(txnHandle);
addDependency(txn, packageID, package->name, package->version);
for (const auto &dep : package->provides) {
addDependency(txn, packageID, dep.name, dep.version, dep.mode);
}
txn.commit();
}
{
auto txn = m_storage->requiredDeps.getRWTransaction();
auto txn = storage.requiredDeps.getRWTransaction(txnHandle);
for (const auto &dep : package->dependencies) {
addDependency(txn, packageID, dep.name, dep.version, dep.mode);
}
for (const auto &dep : package->optionalDependencies) {
addDependency(txn, packageID, dep.name, dep.version, dep.mode);
}
txn.commit();
}
{
auto txn = m_storage->providedLibs.getRWTransaction();
auto txn = storage.providedLibs.getRWTransaction(txnHandle);
for (const auto &lib : package->libprovides) {
addLibDependency(txn, packageID, lib);
}
txn.commit();
}
{
auto txn = m_storage->requiredLibs.getRWTransaction();
auto txn = storage.requiredLibs.getRWTransaction(txnHandle);
for (const auto &lib : package->libdepends) {
addLibDependency(txn, packageID, lib);
}
txn.commit();
}
}
@ -472,9 +466,11 @@ StorageID Database::findBasePackageWithID(const std::string &packageName, Packag
void Database::removePackage(const std::string &packageName)
{
const auto lock = std::unique_lock(m_storage->updateMutex);
const auto [packageID, package] = m_storage->packageCache.retrieve(*m_storage, packageName);
auto txn = m_storage->packages.getRWTransaction();
const auto [packageID, package] = m_storage->packageCache.retrieve(*m_storage, &txn, packageName);
if (package) {
removePackageDependencies(packageID, package);
removePackageDependencies(*m_storage, txn.getTransactionHandle(), packageID, package);
txn.commit();
m_storage->packageCache.invalidate(*m_storage, packageName);
}
}
@ -485,14 +481,16 @@ StorageID Database::updatePackage(const std::shared_ptr<Package> &package)
return 0;
}
const auto lock = std::unique_lock(m_storage->updateMutex);
const auto res = m_storage->packageCache.store(*m_storage, package, false);
auto txn = m_storage->packages.getRWTransaction();
const auto res = m_storage->packageCache.store(*m_storage, txn, package, false);
if (!res.updated) {
return res.id;
}
if (res.oldEntry) {
removePackageDependencies(res.id, res.oldEntry);
removePackageDependencies(*m_storage, txn.getTransactionHandle(), res.id, res.oldEntry);
}
addPackageDependencies(res.id, package);
addPackageDependencies(*m_storage, txn.getTransactionHandle(), res.id, package);
txn.commit();
return res.id;
}
@ -502,11 +500,13 @@ StorageID Database::forceUpdatePackage(const std::shared_ptr<Package> &package)
return 0;
}
const auto lock = std::unique_lock(m_storage->updateMutex);
const auto res = m_storage->packageCache.store(*m_storage, package, true);
auto txn = m_storage->packages.getRWTransaction();
const auto res = m_storage->packageCache.store(*m_storage, txn, package, true);
if (res.oldEntry) {
removePackageDependencies(res.id, res.oldEntry);
removePackageDependencies(*m_storage, txn.getTransactionHandle(), res.id, res.oldEntry);
}
addPackageDependencies(res.id, package);
addPackageDependencies(*m_storage, txn.getTransactionHandle(), res.id, package);
txn.commit();
return res.id;
}
@ -885,7 +885,7 @@ PackageSpec LibPkg::PackageUpdater::findPackageWithID(const std::string &package
StorageID PackageUpdater::update(const std::shared_ptr<Package> &package)
{
const auto &storage = m_database.m_storage;
const auto res = storage->packageCache.store(*m_database.m_storage, m_d->packagesTxn, package);
const auto res = storage->packageCache.store(*m_database.m_storage, m_d->packagesTxn, package, true);
m_d->update(res, package);
return res.id;
}

View File

@ -194,10 +194,6 @@ struct LIBPKG_EXPORT Database : public ReflectiveRapidJSON::JsonSerializable<Dat
PackageLocation locatePackage(const std::string &packageName) const;
std::string filesPathFromRegularPath() const;
private:
void removePackageDependencies(StorageID packageID, const std::shared_ptr<Package> &package);
void addPackageDependencies(StorageID packageID, const std::shared_ptr<Package> &package);
public:
std::string name;
std::string path;

View File

@ -130,55 +130,8 @@ auto StorageCache<StorageEntriesType, StorageType, SpecType>::retrieve(Storage &
}
template <typename StorageEntriesType, typename StorageType, typename SpecType>
auto StorageCache<StorageEntriesType, StorageType, SpecType>::store(Storage &storage, const std::shared_ptr<Entry> &entry, bool force) -> StoreResult
{
// check for package in cache
using CacheEntry = typename Entries::StorageEntry;
using CacheRef = typename Entries::Ref;
const auto ref = CacheRef(storage, entry);
auto res = StorageCache::StoreResult();
auto lock = std::unique_lock(m_mutex);
auto *cacheEntry = m_entries.find(ref);
if (cacheEntry) {
res.id = cacheEntry->id;
res.oldEntry = cacheEntry->entry;
if (cacheEntry->entry == entry && !force) {
// do nothing if cached package is the same as specified one
return res;
} else {
// retain certain information obtained from package contents if this is actually the same package as before
entry->addDepsAndProvidesFromOtherPackage(*cacheEntry->entry);
}
}
lock.unlock();
// check for package in storage
auto txn = storage.packages.getRWTransaction();
if (!res.oldEntry) {
res.oldEntry = std::make_shared<Entry>();
if ((res.id = txn.template get<0>(entry->name, *res.oldEntry))) {
entry->addDepsAndProvidesFromOtherPackage(*res.oldEntry);
} else {
res.oldEntry.reset();
}
}
// update package in storage
res.id = txn.put(*entry, res.id);
// update cache entry
lock = std::unique_lock(m_mutex);
if (cacheEntry) {
cacheEntry->ref.entryName = &entry->name;
} else {
cacheEntry = &m_entries.insert(CacheEntry(ref, res.id));
}
cacheEntry->entry = entry;
lock.unlock();
txn.commit();
res.updated = true;
return res;
}
template <typename StorageEntriesType, typename StorageType, typename SpecType>
auto StorageCache<StorageEntriesType, StorageType, SpecType>::store(Storage &storage, RWTxn &txn, const std::shared_ptr<Entry> &entry) -> StoreResult
auto StorageCache<StorageEntriesType, StorageType, SpecType>::store(Storage &storage, RWTxn &txn, const std::shared_ptr<Entry> &entry, bool force)
-> StoreResult
{
// check for package in cache
using CacheEntry = typename Entries::StorageEntry;
@ -191,6 +144,10 @@ auto StorageCache<StorageEntriesType, StorageType, SpecType>::store(Storage &sto
auto lock = std::unique_lock(m_mutex);
auto *cacheEntry = m_entries.find(ref);
if (cacheEntry) {
if (cacheEntry->entry == entry && !force) {
// do nothing if cached package is the same as specified one
return res;
}
// retain certain information obtained from package contents if this is actually the same package as before
res.id = cacheEntry->id;
entry->addDepsAndProvidesFromOtherPackage(*(res.oldEntry = cacheEntry->entry));

View File

@ -151,8 +151,7 @@ template <typename StorageEntriesType, typename StorageType, typename SpecType>
SpecType retrieve(Storage &storage, StorageID storageID);
SpecType retrieve(Storage &storage, RWTxn *, const std::string &entryName);
SpecType retrieve(Storage &storage, const std::string &entryName);
StoreResult store(Storage &storage, const std::shared_ptr<Entry> &entry, bool force);
StoreResult store(Storage &storage, RWTxn &txn, const std::shared_ptr<Entry> &entry);
StoreResult store(Storage &storage, RWTxn &txn, const std::shared_ptr<Entry> &entry, bool force);
bool invalidate(Storage &storage, const std::string &entryName);
void clear(Storage &storage);
void clearCacheOnly(Storage &storage);