Add command to delete invalid build actions from DB

This commit is contained in:
Martchus 2022-03-07 23:36:48 +01:00
parent 7ade757c8d
commit 55f081153e
5 changed files with 68 additions and 2 deletions

2
3rdparty/lmdb-safe vendored

@ -1 +1 @@
Subproject commit 4580d7242ad2c1c56582c6ee25e2227bfc6166e7
Subproject commit 95ff695381c9662ec100697bebc6132bc317c005

View File

@ -47,6 +47,7 @@ enum class BuildActionType : std::uint64_t {
CleanRepository,
DummyBuildAction,
CustomCommand,
LastType = CustomCommand,
};
using BuildActionFlagType = std::uint64_t;

View File

@ -357,6 +357,41 @@ std::size_t ServiceSetup::BuildSetup::buildActionCount()
return m_storage->buildActions.getROTransaction().size();
}
void ServiceSetup::BuildSetup::rebuildDb()
{
auto txn = m_storage->buildActions.getRWTransaction();
auto processed = std::size_t();
auto ok = std::size_t();
txn.rebuild([count = txn.size(), &processed, &ok](StorageID id, BuildAction *buildAction) mutable {
std::cerr << "Processing build action " << ++processed << " / " << count << '\n';
if (!buildAction) {
std::cerr << "Deleting build action " << id << ": unable to deserialize\n";
return false;
}
if (buildAction->id > std::numeric_limits<StorageID>::max()) {
std::cerr << "Deleting build action " << id << ": object ID " << buildAction->id << " is out of range\n";
return false;
}
if (buildAction->id != id) {
std::cerr << "Deleting build action " << id << ": ID mismatch (object ID is " << buildAction->id << ")\n";
return false;
}
if (buildAction->type == BuildActionType::Invalid || buildAction->type > BuildActionType::LastType) {
std::cerr << "Deleting build action " << id << ": type is invalid\n";
return false;
}
++ok;
return true;
});
if (ok < processed) {
std::cerr << "Discarding " << (processed - ok) << " invalid build actions.\n";
} else {
std::cerr << "All " << ok << " build actions are valid.\n";
}
std::cerr << "Committing changes.\n";
txn.commit();
}
void ServiceSetup::BuildSetup::forEachBuildAction(
std::function<void(std::size_t)> count, std::function<bool(LibPkg::StorageID, BuildAction &&)> &&func, std::size_t limit, std::size_t start)
{
@ -764,6 +799,26 @@ int ServiceSetup::run()
return 0;
}
int ServiceSetup::fixDb()
{
#ifndef CPP_UTILITIES_DEBUG_BUILD
try {
#endif
loadConfigFiles(true);
building.initStorage(building.dbPath.data());
building.rebuildDb();
#ifndef CPP_UTILITIES_DEBUG_BUILD
} catch (const std::exception &e) {
cerr << Phrases::ErrorMessage << "Exception occurred when terminating server: " << Phrases::End << " " << e.what() << Phrases::EndFlush;
return -5;
} catch (...) {
cerr << Phrases::ErrorMessage << "Unknown error occurred when terminating server." << Phrases::EndFlush;
return -6;
}
#endif
return 0;
}
void ServiceSetup::Locks::clear()
{
auto log = LogContext();

View File

@ -55,6 +55,7 @@ struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable {
std::size_t saveState();
void initStorage();
int run();
int fixDb();
ServiceStatus computeStatus() const;
// variables relevant for the web server; only changed when (re)loading config
@ -141,6 +142,7 @@ struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable {
void deleteBuildAction(const std::vector<std::shared_ptr<BuildAction>> &actions);
std::size_t buildActionCount();
std::size_t runningBuildActionCount();
void rebuildDb();
void forEachBuildAction(std::function<void(std::size_t)> count, std::function<bool(LibPkg::StorageID, BuildAction &&)> &&func,
std::size_t limit, std::size_t start);
void forEachBuildAction(std::function<bool(LibPkg::StorageID, BuildAction &, bool &)> &&func);

View File

@ -41,9 +41,17 @@ int main(int argc, const char *argv[])
setup.building.forceLoadingDbs = forceLoadingDBsArg.isPresent();
exitCode = setup.run();
});
OperationArgument fixDb("fix-db", '\0', "fixes the database files");
fixDb.setSubArguments({ &configFileArg });
fixDb.setCallback([&setup, &exitCode, &configFileArg](const ArgumentOccurrence &) {
if (const auto configFilePath = configFileArg.firstValue()) {
setup.configFilePath = configFilePath;
}
exitCode = setup.fixDb();
});
HelpArgument helpArg(parser);
NoColorArgument noColorArg;
parser.setMainArguments({ &runArg, &noColorArg, &helpArg });
parser.setMainArguments({ &runArg, &fixDb, &noColorArg, &helpArg });
parser.setDefaultArgument(&runArg);
parser.parseArgs(argc, argv);
return exitCode;