diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc index ed2f18ffe..13b67b81f 100644 --- a/src/libstore/nar-info-disk-cache.cc +++ b/src/libstore/nar-info-disk-cache.cc @@ -36,6 +36,11 @@ create table if not exists NARs ( foreign key (cache) references BinaryCaches(id) on delete cascade ); +create table if not exists LastPurge ( + dummy text primary key, + value integer +); + )sql"; class NarInfoDiskCacheImpl : public NarInfoDiskCache @@ -46,6 +51,9 @@ public: const int ttlNegative = 3600; const int ttlPositive = 30 * 24 * 3600; + /* How often to purge expired entries from the cache. */ + const int purgeInterval = 24 * 3600; + struct Cache { int id; @@ -57,7 +65,7 @@ public: struct State { SQLite db; - SQLiteStmt insertCache, queryCache, insertNAR, insertMissingNAR, queryNAR; + SQLiteStmt insertCache, queryCache, insertNAR, insertMissingNAR, queryNAR, purgeCache; std::map caches; }; @@ -96,6 +104,27 @@ public: state->queryNAR.create(state->db, "select * from NARs where cache = ? and hashPart = ? and ((present = 0 and timestamp > ?) or (present = 1 and timestamp > ?))"); + + /* Periodically purge expired entries from the database. */ + auto now = time(0); + + SQLiteStmt queryLastPurge(state->db, "select value from LastPurge"); + auto queryLastPurge_(queryLastPurge.use()); + + if (!queryLastPurge_.next() || queryLastPurge_.getInt(0) < now - purgeInterval) { + SQLiteStmt(state->db, + "delete from NARs where ((present = 0 and timestamp < ?) or (present = 1 and timestamp < ?))") + .use() + (now - ttlNegative) + (now - ttlPositive) + .exec(); + + debug("deleted %d entries from the NAR info disk cache", sqlite3_changes(state->db)); + + SQLiteStmt(state->db, + "insert or replace into LastPurge(dummy, value) values ('', ?)") + .use()(now).exec(); + } } Cache & getCache(State & state, const std::string & uri) diff --git a/src/libstore/sqlite.hh b/src/libstore/sqlite.hh index 7c1ed5382..4d347a2e5 100644 --- a/src/libstore/sqlite.hh +++ b/src/libstore/sqlite.hh @@ -31,6 +31,7 @@ struct SQLiteStmt sqlite3 * db = 0; sqlite3_stmt * stmt = 0; SQLiteStmt() { } + SQLiteStmt(sqlite3 * db, const std::string & s) { create(db, s); } void create(sqlite3 * db, const std::string & s); ~SQLiteStmt(); operator sqlite3_stmt * () { return stmt; }