aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/nar-info-disk-cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/nar-info-disk-cache.cc')
-rw-r--r--src/libstore/nar-info-disk-cache.cc47
1 files changed, 31 insertions, 16 deletions
diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc
index 1bb9201e9..8d4a21daf 100644
--- a/src/libstore/nar-info-disk-cache.cc
+++ b/src/libstore/nar-info-disk-cache.cc
@@ -62,6 +62,9 @@ public:
/* How often to purge expired entries from the cache. */
const int purgeInterval = 24 * 3600;
+ /* How long to cache binary cache info (i.e. /nix-cache-info) */
+ const int cacheInfoTtl = 7 * 24 * 3600;
+
struct Cache
{
int id;
@@ -98,7 +101,7 @@ public:
"insert or replace into BinaryCaches(url, timestamp, storeDir, wantMassQuery, priority) values (?, ?, ?, ?, ?)");
state->queryCache.create(state->db,
- "select id, storeDir, wantMassQuery, priority from BinaryCaches where url = ?");
+ "select id, storeDir, wantMassQuery, priority from BinaryCaches where url = ? and timestamp > ?");
state->insertNAR.create(state->db,
"insert or replace into NARs(cache, hashPart, namePart, url, compression, fileHash, fileSize, narHash, "
@@ -163,16 +166,37 @@ public:
return i->second;
}
+ std::optional<Cache> queryCacheRaw(State & state, const std::string & uri)
+ {
+ auto i = state.caches.find(uri);
+ if (i == state.caches.end()) {
+ auto queryCache(state.queryCache.use()(uri)(time(0) - cacheInfoTtl));
+ if (!queryCache.next())
+ return std::nullopt;
+ state.caches.emplace(uri,
+ Cache{(int) queryCache.getInt(0), queryCache.getStr(1), queryCache.getInt(2) != 0, (int) queryCache.getInt(3)});
+ }
+ return getCache(state, uri);
+ }
+
void createCache(const std::string & uri, const Path & storeDir, bool wantMassQuery, int priority) override
{
retrySQLite<void>([&]() {
auto state(_state.lock());
+ SQLiteTxn txn(state->db);
+
+ // To avoid the race, we have to check if maybe someone hasn't yet created
+ // the cache for this URI in the meantime.
+ auto cache(queryCacheRaw(*state, uri));
- // FIXME: race
+ if (cache)
+ return;
state->insertCache.use()(uri)(time(0))(storeDir)(wantMassQuery)(priority).exec();
assert(sqlite3_changes(state->db) == 1);
state->caches[uri] = Cache{(int) sqlite3_last_insert_rowid(state->db), storeDir, wantMassQuery, priority};
+
+ txn.commit();
});
}
@@ -180,21 +204,12 @@ public:
{
return retrySQLite<std::optional<CacheInfo>>([&]() -> std::optional<CacheInfo> {
auto state(_state.lock());
-
- auto i = state->caches.find(uri);
- if (i == state->caches.end()) {
- auto queryCache(state->queryCache.use()(uri));
- if (!queryCache.next())
- return std::nullopt;
- state->caches.emplace(uri,
- Cache{(int) queryCache.getInt(0), queryCache.getStr(1), queryCache.getInt(2) != 0, (int) queryCache.getInt(3)});
- }
-
- auto & cache(getCache(*state, uri));
-
+ auto cache(queryCacheRaw(*state, uri));
+ if (!cache)
+ return std::nullopt;
return CacheInfo {
- .wantMassQuery = cache.wantMassQuery,
- .priority = cache.priority
+ .wantMassQuery = cache->wantMassQuery,
+ .priority = cache->priority
};
});
}