diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2016-03-30 12:04:27 +0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2016-03-30 12:04:27 +0200 |
commit | 2ae43ced9a907b16244245761f67e10bce925171 (patch) | |
tree | 07d602aad58cfe9cdfcb7ee808ed44389d567492 /src/libstore/local-store.cc | |
parent | 39a6abc0bc2f1986f29e52de15ccbdde9586bc08 (diff) |
Turn retrying SQLite transactions into a higher-order function
Diffstat (limited to 'src/libstore/local-store.cc')
-rw-r--r-- | src/libstore/local-store.cc | 75 |
1 files changed, 42 insertions, 33 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 3d10b3387..3b86f9b8a 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -70,9 +70,18 @@ MakeError(SQLiteBusy, SQLiteError); } -/* Convenience macros for retrying a SQLite transaction. */ -#define retry_sqlite while (1) { try { -#define end_retry_sqlite break; } catch (SQLiteBusy & e) { } } +/* Convenience function for retrying a SQLite transaction when the + database is busy. */ +template<typename T> +T retrySQLite(std::function<T()> fun) +{ + while (true) { + try { + return fun(); + } catch (SQLiteBusy & e) { + } + } +} SQLite::~SQLite() @@ -746,32 +755,32 @@ void LocalStore::addReference(unsigned long long referrer, unsigned long long re void LocalStore::registerFailedPath(const Path & path) { - retry_sqlite { + retrySQLite<void>([&]() { SQLiteStmtUse use(stmtRegisterFailedPath); stmtRegisterFailedPath.bind(path); stmtRegisterFailedPath.bind(time(0)); if (sqlite3_step(stmtRegisterFailedPath) != SQLITE_DONE) throwSQLiteError(db, format("registering failed path ‘%1%’") % path); - } end_retry_sqlite; + }); } bool LocalStore::hasPathFailed(const Path & path) { - retry_sqlite { + return retrySQLite<bool>([&]() { SQLiteStmtUse use(stmtHasPathFailed); stmtHasPathFailed.bind(path); int res = sqlite3_step(stmtHasPathFailed); if (res != SQLITE_DONE && res != SQLITE_ROW) throwSQLiteError(db, "querying whether path failed"); return res == SQLITE_ROW; - } end_retry_sqlite; + }); } PathSet LocalStore::queryFailedPaths() { - retry_sqlite { + return retrySQLite<PathSet>([&]() { SQLiteStmtUse use(stmtQueryFailedPaths); PathSet res; @@ -786,13 +795,13 @@ PathSet LocalStore::queryFailedPaths() throwSQLiteError(db, "error querying failed paths"); return res; - } end_retry_sqlite; + }); } void LocalStore::clearFailedPaths(const PathSet & paths) { - retry_sqlite { + retrySQLite<void>([&]() { SQLiteTxn txn(db); for (auto & i : paths) { @@ -803,7 +812,7 @@ void LocalStore::clearFailedPaths(const PathSet & paths) } txn.commit(); - } end_retry_sqlite; + }); } @@ -828,7 +837,7 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path) assertStorePath(path); - retry_sqlite { + return retrySQLite<ValidPathInfo>([&]() { /* Get the path info. */ SQLiteStmtUse use1(stmtQueryPathInfo); @@ -868,7 +877,7 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path) throwSQLiteError(db, format("error getting references of ‘%1%’") % path); return info; - } end_retry_sqlite; + }); } @@ -912,26 +921,26 @@ bool LocalStore::isValidPath_(const Path & path) bool LocalStore::isValidPath(const Path & path) { - retry_sqlite { + return retrySQLite<bool>([&]() { return isValidPath_(path); - } end_retry_sqlite; + }); } PathSet LocalStore::queryValidPaths(const PathSet & paths) { - retry_sqlite { + return retrySQLite<PathSet>([&]() { PathSet res; for (auto & i : paths) if (isValidPath_(i)) res.insert(i); return res; - } end_retry_sqlite; + }); } PathSet LocalStore::queryAllValidPaths() { - retry_sqlite { + return retrySQLite<PathSet>([&]() { SQLiteStmt stmt; stmt.create(db, "select path from ValidPaths"); @@ -947,7 +956,7 @@ PathSet LocalStore::queryAllValidPaths() throwSQLiteError(db, "error getting valid paths"); 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) { assertStorePath(path); - retry_sqlite { + return retrySQLite<void>([&]() { queryReferrers_(path, referrers); - } end_retry_sqlite; + }); } @@ -988,7 +997,7 @@ PathSet LocalStore::queryValidDerivers(const Path & path) { assertStorePath(path); - retry_sqlite { + return retrySQLite<PathSet>([&]() { SQLiteStmtUse use(stmtQueryValidDerivers); stmtQueryValidDerivers.bind(path); @@ -1004,13 +1013,13 @@ PathSet LocalStore::queryValidDerivers(const Path & path) throwSQLiteError(db, format("error getting valid derivers of ‘%1%’") % path); return derivers; - } end_retry_sqlite; + }); } PathSet LocalStore::queryDerivationOutputs(const Path & path) { - retry_sqlite { + return retrySQLite<PathSet>([&]() { SQLiteStmtUse use(stmtQueryDerivationOutputs); stmtQueryDerivationOutputs.bind(queryValidPathId(path)); @@ -1026,13 +1035,13 @@ PathSet LocalStore::queryDerivationOutputs(const Path & path) throwSQLiteError(db, format("error getting outputs of ‘%1%’") % path); return outputs; - } end_retry_sqlite; + }); } StringSet LocalStore::queryDerivationOutputNames(const Path & path) { - retry_sqlite { + return retrySQLite<StringSet>([&]() { SQLiteStmtUse use(stmtQueryDerivationOutputs); stmtQueryDerivationOutputs.bind(queryValidPathId(path)); @@ -1048,7 +1057,7 @@ StringSet LocalStore::queryDerivationOutputNames(const Path & path) throwSQLiteError(db, format("error getting output names of ‘%1%’") % path); return outputNames; - } end_retry_sqlite; + }); } @@ -1058,7 +1067,7 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart) Path prefix = settings.nixStore + "/" + hashPart; - retry_sqlite { + return retrySQLite<Path>([&]() { SQLiteStmtUse use(stmtQueryPathFromHashPart); stmtQueryPathFromHashPart.bind(prefix); @@ -1068,7 +1077,7 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart) const char * s = (const char *) sqlite3_column_text(stmtQueryPathFromHashPart, 0); 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. */ if (settings.syncBeforeRegistering) sync(); - retry_sqlite { + return retrySQLite<void>([&]() { SQLiteTxn txn(db); PathSet paths; @@ -1328,7 +1337,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) topoSortPaths(paths); txn.commit(); - } end_retry_sqlite; + }); } @@ -1712,7 +1721,7 @@ void LocalStore::invalidatePathChecked(const Path & path) { assertStorePath(path); - retry_sqlite { + retrySQLite<void>([&]() { SQLiteTxn txn(db); if (isValidPath_(path)) { @@ -1725,7 +1734,7 @@ void LocalStore::invalidatePathChecked(const Path & path) } txn.commit(); - } end_retry_sqlite; + }); } |