Skip to content

Commit a565d89

Browse files
authored
Merge pull request #525 from DeterminateSystems/nar-info-disk-cache-generic-fields
NarInfoDiskCache: Support arbitrary nix-cache-info fields
2 parents 3888c31 + 6108e4d commit a565d89

6 files changed

Lines changed: 72 additions & 37 deletions

File tree

src/libstore-tests/nar-info-disk-cache.cc

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ TEST(NarInfoDiskCacheImpl, create_and_read)
1515
int prio = 12345;
1616
bool wantMassQuery = true;
1717

18+
auto mkFields = [](bool wantMassQuery, int prio) {
19+
return std::map<std::string, std::string>{
20+
{"WantMassQuery", wantMassQuery ? "1" : "0"},
21+
{"Priority", std::to_string(prio)},
22+
};
23+
};
24+
1825
auto tmpDir = createTempDir();
1926
AutoDelete delTmpDir(tmpDir);
2027
auto dbPath(tmpDir / "test-narinfo-disk-cache.sqlite");
@@ -30,22 +37,20 @@ TEST(NarInfoDiskCacheImpl, create_and_read)
3037

3138
// Set up "background noise" and check that different caches receive different ids
3239
{
33-
auto bc1 =
34-
cache->createCache("https://bar", "/nix/storedir", {.wantMassQuery = wantMassQuery, .priority = prio});
35-
auto bc2 = cache->createCache("https://xyz", "/nix/storedir", {.priority = 12});
40+
auto bc1 = cache->createCache("https://bar", "/nix/storedir", {.fields = mkFields(wantMassQuery, prio)});
41+
auto bc2 = cache->createCache("https://xyz", "/nix/storedir", {.fields = mkFields(false, 12)});
3642
ASSERT_NE(bc1, bc2);
3743
barId = bc1;
3844
}
3945

4046
// Check that the fields are saved and returned correctly. This does not test
4147
// the select statement yet, because of in-memory caching.
42-
savedId = cache->createCache("http://foo", "/nix/storedir", {.wantMassQuery = wantMassQuery, .priority = prio});
48+
savedId = cache->createCache("http://foo", "/nix/storedir", {.fields = mkFields(wantMassQuery, prio)});
4349
;
4450
{
4551
auto r = cache->upToDateCacheExists("http://foo");
4652
ASSERT_TRUE(r);
47-
ASSERT_EQ(r->priority, prio);
48-
ASSERT_EQ(r->wantMassQuery, wantMassQuery);
53+
ASSERT_EQ(r->fields, mkFields(wantMassQuery, prio));
4954
ASSERT_EQ(savedId, r->id);
5055
}
5156

@@ -68,8 +73,7 @@ TEST(NarInfoDiskCacheImpl, create_and_read)
6873
{
6974
auto r = cache->upToDateCacheExists("http://foo");
7075
ASSERT_TRUE(r);
71-
ASSERT_EQ(r->priority, prio);
72-
ASSERT_EQ(r->wantMassQuery, wantMassQuery);
76+
ASSERT_EQ(r->fields, mkFields(wantMassQuery, prio));
7377
}
7478
}
7579

@@ -85,13 +89,12 @@ TEST(NarInfoDiskCacheImpl, create_and_read)
8589
}
8690

8791
// "Update", same data, check that the id number is reused
88-
cache2->createCache("http://foo", "/nix/storedir", {.wantMassQuery = wantMassQuery, .priority = prio});
92+
cache2->createCache("http://foo", "/nix/storedir", {.fields = mkFields(wantMassQuery, prio)});
8993

9094
{
9195
auto r = cache2->upToDateCacheExists("http://foo");
9296
ASSERT_TRUE(r);
93-
ASSERT_EQ(r->priority, prio);
94-
ASSERT_EQ(r->wantMassQuery, wantMassQuery);
97+
ASSERT_EQ(r->fields, mkFields(wantMassQuery, prio));
9598
ASSERT_EQ(r->id, savedId);
9699
}
97100

