aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-07-14 15:17:38 +0200
committerEelco Dolstra <edolstra@gmail.com>2020-07-14 15:17:38 +0200
commitda3aea291da2519e54cb897c5b3ca02eb00d688c (patch)
treed683b23b543740abe5f77f2bff9b98c277e5e275 /src
parent832e111494d2d3acf3f919376d0f2765042946cc (diff)
EvalCache: Ignore SQLite errors
Fixes #3794.
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/eval-cache.cc191
-rw-r--r--src/libexpr/flake/flake.cc1
2 files changed, 119 insertions, 73 deletions
diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc
index 65a3fceeb..919de8a4e 100644
--- a/src/libexpr/eval-cache.cc
+++ b/src/libexpr/eval-cache.cc
@@ -19,6 +19,8 @@ create table if not exists Attributes (
struct AttrDb
{
+ std::atomic_bool failed{false};
+
struct State
{
SQLite db;
@@ -64,36 +66,53 @@ struct AttrDb
{
try {
auto state(_state->lock());
- state->txn->commit();
+ if (!failed)
+ state->txn->commit();
state->txn.reset();
} catch (...) {
ignoreException();
}
}
+ template<typename F>
+ AttrId doSQLite(F && fun)
+ {
+ if (failed) return 0;
+ try {
+ return fun();
+ } catch (SQLiteError &) {
+ ignoreException();
+ failed = true;
+ return 0;
+ }
+ }
+
AttrId setAttrs(
AttrKey key,
const std::vector<Symbol> & attrs)
{
- auto state(_state->lock());
-
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::FullAttrs)
- (0, false).exec();
-
- AttrId rowId = state->db.getLastInsertedRowId();
- assert(rowId);
+ return doSQLite([&]()
+ {
+ auto state(_state->lock());
- for (auto & attr : attrs)
state->insertAttribute.use()
- (rowId)
- (attr)
- (AttrType::Placeholder)
+ (key.first)
+ (key.second)
+ (AttrType::FullAttrs)
(0, false).exec();
- return rowId;
+ AttrId rowId = state->db.getLastInsertedRowId();
+ assert(rowId);
+
+ for (auto & attr : attrs)
+ state->insertAttribute.use()
+ (rowId)
+ (attr)
+ (AttrType::Placeholder)
+ (0, false).exec();
+
+ return rowId;
+ });
}
AttrId setString(
@@ -101,96 +120,114 @@ struct AttrDb
std::string_view s,
const char * * context = nullptr)
{
- auto state(_state->lock());
+ return doSQLite([&]()
+ {
+ auto state(_state->lock());
- if (context) {
- std::string ctx;
- for (const char * * p = context; *p; ++p) {
- if (p != context) ctx.push_back(' ');
- ctx.append(*p);
- }
- state->insertAttributeWithContext.use()
- (key.first)
- (key.second)
- (AttrType::String)
- (s)
- (ctx).exec();
- } else {
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::String)
+ if (context) {
+ std::string ctx;
+ for (const char * * p = context; *p; ++p) {
+ if (p != context) ctx.push_back(' ');
+ ctx.append(*p);
+ }
+ state->insertAttributeWithContext.use()
+ (key.first)
+ (key.second)
+ (AttrType::String)
+ (s)
+ (ctx).exec();
+ } else {
+ state->insertAttribute.use()
+ (key.first)
+ (key.second)
+ (AttrType::String)
(s).exec();
- }
+ }
- return state->db.getLastInsertedRowId();
+ return state->db.getLastInsertedRowId();
+ });
}
AttrId setBool(
AttrKey key,
bool b)
{
- auto state(_state->lock());
+ return doSQLite([&]()
+ {
+ auto state(_state->lock());
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::Bool)
- (b ? 1 : 0).exec();
+ state->insertAttribute.use()
+ (key.first)
+ (key.second)
+ (AttrType::Bool)
+ (b ? 1 : 0).exec();
- return state->db.getLastInsertedRowId();
+ return state->db.getLastInsertedRowId();
+ });
}
AttrId setPlaceholder(AttrKey key)
{
- auto state(_state->lock());
+ return doSQLite([&]()
+ {
+ auto state(_state->lock());
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::Placeholder)
- (0, false).exec();
+ state->insertAttribute.use()
+ (key.first)
+ (key.second)
+ (AttrType::Placeholder)
+ (0, false).exec();
- return state->db.getLastInsertedRowId();
+ return state->db.getLastInsertedRowId();
+ });
}
AttrId setMissing(AttrKey key)
{
- auto state(_state->lock());
+ return doSQLite([&]()
+ {
+ auto state(_state->lock());
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::Missing)
- (0, false).exec();
+ state->insertAttribute.use()
+ (key.first)
+ (key.second)
+ (AttrType::Missing)
+ (0, false).exec();
- return state->db.getLastInsertedRowId();
+ return state->db.getLastInsertedRowId();
+ });
}
AttrId setMisc(AttrKey key)
{
- auto state(_state->lock());
+ return doSQLite([&]()
+ {
+ auto state(_state->lock());
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::Misc)
- (0, false).exec();
+ state->insertAttribute.use()
+ (key.first)
+ (key.second)
+ (AttrType::Misc)
+ (0, false).exec();
- return state->db.getLastInsertedRowId();
+ return state->db.getLastInsertedRowId();
+ });
}
AttrId setFailed(AttrKey key)
{
- auto state(_state->lock());
+ return doSQLite([&]()
+ {
+ auto state(_state->lock());
- state->insertAttribute.use()
- (key.first)
- (key.second)
- (AttrType::Failed)
- (0, false).exec();
+ state->insertAttribute.use()
+ (key.first)
+ (key.second)
+ (AttrType::Failed)
+ (0, false).exec();
- return state->db.getLastInsertedRowId();
+ return state->db.getLastInsertedRowId();
+ });
}
std::optional<std::pair<AttrId, AttrValue>> getAttr(
@@ -237,12 +274,22 @@ struct AttrDb
}
};
+static std::shared_ptr<AttrDb> makeAttrDb(const Hash & fingerprint)
+{
+ try {
+ return std::make_shared<AttrDb>(fingerprint);
+ } catch (SQLiteError &) {
+ ignoreException();
+ return nullptr;
+ }
+}
+
EvalCache::EvalCache(
bool useCache,
const Hash & fingerprint,
EvalState & state,
RootLoader rootLoader)
- : db(useCache ? std::make_shared<AttrDb>(fingerprint) : nullptr)
+ : db(useCache ? makeAttrDb(fingerprint) : nullptr)
, state(state)
, rootLoader(rootLoader)
{
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index fd168b74f..01f464859 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -63,7 +63,6 @@ static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
debug("got tree '%s' from '%s'",
state.store->printStorePath(tree.storePath), lockedRef);
-
if (state.allowedPaths)
state.allowedPaths->insert(tree.actualPath);