Skip to content

Commit 09d8dd7

Browse files
committed
RemoteFSAccessor: Make the local NAR cache content-addressed
1 parent afcd329 commit 09d8dd7

2 files changed

Lines changed: 52 additions & 40 deletions

File tree

src/libstore/include/nix/store/remote-fs-accessor.hh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,13 @@ class RemoteFSAccessor : public SourceAccessor
2121

2222
friend struct BinaryCacheStore;
2323

24-
std::filesystem::path makeCacheFile(std::string_view hashPart, const std::string & ext);
24+
std::filesystem::path makeCacheFile(const Hash & narHash, const std::string & ext);
2525

26-
ref<SourceAccessor> addToCache(std::string_view hashPart, std::string && nar);
26+
ref<SourceAccessor> addToCache(
27+
std::string_view hashPart,
28+
const std::filesystem::path & cacheFile,
29+
const std::filesystem::path & listingFile,
30+
std::string && nar);
2731

2832
public:
2933

src/libstore/remote-fs-accessor.cc

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,22 @@ RemoteFSAccessor::RemoteFSAccessor(ref<Store> store, bool requireValidPath, std:
1717
createDirs(cacheDir);
1818
}
1919

20-
std::filesystem::path RemoteFSAccessor::makeCacheFile(std::string_view hashPart, const std::string & ext)
20+
std::filesystem::path RemoteFSAccessor::makeCacheFile(const Hash & narHash, const std::string & ext)
2121
{
2222
assert(!cacheDir.empty());
23-
return (cacheDir / hashPart) + "." + ext;
23+
return (cacheDir / narHash.to_string(HashFormat::Nix32, false)) + "." + ext;
2424
}
2525

26-
ref<SourceAccessor> RemoteFSAccessor::addToCache(std::string_view hashPart, std::string && nar)
26+
ref<SourceAccessor> RemoteFSAccessor::addToCache(
27+
std::string_view hashPart,
28+
const std::filesystem::path & cacheFile,
29+
const std::filesystem::path & listingFile,
30+
std::string && nar)
2731
{
28-
if (!cacheDir.empty()) {
32+
if (!cacheFile.empty()) {
2933
try {
3034
/* FIXME: do this asynchronously. */
31-
writeFile(makeCacheFile(hashPart, "nar"), nar);
35+
writeFile(cacheFile, nar);
3236
} catch (...) {
3337
ignoreExceptionExceptInterrupt();
3438
}
@@ -37,10 +41,10 @@ ref<SourceAccessor> RemoteFSAccessor::addToCache(std::string_view hashPart, std:
3741
auto narAccessor = makeNarAccessor(std::move(nar));
3842
nars.emplace(hashPart, narAccessor);
3943

40-
if (!cacheDir.empty()) {
44+
if (!listingFile.empty()) {
4145
try {
4246
nlohmann::json j = listNar(narAccessor, CanonPath::root, true);
43-
writeFile(makeCacheFile(hashPart, "ls"), j.dump());
47+
writeFile(listingFile, j.dump());
4448
} catch (...) {
4549
ignoreExceptionExceptInterrupt();
4650
}
@@ -63,51 +67,55 @@ std::shared_ptr<SourceAccessor> RemoteFSAccessor::accessObject(const StorePath &
6367
if (i != nars.end())
6468
return i->second;
6569

66-
std::string listing;
67-
std::filesystem::path cacheFile;
68-
69-
if (!cacheDir.empty() && nix::pathExists(cacheFile = makeCacheFile(storePath.hashPart(), "nar"))) {
70-
71-
try {
72-
listing = nix::readFile(makeCacheFile(storePath.hashPart(), "ls"));
70+
std::filesystem::path cacheFile, listingFile;
7371

74-
auto narAccessor = makeLazyNarAccessor(listing, [cacheFile](uint64_t offset, uint64_t length) {
75-
AutoCloseFD fd = toDescriptor(open(
76-
cacheFile.c_str(),
77-
O_RDONLY
72+
if (!cacheDir.empty()) {
73+
auto info = store->queryPathInfo(storePath);
74+
75+
cacheFile = makeCacheFile(info->narHash, "nar");
76+
listingFile = makeCacheFile(info->narHash, "ls");
77+
78+
if (nix::pathExists(cacheFile)) {
79+
try {
80+
auto listing = nix::readFile(listingFile);
81+
auto narAccessor = makeLazyNarAccessor(listing, [cacheFile](uint64_t offset, uint64_t length) {
82+
AutoCloseFD fd = toDescriptor(open(
83+
cacheFile.c_str(),
84+
O_RDONLY
7885
#ifndef _WIN32
79-
| O_CLOEXEC
86+
| O_CLOEXEC
8087
#endif
81-
));
82-
if (!fd)
83-
throw SysError("opening NAR cache file '%s'", cacheFile);
88+
));
89+
if (!fd)
90+
throw SysError("opening NAR cache file '%s'", cacheFile);
8491

85-
if (lseek(fromDescriptorReadOnly(fd.get()), offset, SEEK_SET) != (off_t) offset)
86-
throw SysError("seeking in '%s'", cacheFile);
92+
if (lseek(fromDescriptorReadOnly(fd.get()), offset, SEEK_SET) != (off_t) offset)
93+
throw SysError("seeking in '%s'", cacheFile);
8794

88-
std::string buf(length, 0);
89-
readFull(fd.get(), buf.data(), length);
95+
std::string buf(length, 0);
96+
readFull(fd.get(), buf.data(), length);
9097

91-
return buf;
92-
});
98+
return buf;
99+
});
93100

94-
nars.emplace(storePath.hashPart(), narAccessor);
95-
return narAccessor;
101+
nars.emplace(storePath.hashPart(), narAccessor);
102+
return narAccessor;
96103

97-
} catch (SystemError &) {
98-
}
104+
} catch (SystemError &) {
105+
}
99106

100-
try {
101-
auto narAccessor = makeNarAccessor(nix::readFile(cacheFile));
102-
nars.emplace(storePath.hashPart(), narAccessor);
103-
return narAccessor;
104-
} catch (SystemError &) {
107+
try {
108+
auto narAccessor = makeNarAccessor(nix::readFile(cacheFile));
109+
nars.emplace(storePath.hashPart(), narAccessor);
110+
return narAccessor;
111+
} catch (SystemError &) {
112+
}
105113
}
106114
}
107115

108116
StringSink sink;
109117
store->narFromPath(storePath, sink);
110-
return addToCache(storePath.hashPart(), std::move(sink.s));
118+
return addToCache(storePath.hashPart(), cacheFile, listingFile, std::move(sink.s));
111119
}
112120

113121
std::optional<SourceAccessor::Stat> RemoteFSAccessor::maybeLstat(const CanonPath & path)

0 commit comments

Comments
 (0)