Skip to content

Commit 5dafde2

Browse files
committed
BinaryCacheStore: Add index-debug-info option
This integrates the functionality of the index-debuginfo program in nixos-channel-scripts to maintain an index of DWARF debuginfo files in a format usable by dwarffs. Thus the debug info index is updated by Hydra rather than by the channel mirroring script. Example usage: $ nix copy --to 'file:///tmp/binary-cache?index-debug-info=true' /nix/store/vr9mhcch3fljzzkjld3kvkggvpq38cva-nix-2.2.2-debug $ cat /tmp/binary-cache/debuginfo/036b210b03bad75ab2d8fc80b7a146f98e7f1ecf.debug {"archive":"../nar/0313h2kdhk4v73xna9ysiksp2v8xrsk5xsw79mmwr3rg7byb4ka8.nar.xz","member":"lib/debug/.build-id/03/6b210b03bad75ab2d8fc80b7a146f98e7f1ecf.debug"} Fixes #3083.
1 parent d20f814 commit 5dafde2

File tree

3 files changed

+71
-12
lines changed

3 files changed

+71
-12
lines changed

src/libstore/binary-cache-store.cc

+68-12
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
#include "nar-info-disk-cache.hh"
1111
#include "nar-accessor.hh"
1212
#include "json.hh"
13+
#include "thread-pool.hh"
1314

1415
#include <chrono>
15-
1616
#include <future>
17+
#include <regex>
18+
19+
#include <nlohmann/json.hpp>
1720

1821
namespace nix {
1922

@@ -139,6 +142,11 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
139142

140143
auto accessor_ = std::dynamic_pointer_cast<RemoteFSAccessor>(accessor);
141144

145+
auto narAccessor = makeNarAccessor(nar);
146+
147+
if (accessor_)
148+
accessor_->addToCache(info.path, *nar, narAccessor);
149+
142150
/* Optionally write a JSON file containing a listing of the
143151
contents of the NAR. */
144152
if (writeNARListing) {
@@ -148,11 +156,6 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
148156
JSONObject jsonRoot(jsonOut);
149157
jsonRoot.attr("version", 1);
150158

151-
auto narAccessor = makeNarAccessor(nar);
152-
153-
if (accessor_)
154-
accessor_->addToCache(info.path, *nar, narAccessor);
155-
156159
{
157160
auto res = jsonRoot.placeholder("root");
158161
listNar(res, narAccessor, "", true);
@@ -162,11 +165,6 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
162165
upsertFile(storePathToHash(info.path) + ".ls", jsonOut.str(), "application/json");
163166
}
164167

165-
else {
166-
if (accessor_)
167-
accessor_->addToCache(info.path, *nar, makeNarAccessor(nar));
168-
}
169-
170168
/* Compress the NAR. */
171169
narInfo->compression = compression;
172170
auto now1 = std::chrono::steady_clock::now();
@@ -181,12 +179,70 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
181179
% ((1.0 - (double) narCompressed->size() / nar->size()) * 100.0)
182180
% duration);
183181

184-
/* Atomically write the NAR file. */
185182
narInfo->url = "nar/" + narInfo->fileHash.to_string(Base32, false) + ".nar"
186183
+ (compression == "xz" ? ".xz" :
187184
compression == "bzip2" ? ".bz2" :
188185
compression == "br" ? ".br" :
189186
"");
187+
188+
/* Optionally maintain an index of DWARF debug info files
189+
consisting of JSON files named 'debuginfo/<build-id>' that
190+
specify the NAR file and member containing the debug info. */
191+
if (writeDebugInfo) {
192+
193+
std::string buildIdDir = "/lib/debug/.build-id";
194+
195+
if (narAccessor->stat(buildIdDir).type == FSAccessor::tDirectory) {
196+
197+
ThreadPool threadPool(25);
198+
199+
auto doFile = [&](std::string member, std::string key, std::string target) {
200+
checkInterrupt();
201+
202+
nlohmann::json json;
203+
json["archive"] = target;
204+
json["member"] = member;
205+
206+
// FIXME: or should we overwrite? The previous link may point
207+
// to a GC'ed file, so overwriting might be useful...
208+
if (fileExists(key)) return;
209+
210+
printMsg(lvlTalkative, "creating debuginfo link from '%s' to '%s'", key, target);
211+
212+
upsertFile(key, json.dump(), "application/json");
213+
};
214+
215+
std::regex regex1("^[0-9a-f]{2}$");
216+
std::regex regex2("^[0-9a-f]{38}\\.debug$");
217+
218+
for (auto & s1 : narAccessor->readDirectory(buildIdDir)) {
219+
auto dir = buildIdDir + "/" + s1;
220+
221+
if (narAccessor->stat(dir).type != FSAccessor::tDirectory
222+
|| !std::regex_match(s1, regex1))
223+
continue;
224+
225+
for (auto & s2 : narAccessor->readDirectory(dir)) {
226+
auto debugPath = dir + "/" + s2;
227+
228+
if (narAccessor->stat(debugPath).type != FSAccessor::tRegular
229+
|| !std::regex_match(s2, regex2))
230+
continue;
231+
232+
auto buildId = s1 + s2;
233+
234+
std::string key = "debuginfo/" + buildId;
235+
std::string target = "../" + narInfo->url;
236+
237+
threadPool.enqueue(std::bind(doFile, std::string(debugPath, 1), key, target));
238+
}
239+
}
240+
241+
threadPool.process();
242+
}
243+
}
244+
245+
/* Atomically write the NAR file. */
190246
if (repair || !fileExists(narInfo->url)) {
191247
stats.narWrite++;
192248
upsertFile(narInfo->url, *narCompressed, "application/x-nix-nar");

src/libstore/binary-cache-store.hh

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public:
1717

1818
const Setting<std::string> compression{this, "xz", "compression", "NAR compression method ('xz', 'bzip2', or 'none')"};
1919
const Setting<bool> writeNARListing{this, false, "write-nar-listing", "whether to write a JSON file listing the files in each NAR"};
20+
const Setting<bool> writeDebugInfo{this, false, "index-debug-info", "whether to index DWARF debug info files by build ID"};
2021
const Setting<Path> secretKeyFile{this, "", "secret-key", "path to secret key used to sign the binary cache"};
2122
const Setting<Path> localNarCache{this, "", "local-nar-cache", "path to a local cache of NARs"};
2223
const Setting<bool> parallelCompression{this, false, "parallel-compression",

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

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class LocalBinaryCacheStore : public BinaryCacheStore
6363
void LocalBinaryCacheStore::init()
6464
{
6565
createDirs(binaryCacheDir + "/nar");
66+
if (writeDebugInfo)
67+
createDirs(binaryCacheDir + "/debuginfo");
6668
BinaryCacheStore::init();
6769
}
6870

0 commit comments

Comments
 (0)