4
4
#include " nix/util/memory-source-accessor.hh"
5
5
#include " nix/store/dummy-store.hh"
6
6
7
+ #include < boost/unordered/concurrent_flat_map.hpp>
8
+
7
9
namespace nix {
8
10
9
11
std::string DummyStoreConfig::doc ()
@@ -13,6 +15,99 @@ std::string DummyStoreConfig::doc()
13
15
;
14
16
}
15
17
18
+ namespace {
19
+
20
+ class WholeStoreViewAccessor : public SourceAccessor
21
+ {
22
+ using BaseName = std::string;
23
+
24
+ /* *
25
+ * Map from store path basenames to corresponding accessors.
26
+ */
27
+ boost::concurrent_flat_map<BaseName, ref<MemorySourceAccessor>> subdirs;
28
+
29
+ /* *
30
+ * Helper accessor for accessing just the CanonPath::root.
31
+ */
32
+ MemorySourceAccessor rootPathAccessor;
33
+
34
+ /* *
35
+ * Helper empty accessor.
36
+ */
37
+ MemorySourceAccessor emptyAccessor;
38
+
39
+ auto
40
+ callWithAccessorForPath (CanonPath path, std::invocable<MemorySourceAccessor &, const CanonPath &> auto callback)
41
+ {
42
+ if (path.isRoot ())
43
+ return callback (rootPathAccessor, path);
44
+
45
+ BaseName baseName (*path.begin ());
46
+ MemorySourceAccessor * res = nullptr ;
47
+
48
+ subdirs.cvisit (baseName, [&](const auto & kv) {
49
+ path = path.removePrefix (CanonPath{baseName});
50
+ res = &*kv.second ;
51
+ });
52
+
53
+ if (!res)
54
+ res = &emptyAccessor;
55
+
56
+ return callback (*res, path);
57
+ }
58
+
59
+ public:
60
+ WholeStoreViewAccessor ()
61
+ {
62
+ MemorySink sink{rootPathAccessor};
63
+ sink.createDirectory (CanonPath::root);
64
+ }
65
+
66
+ void addObject (std::string_view baseName, ref<MemorySourceAccessor> accessor)
67
+ {
68
+ subdirs.emplace (baseName, std::move (accessor));
69
+ }
70
+
71
+ std::string readFile (const CanonPath & path) override
72
+ {
73
+ return callWithAccessorForPath (
74
+ path, [](SourceAccessor & accessor, const CanonPath & path) { return accessor.readFile (path); });
75
+ }
76
+
77
+ void readFile (const CanonPath & path, Sink & sink, std::function<void (uint64_t )> sizeCallback) override
78
+ {
79
+ return callWithAccessorForPath (path, [&](SourceAccessor & accessor, const CanonPath & path) {
80
+ return accessor.readFile (path, sink, sizeCallback);
81
+ });
82
+ }
83
+
84
+ bool pathExists (const CanonPath & path) override
85
+ {
86
+ return callWithAccessorForPath (
87
+ path, [](SourceAccessor & accessor, const CanonPath & path) { return accessor.pathExists (path); });
88
+ }
89
+
90
+ std::optional<Stat> maybeLstat (const CanonPath & path) override
91
+ {
92
+ return callWithAccessorForPath (
93
+ path, [](SourceAccessor & accessor, const CanonPath & path) { return accessor.maybeLstat (path); });
94
+ }
95
+
96
+ DirEntries readDirectory (const CanonPath & path) override
97
+ {
98
+ return callWithAccessorForPath (
99
+ path, [](SourceAccessor & accessor, const CanonPath & path) { return accessor.readDirectory (path); });
100
+ }
101
+
102
+ std::string readLink (const CanonPath & path) override
103
+ {
104
+ return callWithAccessorForPath (
105
+ path, [](SourceAccessor & accessor, const CanonPath & path) { return accessor.readLink (path); });
106
+ }
107
+ };
108
+
109
+ } // namespace
110
+
16
111
struct DummyStore : virtual Store
17
112
{
18
113
using Config = DummyStoreConfig;
@@ -29,7 +124,7 @@ struct DummyStore : virtual Store
29
124
* This is map conceptually owns the file system objects for each
30
125
* store object.
31
126
*/
32
- std::map <StorePath, PathInfoAndContents> contents;
127
+ boost::concurrent_flat_map <StorePath, PathInfoAndContents> contents;
33
128
34
129
/* *
35
130
* This view conceptually just borrows the file systems objects of
@@ -38,23 +133,23 @@ struct DummyStore : virtual Store
38
133
*
39
134
* This is needed just in order to implement `Store::getFSAccessor`.
40
135
*/
41
- ref<MemorySourceAccessor > wholeStoreView = make_ref<MemorySourceAccessor >();
136
+ ref<WholeStoreViewAccessor > wholeStoreView = make_ref<WholeStoreViewAccessor >();
42
137
43
138
DummyStore (ref<const Config> config)
44
139
: Store{*config}
45
140
, config(config)
46
141
{
47
142
wholeStoreView->setPathDisplay (config->storeDir );
48
- MemorySink sink{*wholeStoreView};
49
- sink.createDirectory (CanonPath::root);
50
143
}
51
144
52
145
void queryPathInfoUncached (
53
146
const StorePath & path, Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept override
54
147
{
55
- if (auto it = contents.find (path); it != contents.end ())
56
- callback (std::make_shared<ValidPathInfo>(StorePath{path}, it->second .info ));
57
- else
148
+ bool visited = contents.cvisit (path, [&](const auto & kv) {
149
+ callback (std::make_shared<ValidPathInfo>(StorePath{kv.first }, kv.second .info ));
150
+ });
151
+
152
+ if (!visited)
58
153
callback (nullptr );
59
154
}
60
155
@@ -87,19 +182,14 @@ struct DummyStore : virtual Store
87
182
parseDump (tempSink, source);
88
183
auto path = info.path ;
89
184
90
- auto [it, _] = contents.insert ({
91
- path,
92
- {
93
- std::move (info),
94
- make_ref<MemorySourceAccessor>(std::move (*temp)),
95
- },
96
- });
97
-
98
- auto & pathAndContents = it->second ;
99
-
100
- bool inserted = wholeStoreView->open (CanonPath (path.to_string ()), pathAndContents.contents ->root );
101
- if (!inserted)
102
- unreachable ();
185
+ auto accessor = make_ref<MemorySourceAccessor>(std::move (*temp));
186
+ contents.insert (
187
+ {path,
188
+ PathInfoAndContents{
189
+ std::move (info),
190
+ accessor,
191
+ }});
192
+ wholeStoreView->addObject (path.to_string (), accessor);
103
193
}
104
194
105
195
StorePath addToStoreFromDump (
@@ -156,33 +246,28 @@ struct DummyStore : virtual Store
156
246
info.narSize = narHash.second .value ();
157
247
158
248
auto path = info.path ;
159
-
160
- auto [it, _] = contents.insert ({
161
- path,
162
- {
163
- std::move (info),
164
- make_ref<MemorySourceAccessor>(std::move (*temp)),
165
- },
166
- });
167
-
168
- auto & pathAndContents = it->second ;
169
-
170
- bool inserted = wholeStoreView->open (CanonPath (path.to_string ()), pathAndContents.contents ->root );
171
- if (!inserted)
172
- unreachable ();
249
+ auto accessor = make_ref<MemorySourceAccessor>(std::move (*temp));
250
+ contents.insert (
251
+ {path,
252
+ PathInfoAndContents{
253
+ std::move (info),
254
+ accessor,
255
+ }});
256
+ wholeStoreView->addObject (path.to_string (), accessor);
173
257
174
258
return path;
175
259
}
176
260
177
261
void narFromPath (const StorePath & path, Sink & sink) override
178
262
{
179
- auto object = contents.find (path);
180
- if (object == contents.end ())
181
- throw Error (" path '%s' is not valid" , printStorePath (path));
263
+ bool visited = contents.cvisit (path, [&](const auto & kv) {
264
+ const auto & [info, accessor] = kv.second ;
265
+ SourcePath sourcePath (accessor);
266
+ dumpPath (sourcePath, sink, FileSerialisationMethod::NixArchive);
267
+ });
182
268
183
- const auto & [info, accessor] = object->second ;
184
- SourcePath sourcePath (accessor);
185
- dumpPath (sourcePath, sink, FileSerialisationMethod::NixArchive);
269
+ if (!visited)
270
+ throw Error (" path '%s' is not valid" , printStorePath (path));
186
271
}
187
272
188
273
void
0 commit comments