@@ -108,11 +111,9 @@ TEST(NarInfoDiskCacheImpl, create_and_read)
108111
auto r0 = cache2->upToDateCacheExists("https://bar");
109112
ASSERT_FALSE(r0);
110113

111-
cache2->createCache(
112-
"https://bar", "/nix/storedir", {.wantMassQuery = !wantMassQuery, .priority = prio + 10});
114+
cache2->createCache("https://bar", "/nix/storedir", {.fields = mkFields(!wantMassQuery, prio + 10)});
113115
auto r = cache2->upToDateCacheExists("https://bar");
114-
ASSERT_EQ(r->wantMassQuery, !wantMassQuery);
115-
ASSERT_EQ(r->priority, prio + 10);
116+
ASSERT_EQ(r->fields, mkFields(!wantMassQuery, prio + 10));
116117
ASSERT_EQ(r->id, barId);
117118
}
118119

src/libstore/binary-cache-store.cc

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ BinaryCacheStore::BinaryCacheStore(Config & config)
4545
narMagic = sink.s;
4646
}
4747

48-
void BinaryCacheStore::init()
48+
std::map<std::string, std::string> BinaryCacheStore::parseNixCacheInfo()
4949
{
50+
std::map<std::string, std::string> fields;
51+
5052
auto cacheInfo = getNixCacheInfo();
5153
if (!cacheInfo) {
5254
upsertFile(cacheInfoFile, "StoreDir: " + storeDir + "\n", "text/x-nix-cache-info");
@@ -64,13 +66,31 @@ void BinaryCacheStore::init()
6466
config.getHumanReadableURI(),
6567
value,
6668
storeDir);
67-
} else if (name == "WantMassQuery") {
68-
config.wantMassQuery.setDefault(value == "1");
69-
} else if (name == "Priority") {
70-
config.priority.setDefault(std::stoi(value));
69+
} else {
70+
/* Keep every other field verbatim, including ones we
71+
don't (yet) understand. The known ones are applied
72+
by applyCacheInfoFields(). */
73+
fields.insert_or_assign(name, value);
7174
}
7275
}
7376
}
77+
78+
return fields;
79+
}
80+
81+
void BinaryCacheStore::applyCacheInfoFields(const std::map<std::string, std::string> & fields)
82+
{
83+
if (auto * value = get(fields, "WantMassQuery"))
84+
config.wantMassQuery.setDefault(*value == "1");
85+
if (auto * value = get(fields, "Priority")) {
86+
if (auto priority = string2Int<int>(*value))
87+
config.priority.setDefault(*priority);
88+
}
89+
}
90+
91+
void BinaryCacheStore::init()
92+
{
93+
applyCacheInfoFields(parseNixCacheInfo());
7494
}
7595

7696
std::optional<std::string> BinaryCacheStore::getNixCacheInfo()

src/libstore/http-binary-cache-store.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,16 @@ void HttpBinaryCacheStore::init()
6969
auto cacheKey = config->getReference().render(/*withParams=*/false);
7070

7171
if (auto cacheInfo = diskCache->upToDateCacheExists(cacheKey)) {
72-
config->wantMassQuery.setDefault(cacheInfo->wantMassQuery);
73-
config->priority.setDefault(cacheInfo->priority);
72+
applyCacheInfoFields(cacheInfo->fields);
7473
} else {
74+
std::map<std::string, std::string> fields;
7575
try {
76-
BinaryCacheStore::init();
76+
fields = parseNixCacheInfo();
7777
} catch (UploadToHTTP &) {
7878
throw Error("'%s' does not appear to be a binary cache", config->cacheUri.to_string());
7979
}
80-
diskCache->createCache(
81-
cacheKey, config->storeDir, {.wantMassQuery = config->wantMassQuery, .priority = config->priority});
80+
applyCacheInfoFields(fields);
81+
diskCache->createCache(cacheKey, config->storeDir, {.fields = std::move(fields)});
8282
}
8383
}
8484

src/libstore/include/nix/store/binary-cache-store.hh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ protected:
9898

9999
BinaryCacheStore(Config &);
100100

