mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-30 01:26:15 +02:00
Turn retrying SQLite transactions into a higher-order function
This commit is contained in:
parent
39a6abc0bc
commit
2ae43ced9a
1 changed files with 42 additions and 33 deletions
|
@ -70,9 +70,18 @@ MakeError(SQLiteBusy, SQLiteError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Convenience macros for retrying a SQLite transaction. */
|
/* Convenience function for retrying a SQLite transaction when the
|
||||||
#define retry_sqlite while (1) { try {
|
database is busy. */
|
||||||
#define end_retry_sqlite break; } catch (SQLiteBusy & e) { } }
|
template<typename T>
|
||||||
|
T retrySQLite(std::function<T()> fun)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
return fun();
|
||||||
|
} catch (SQLiteBusy & e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SQLite::~SQLite()
|
SQLite::~SQLite()
|
||||||
|
@ -746,32 +755,32 @@ void LocalStore::addReference(unsigned long long referrer, unsigned long long re
|
||||||
|
|
||||||
void LocalStore::registerFailedPath(const Path & path)
|
void LocalStore::registerFailedPath(const Path & path)
|
||||||
{
|
{
|
||||||
retry_sqlite {
|
retrySQLite<void>([&]() {
|
||||||
SQLiteStmtUse use(stmtRegisterFailedPath);
|
SQLiteStmtUse use(stmtRegisterFailedPath);
|
||||||
stmtRegisterFailedPath.bind(path);
|
stmtRegisterFailedPath.bind(path);
|
||||||
stmtRegisterFailedPath.bind(time(0));
|
stmtRegisterFailedPath.bind(time(0));
|
||||||
if (sqlite3_step(stmtRegisterFailedPath) != SQLITE_DONE)
|
if (sqlite3_step(stmtRegisterFailedPath) != SQLITE_DONE)
|
||||||
throwSQLiteError(db, format("registering failed path ‘%1%’") % path);
|
throwSQLiteError(db, format("registering failed path ‘%1%’") % path);
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LocalStore::hasPathFailed(const Path & path)
|
bool LocalStore::hasPathFailed(const Path & path)
|
||||||
{
|
{
|
||||||
retry_sqlite {
|
return retrySQLite<bool>([&]() {
|
||||||
SQLiteStmtUse use(stmtHasPathFailed);
|
SQLiteStmtUse use(stmtHasPathFailed);
|
||||||
stmtHasPathFailed.bind(path);
|
stmtHasPathFailed.bind(path);
|
||||||
int res = sqlite3_step(stmtHasPathFailed);
|
int res = sqlite3_step(stmtHasPathFailed);
|
||||||
if (res != SQLITE_DONE && res != SQLITE_ROW)
|
if (res != SQLITE_DONE && res != SQLITE_ROW)
|
||||||
throwSQLiteError(db, "querying whether path failed");
|
throwSQLiteError(db, "querying whether path failed");
|
||||||
return res == SQLITE_ROW;
|
return res == SQLITE_ROW;
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PathSet LocalStore::queryFailedPaths()
|
PathSet LocalStore::queryFailedPaths()
|
||||||
{
|
{
|
||||||
retry_sqlite {
|
return retrySQLite<PathSet>([&]() {
|
||||||
SQLiteStmtUse use(stmtQueryFailedPaths);
|
SQLiteStmtUse use(stmtQueryFailedPaths);
|
||||||
|
|
||||||
PathSet res;
|
PathSet res;
|
||||||
|
@ -786,13 +795,13 @@ PathSet LocalStore::queryFailedPaths()
|
||||||
throwSQLiteError(db, "error querying failed paths");
|
throwSQLiteError(db, "error querying failed paths");
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::clearFailedPaths(const PathSet & paths)
|
void LocalStore::clearFailedPaths(const PathSet & paths)
|
||||||
{
|
{
|
||||||
retry_sqlite {
|
retrySQLite<void>([&]() {
|
||||||
SQLiteTxn txn(db);
|
SQLiteTxn txn(db);
|
||||||
|
|
||||||
for (auto & i : paths) {
|
for (auto & i : paths) {
|
||||||
|
@ -803,7 +812,7 @@ void LocalStore::clearFailedPaths(const PathSet & paths)
|
||||||
}
|
}
|
||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -828,7 +837,7 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
|
||||||
|
|
||||||
assertStorePath(path);
|
assertStorePath(path);
|
||||||
|
|
||||||
retry_sqlite {
|
return retrySQLite<ValidPathInfo>([&]() {
|
||||||
|
|
||||||
/* Get the path info. */
|
/* Get the path info. */
|
||||||
SQLiteStmtUse use1(stmtQueryPathInfo);
|
SQLiteStmtUse use1(stmtQueryPathInfo);
|
||||||
|
@ -868,7 +877,7 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
|
||||||
throwSQLiteError(db, format("error getting references of ‘%1%’") % path);
|
throwSQLiteError(db, format("error getting references of ‘%1%’") % path);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -912,26 +921,26 @@ bool LocalStore::isValidPath_(const Path & path)
|
||||||
|
|
||||||
bool LocalStore::isValidPath(const Path & path)
|
bool LocalStore::isValidPath(const Path & path)
|
||||||
{
|
{
|
||||||
retry_sqlite {
|
return retrySQLite<bool>([&]() {
|
||||||
return isValidPath_(path);
|
return isValidPath_(path);
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PathSet LocalStore::queryValidPaths(const PathSet & paths)
|
PathSet LocalStore::queryValidPaths(const PathSet & paths)
|
||||||
{
|
{
|
||||||
retry_sqlite {
|
return retrySQLite<PathSet>([&]() {
|
||||||
PathSet res;
|
PathSet res;
|
||||||
for (auto & i : paths)
|
for (auto & i : paths)
|
||||||
if (isValidPath_(i)) res.insert(i);
|
if (isValidPath_(i)) res.insert(i);
|
||||||
return res;
|
return res;
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PathSet LocalStore::queryAllValidPaths()
|
PathSet LocalStore::queryAllValidPaths()
|
||||||
{
|
{
|
||||||
retry_sqlite {
|
return retrySQLite<PathSet>([&]() {
|
||||||
SQLiteStmt stmt;
|
SQLiteStmt stmt;
|
||||||
stmt.create(db, "select path from ValidPaths");
|
stmt.create(db, "select path from ValidPaths");
|
||||||
|
|
||||||
|
@ -947,7 +956,7 @@ PathSet LocalStore::queryAllValidPaths()
|
||||||
throwSQLiteError(db, "error getting valid paths");
|
throwSQLiteError(db, "error getting valid paths");
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -972,9 +981,9 @@ void LocalStore::queryReferrers_(const Path & path, PathSet & referrers)
|
||||||
void LocalStore::queryReferrers(const Path & path, PathSet & referrers)
|
void LocalStore::queryReferrers(const Path & path, PathSet & referrers)
|
||||||
{
|
{
|
||||||
assertStorePath(path);
|
assertStorePath(path);
|
||||||
retry_sqlite {
|
return retrySQLite<void>([&]() {
|
||||||
queryReferrers_(path, referrers);
|
queryReferrers_(path, referrers);
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -988,7 +997,7 @@ PathSet LocalStore::queryValidDerivers(const Path & path)
|
||||||
{
|
{
|
||||||
assertStorePath(path);
|
assertStorePath(path);
|
||||||
|
|
||||||
retry_sqlite {
|
return retrySQLite<PathSet>([&]() {
|
||||||
SQLiteStmtUse use(stmtQueryValidDerivers);
|
SQLiteStmtUse use(stmtQueryValidDerivers);
|
||||||
stmtQueryValidDerivers.bind(path);
|
stmtQueryValidDerivers.bind(path);
|
||||||
|
|
||||||
|
@ -1004,13 +1013,13 @@ PathSet LocalStore::queryValidDerivers(const Path & path)
|
||||||
throwSQLiteError(db, format("error getting valid derivers of ‘%1%’") % path);
|
throwSQLiteError(db, format("error getting valid derivers of ‘%1%’") % path);
|
||||||
|
|
||||||
return derivers;
|
return derivers;
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PathSet LocalStore::queryDerivationOutputs(const Path & path)
|
PathSet LocalStore::queryDerivationOutputs(const Path & path)
|
||||||
{
|
{
|
||||||
retry_sqlite {
|
return retrySQLite<PathSet>([&]() {
|
||||||
SQLiteStmtUse use(stmtQueryDerivationOutputs);
|
SQLiteStmtUse use(stmtQueryDerivationOutputs);
|
||||||
stmtQueryDerivationOutputs.bind(queryValidPathId(path));
|
stmtQueryDerivationOutputs.bind(queryValidPathId(path));
|
||||||
|
|
||||||
|
@ -1026,13 +1035,13 @@ PathSet LocalStore::queryDerivationOutputs(const Path & path)
|
||||||
throwSQLiteError(db, format("error getting outputs of ‘%1%’") % path);
|
throwSQLiteError(db, format("error getting outputs of ‘%1%’") % path);
|
||||||
|
|
||||||
return outputs;
|
return outputs;
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StringSet LocalStore::queryDerivationOutputNames(const Path & path)
|
StringSet LocalStore::queryDerivationOutputNames(const Path & path)
|
||||||
{
|
{
|
||||||
retry_sqlite {
|
return retrySQLite<StringSet>([&]() {
|
||||||
SQLiteStmtUse use(stmtQueryDerivationOutputs);
|
SQLiteStmtUse use(stmtQueryDerivationOutputs);
|
||||||
stmtQueryDerivationOutputs.bind(queryValidPathId(path));
|
stmtQueryDerivationOutputs.bind(queryValidPathId(path));
|
||||||
|
|
||||||
|
@ -1048,7 +1057,7 @@ StringSet LocalStore::queryDerivationOutputNames(const Path & path)
|
||||||
throwSQLiteError(db, format("error getting output names of ‘%1%’") % path);
|
throwSQLiteError(db, format("error getting output names of ‘%1%’") % path);
|
||||||
|
|
||||||
return outputNames;
|
return outputNames;
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1058,7 +1067,7 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
|
||||||
|
|
||||||
Path prefix = settings.nixStore + "/" + hashPart;
|
Path prefix = settings.nixStore + "/" + hashPart;
|
||||||
|
|
||||||
retry_sqlite {
|
return retrySQLite<Path>([&]() {
|
||||||
SQLiteStmtUse use(stmtQueryPathFromHashPart);
|
SQLiteStmtUse use(stmtQueryPathFromHashPart);
|
||||||
stmtQueryPathFromHashPart.bind(prefix);
|
stmtQueryPathFromHashPart.bind(prefix);
|
||||||
|
|
||||||
|
@ -1068,7 +1077,7 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
|
||||||
|
|
||||||
const char * s = (const char *) sqlite3_column_text(stmtQueryPathFromHashPart, 0);
|
const char * s = (const char *) sqlite3_column_text(stmtQueryPathFromHashPart, 0);
|
||||||
return s && prefix.compare(0, prefix.size(), s, prefix.size()) == 0 ? s : "";
|
return s && prefix.compare(0, prefix.size(), s, prefix.size()) == 0 ? s : "";
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1291,7 +1300,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
|
||||||
* expense of some speed of the path registering operation. */
|
* expense of some speed of the path registering operation. */
|
||||||
if (settings.syncBeforeRegistering) sync();
|
if (settings.syncBeforeRegistering) sync();
|
||||||
|
|
||||||
retry_sqlite {
|
return retrySQLite<void>([&]() {
|
||||||
SQLiteTxn txn(db);
|
SQLiteTxn txn(db);
|
||||||
PathSet paths;
|
PathSet paths;
|
||||||
|
|
||||||
|
@ -1328,7 +1337,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
|
||||||
topoSortPaths(paths);
|
topoSortPaths(paths);
|
||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1712,7 +1721,7 @@ void LocalStore::invalidatePathChecked(const Path & path)
|
||||||
{
|
{
|
||||||
assertStorePath(path);
|
assertStorePath(path);
|
||||||
|
|
||||||
retry_sqlite {
|
retrySQLite<void>([&]() {
|
||||||
SQLiteTxn txn(db);
|
SQLiteTxn txn(db);
|
||||||
|
|
||||||
if (isValidPath_(path)) {
|
if (isValidPath_(path)) {
|
||||||
|
@ -1725,7 +1734,7 @@ void LocalStore::invalidatePathChecked(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
} end_retry_sqlite;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue