Clear entries from package cache correctly

This commit is contained in:
Martchus 2023-12-16 23:07:22 +01:00
parent 40e2fb82de
commit 303d0bd17b
4 changed files with 60 additions and 11 deletions

View File

@ -931,19 +931,21 @@ bool PackageUpdater::insertFromDatabaseFile(const std::string &databaseFilePath)
void PackageUpdater::commit()
{
const auto &storage = m_database.m_storage;
auto &storage = *m_database.m_storage;
auto &pkgTxn = m_d->packagesTxn;
auto txnHandle = pkgTxn.getTransactionHandle();
if (m_d->clear) {
const auto &toPreserve = m_d->handledIds;
for (auto i = pkgTxn.begin<std::unique_ptr>(); i != pkgTxn.end(); ++i) {
const auto end = pkgTxn.end();
for (auto i = pkgTxn.begin(); i != end; ++i) {
if (!toPreserve.contains(i.getID())) {
storage.packageCache.invalidateCacheOnly(storage, i.value().name);
i.del();
}
}
}
{
auto txn = storage->providedDeps.getRWTransaction(txnHandle);
auto txn = storage.providedDeps.getRWTransaction(txnHandle);
if (m_d->clear) {
txn.clear();
}
@ -952,7 +954,7 @@ void PackageUpdater::commit()
}
}
{
auto txn = storage->requiredDeps.getRWTransaction(txnHandle);
auto txn = storage.requiredDeps.getRWTransaction(txnHandle);
if (m_d->clear) {
txn.clear();
}
@ -961,7 +963,7 @@ void PackageUpdater::commit()
}
}
{
auto txn = storage->providedLibs.getRWTransaction(txnHandle);
auto txn = storage.providedLibs.getRWTransaction(txnHandle);
if (m_d->clear) {
txn.clear();
}
@ -970,7 +972,7 @@ void PackageUpdater::commit()
}
}
{
auto txn = storage->requiredLibs.getRWTransaction(txnHandle);
auto txn = storage.requiredLibs.getRWTransaction(txnHandle);
if (m_d->clear) {
txn.clear();
}

View File

@ -181,10 +181,7 @@ template <typename StorageEntriesType, typename StorageType, typename SpecType>
bool StorageCache<StorageEntriesType, StorageType, SpecType>::invalidate(Storage &storage, const std::string &entryName)
{
// remove package from cache
const auto ref = typename Entries::Ref(storage, entryName);
auto lock = std::unique_lock(m_mutex);
m_entries.erase(ref);
lock.unlock();
invalidateCacheOnly(storage, entryName);
// remove package from storage
auto txn = storage.packages.getRWTransaction();
if (auto i = txn.template find<0>(entryName); i != txn.end()) {
@ -195,6 +192,15 @@ bool StorageCache<StorageEntriesType, StorageType, SpecType>::invalidate(Storage
return false;
}
template <typename StorageEntriesType, typename StorageType, typename SpecType>
bool StorageCache<StorageEntriesType, StorageType, SpecType>::invalidateCacheOnly(Storage &storage, const std::string &entryName)
{
const auto ref = typename Entries::Ref(storage, entryName);
const auto lock = std::unique_lock(m_mutex);
m_entries.erase(ref);
return true;
}
template <typename StorageEntriesType, typename StorageType, typename SpecType>
void StorageCache<StorageEntriesType, StorageType, SpecType>::clear(Storage &storage)
{

View File

@ -153,6 +153,7 @@ template <typename StorageEntriesType, typename StorageType, typename SpecType>
SpecType retrieve(Storage &storage, const std::string &entryName);
StoreResult store(Storage &storage, RWTxn &txn, const std::shared_ptr<Entry> &entry, bool force);
bool invalidate(Storage &storage, const std::string &entryName);
bool invalidateCacheOnly(Storage &storage, const std::string &entryName);
void clear(Storage &storage);
void clearCacheOnly(Storage &storage);
void setLimit(std::size_t limit);

View File

@ -11,8 +11,8 @@ using CppUtilities::operator<<; // must be visible prior to the call site
#include <filesystem>
#include <initializer_list>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
using namespace std;
@ -36,6 +36,7 @@ class DataTests : public TestFixture {
CPPUNIT_TEST(testLocatePackage);
CPPUNIT_TEST(testAddingDepsAndProvidesFromOtherPackage);
CPPUNIT_TEST(testDependencyExport);
CPPUNIT_TEST(testPackageUpdater);
CPPUNIT_TEST(testMisc);
CPPUNIT_TEST_SUITE_END();
@ -59,6 +60,7 @@ public:
void testLocatePackage();
void testAddingDepsAndProvidesFromOtherPackage();
void testDependencyExport();
void testPackageUpdater();
void testMisc();
private:
@ -524,6 +526,44 @@ void DataTests::testDependencyExport()
CPPUNIT_ASSERT(libProvides.contains("libbar"));
}
void DataTests::testPackageUpdater()
{
m_pkg1 = std::make_shared<LibPkg::Package>();
m_pkg1->name = "foo";
m_pkg2 = std::make_shared<LibPkg::Package>();
m_pkg2->name = "autoconf";
m_pkg2->version = "1-1";
m_dbFile = workingCopyPath("test-data.db", WorkingCopyMode::Cleanup);
m_config.initStorage(m_dbFile.data());
auto *const db = m_config.findOrCreateDatabase("test"sv, "x86_64"sv);
db->path = testFilePath("core.db");
db->updatePackage(m_pkg1);
db->updatePackage(m_pkg2);
auto updater = LibPkg::PackageUpdater(*db, true);
updater.insertFromDatabaseFile(db->path);
auto thread = std::thread([db] {
auto autoconf = db->findPackage("autoconf");
CPPUNIT_ASSERT_EQUAL_MESSAGE("two packages before commit", 2_st, db->packageCount());
CPPUNIT_ASSERT_MESSAGE("cache not wiped before commit (so removed package still present)", db->findPackage("foo"));
CPPUNIT_ASSERT_MESSAGE("cache contains autoconf", autoconf);
CPPUNIT_ASSERT_EQUAL_MESSAGE("cache populated before commit (so new version already visible)", "2.69-4"s, autoconf->version);
});
thread.join();
updater.commit();
CPPUNIT_ASSERT_EQUAL_MESSAGE("package count after commit", 220_st, db->packageCount());
CPPUNIT_ASSERT_MESSAGE("old package gone after commit", !db->findPackage("foo"));
auto newPkg = db->findPackage("autoconf");
CPPUNIT_ASSERT_MESSAGE("new package present after commit", newPkg);
CPPUNIT_ASSERT_EQUAL_MESSAGE("search returns correct package", "autoconf"s, newPkg->name);
CPPUNIT_ASSERT_EQUAL_MESSAGE("the package version was updated", "2.69-4"s, newPkg->version);
CPPUNIT_ASSERT(newPkg = db->findPackage("acl"));
CPPUNIT_ASSERT_EQUAL("acl"s, newPkg->name);
CPPUNIT_ASSERT(newPkg = db->findPackage("zlib"));
CPPUNIT_ASSERT_EQUAL("zlib"s, newPkg->name);
}
void DataTests::testMisc()
{
CPPUNIT_ASSERT_EQUAL("123.4"s, PackageVersion::trimPackageVersion("123.4"s));