101+
/**
102+
* Fetch and parse `nix-cache-info`.
103+
*/
104+
std::map<std::string, std::string> parseNixCacheInfo();
105+
106+
/**
107+
* Apply the known `nix-cache-info` fields from `fields` to this store.
108+
*/
109+
void applyCacheInfoFields(const std::map<std::string, std::string> & fields);
110+
101111
/**
102112
* Compute the path to the given realisation
103113
*

src/libstore/include/nix/store/nar-info-disk-cache.hh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#include "nix/store/nar-info.hh"
66
#include "nix/store/realisation.hh"
77

8+
#include <map>
9+
#include <string>
10+
811
namespace nix {
912

1013
struct SQLiteSettings;
@@ -28,8 +31,13 @@ struct NarInfoDiskCache
2831
struct CacheInfo
2932
{
3033
int id = 0;
31-
bool wantMassQuery = false;
32-
int priority = 0;
34+
35+
/**
36+
* The `nix-cache-info` fields other than `StoreDir`, stored
37+
* verbatim (e.g. `WantMassQuery`). Keeping these generic
38+
* means fields we don't (yet) understand are still recorded.
39+
*/
40+
std::map<std::string, std::string> fields;
3341
};
3442

3543
/**

src/libstore/nar-info-disk-cache.cc

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ create table if not exists BinaryCaches (
1919
url text unique not null,
2020
timestamp integer not null,
2121
storeDir text not null,
22-
wantMassQuery integer not null,
23-
priority integer not null
22+
fields text not null
2423
);
2524
2625
create table if not exists NARs (
@@ -84,7 +83,7 @@ struct NarInfoDiskCacheImpl : NarInfoDiskCache
8483
NarInfoDiskCacheImpl(
8584
const Settings & settings,
8685
SQLiteSettings sqliteSettings,
87-
std::filesystem::path dbPath = getCacheDir() / "binary-cache-detsys-v1.sqlite")
86+
std::filesystem::path dbPath = getCacheDir() / "binary-cache-detsys-v2.sqlite")
8887
: NarInfoDiskCache{settings}
8988
{
9089
auto state(_state.lock());
@@ -99,11 +98,10 @@ struct NarInfoDiskCacheImpl : NarInfoDiskCache
9998

10099
state->insertCache.create(
101100
state->db,
102-
"insert into BinaryCaches(url, timestamp, storeDir, wantMassQuery, priority) values (?1, ?2, ?3, ?4, ?5) on conflict (url) do update set timestamp = ?2, storeDir = ?3, wantMassQuery = ?4, priority = ?5 returning id;");
101+
"insert into BinaryCaches(url, timestamp, storeDir, fields) values (?1, ?2, ?3, ?4) on conflict (url) do update set timestamp = ?2, storeDir = ?3, fields = ?4 returning id;");
103102

104103
state->queryCache.create(
105-
state->db,
106-
"select id, storeDir, wantMassQuery, priority from BinaryCaches where url = ? and timestamp > ?");
104+
state->db, "select id, storeDir, fields from BinaryCaches where url = ? and timestamp > ?");
107105

108106
state->insertNAR.create(
109107
state->db,
@@ -193,8 +191,7 @@ struct NarInfoDiskCacheImpl : NarInfoDiskCache
193191
.storeDir = queryCache.getStr(1),
194192
.info = {
195193
.id = (int) queryCache.getInt(0),
196-
.wantMassQuery = queryCache.getInt(2) != 0,
197-
.priority = (int) queryCache.getInt(3),
194+
.fields = nlohmann::json::parse(queryCache.getStr(2)).get<std::map<std::string, std::string>>(),
198195
}};
199196
state.caches.emplace(uri, cache);
200197
}
@@ -222,8 +219,7 @@ struct NarInfoDiskCacheImpl : NarInfoDiskCache
222219
.apply(uri)
223220
.apply(time(nullptr))
224221
.apply(storeDir)
225-
.apply(info.wantMassQuery)
226-
.apply(info.priority));
222+
.apply(nlohmann::json(info.fields).dump()));
227223
if (!r.next()) {
228224
unreachable();
229225
}

0 commit comments

Comments
 (0)