Commit | Line | Data |
---|---|---|
36457566 LC |
1 | #pragma once |
2 | ||
3 | #include "hash.hh" | |
4 | #include "serialise.hh" | |
5 | ||
6 | #include <string> | |
7 | #include <map> | |
8 | #include <memory> | |
9 | ||
10 | ||
11 | namespace nix { | |
12 | ||
13 | ||
14 | typedef std::map<Path, Path> Roots; | |
15 | ||
16 | ||
17 | struct GCOptions | |
18 | { | |
19 | /* Garbage collector operation: | |
20 | ||
21 | - `gcReturnLive': return the set of paths reachable from | |
22 | (i.e. in the closure of) the roots. | |
23 | ||
24 | - `gcReturnDead': return the set of paths not reachable from | |
25 | the roots. | |
26 | ||
27 | - `gcDeleteDead': actually delete the latter set. | |
28 | ||
29 | - `gcDeleteSpecific': delete the paths listed in | |
30 | `pathsToDelete', insofar as they are not reachable. | |
31 | */ | |
32 | typedef enum { | |
33 | gcReturnLive, | |
34 | gcReturnDead, | |
35 | gcDeleteDead, | |
36 | gcDeleteSpecific, | |
37 | } GCAction; | |
38 | ||
39 | GCAction action; | |
40 | ||
41 | /* If `ignoreLiveness' is set, then reachability from the roots is | |
42 | ignored (dangerous!). However, the paths must still be | |
43 | unreferenced *within* the store (i.e., there can be no other | |
44 | store paths that depend on them). */ | |
45 | bool ignoreLiveness; | |
46 | ||
47 | /* For `gcDeleteSpecific', the paths to delete. */ | |
48 | PathSet pathsToDelete; | |
49 | ||
50 | /* Stop after at least `maxFreed' bytes have been freed. */ | |
51 | unsigned long long maxFreed; | |
52 | ||
53 | GCOptions(); | |
54 | }; | |
55 | ||
56 | ||
54c260e6 | 57 | struct GCResults |
36457566 LC |
58 | { |
59 | /* Depending on the action, the GC roots, or the paths that would | |
60 | be or have been deleted. */ | |
61 | PathSet paths; | |
62 | ||
63 | /* For `gcReturnDead', `gcDeleteDead' and `gcDeleteSpecific', the | |
64 | number of bytes that would be or was freed. */ | |
65 | unsigned long long bytesFreed; | |
66 | ||
67 | GCResults() | |
68 | { | |
69 | bytesFreed = 0; | |
70 | } | |
71 | }; | |
72 | ||
73 | ||
74 | struct SubstitutablePathInfo | |
75 | { | |
76 | Path deriver; | |
77 | PathSet references; | |
78 | unsigned long long downloadSize; /* 0 = unknown or inapplicable */ | |
79 | unsigned long long narSize; /* 0 = unknown */ | |
80 | }; | |
81 | ||
82 | typedef std::map<Path, SubstitutablePathInfo> SubstitutablePathInfos; | |
83 | ||
84 | ||
54c260e6 | 85 | struct ValidPathInfo |
36457566 LC |
86 | { |
87 | Path path; | |
88 | Path deriver; | |
89 | Hash hash; | |
90 | PathSet references; | |
b23b4d39 | 91 | time_t registrationTime = 0; |
b1fd0ab7 ED |
92 | uint64_t narSize = 0; // 0 = unknown |
93 | uint64_t id; // internal use only | |
b23b4d39 ED |
94 | |
95 | bool operator == (const ValidPathInfo & i) const | |
96 | { | |
97 | return | |
98 | path == i.path | |
99 | && hash == i.hash | |
100 | && references == i.references; | |
101 | } | |
36457566 LC |
102 | }; |
103 | ||
104 | typedef list<ValidPathInfo> ValidPathInfos; | |
105 | ||
106 | ||
107 | enum BuildMode { bmNormal, bmRepair, bmCheck }; | |
108 | ||
f3ff1da4 ED |
109 | struct BuildResult |
110 | { | |
111 | enum Status { | |
112 | Built = 0, | |
113 | Substituted, | |
114 | AlreadyValid, | |
115 | PermanentFailure, | |
116 | InputRejected, | |
117 | OutputRejected, | |
118 | TransientFailure, // possibly transient | |
119 | CachedFailure, | |
120 | TimedOut, | |
121 | MiscFailure, | |
122 | DependencyFailed, | |
123 | LogLimitExceeded, | |
124 | NotDeterministic, | |
125 | } status = MiscFailure; | |
126 | std::string errorMsg; | |
127 | //time_t startTime = 0, stopTime = 0; | |
128 | bool success() { | |
129 | return status == Built || status == Substituted || status == AlreadyValid; | |
130 | } | |
131 | }; | |
132 | ||
36457566 | 133 | |
54c260e6 | 134 | class StoreAPI |
36457566 LC |
135 | { |
136 | public: | |
137 | ||
138 | virtual ~StoreAPI() { } | |
139 | ||
54c260e6 | 140 | /* Check whether a path is valid. */ |
36457566 LC |
141 | virtual bool isValidPath(const Path & path) = 0; |
142 | ||
143 | /* Query which of the given paths is valid. */ | |
144 | virtual PathSet queryValidPaths(const PathSet & paths) = 0; | |
145 | ||
146 | /* Query the set of all valid paths. */ | |
147 | virtual PathSet queryAllValidPaths() = 0; | |
148 | ||
149 | /* Query information about a valid path. */ | |
150 | virtual ValidPathInfo queryPathInfo(const Path & path) = 0; | |
151 | ||
54c260e6 | 152 | /* Query the hash of a valid path. */ |
36457566 LC |
153 | virtual Hash queryPathHash(const Path & path) = 0; |
154 | ||
155 | /* Query the set of outgoing FS references for a store path. The | |
156 | result is not cleared. */ | |
157 | virtual void queryReferences(const Path & path, | |
158 | PathSet & references) = 0; | |
159 | ||
160 | /* Queries the set of incoming FS references for a store path. | |
161 | The result is not cleared. */ | |
162 | virtual void queryReferrers(const Path & path, | |
163 | PathSet & referrers) = 0; | |
164 | ||
165 | /* Query the deriver of a store path. Return the empty string if | |
166 | no deriver has been set. */ | |
167 | virtual Path queryDeriver(const Path & path) = 0; | |
168 | ||
169 | /* Return all currently valid derivations that have `path' as an | |
170 | output. (Note that the result of `queryDeriver()' is the | |
171 | derivation that was actually used to produce `path', which may | |
172 | not exist anymore.) */ | |
173 | virtual PathSet queryValidDerivers(const Path & path) = 0; | |
174 | ||
175 | /* Query the outputs of the derivation denoted by `path'. */ | |
176 | virtual PathSet queryDerivationOutputs(const Path & path) = 0; | |
177 | ||
178 | /* Query the output names of the derivation denoted by `path'. */ | |
179 | virtual StringSet queryDerivationOutputNames(const Path & path) = 0; | |
180 | ||
181 | /* Query the full store path given the hash part of a valid store | |
182 | path, or "" if the path doesn't exist. */ | |
183 | virtual Path queryPathFromHashPart(const string & hashPart) = 0; | |
54c260e6 | 184 | |
36457566 LC |
185 | /* Query which of the given paths have substitutes. */ |
186 | virtual PathSet querySubstitutablePaths(const PathSet & paths) = 0; | |
187 | ||
188 | /* Query substitute info (i.e. references, derivers and download | |
189 | sizes) of a set of paths. If a path does not have substitute | |
190 | info, it's omitted from the resulting ‘infos’ map. */ | |
191 | virtual void querySubstitutablePathInfos(const PathSet & paths, | |
192 | SubstitutablePathInfos & infos) = 0; | |
54c260e6 | 193 | |
36457566 LC |
194 | /* Copy the contents of a path to the store and register the |
195 | validity the resulting path. The resulting path is returned. | |
196 | The function object `filter' can be used to exclude files (see | |
197 | libutil/archive.hh). */ | |
54c260e6 | 198 | virtual Path addToStore(const string & name, const Path & srcPath, |
36457566 LC |
199 | bool recursive = true, HashType hashAlgo = htSHA256, |
200 | PathFilter & filter = defaultPathFilter, bool repair = false) = 0; | |
201 | ||
202 | /* Like addToStore, but the contents written to the output path is | |
203 | a regular file containing the given string. */ | |
204 | virtual Path addTextToStore(const string & name, const string & s, | |
205 | const PathSet & references, bool repair = false) = 0; | |
206 | ||
207 | /* Export a store path, that is, create a NAR dump of the store | |
208 | path and append its references and its deriver. Optionally, a | |
209 | cryptographic signature (created by OpenSSL) of the preceding | |
210 | data is attached. */ | |
211 | virtual void exportPath(const Path & path, bool sign, | |
212 | Sink & sink) = 0; | |
213 | ||
214 | /* Import a sequence of NAR dumps created by exportPaths() into | |
215 | the Nix store. */ | |
216 | virtual Paths importPaths(bool requireSignature, Source & source) = 0; | |
217 | ||
218 | /* For each path, if it's a derivation, build it. Building a | |
219 | derivation means ensuring that the output paths are valid. If | |
220 | they are already valid, this is a no-op. Otherwise, validity | |
221 | can be reached in two ways. First, if the output paths is | |
222 | substitutable, then build the path that way. Second, the | |
223 | output paths can be created by running the builder, after | |
224 | recursively building any sub-derivations. For inputs that are | |
225 | not derivations, substitute them. */ | |
226 | virtual void buildPaths(const PathSet & paths, BuildMode buildMode = bmNormal) = 0; | |
227 | ||
228 | /* Ensure that a path is valid. If it is not currently valid, it | |
229 | may be made valid by running a substitute (if defined for the | |
230 | path). */ | |
231 | virtual void ensurePath(const Path & path) = 0; | |
232 | ||
233 | /* Add a store path as a temporary root of the garbage collector. | |
234 | The root disappears as soon as we exit. */ | |
235 | virtual void addTempRoot(const Path & path) = 0; | |
236 | ||
237 | /* Add an indirect root, which is merely a symlink to `path' from | |
238 | /nix/var/nix/gcroots/auto/<hash of `path'>. `path' is supposed | |
239 | to be a symlink to a store path. The garbage collector will | |
240 | automatically remove the indirect root when it finds that | |
241 | `path' has disappeared. */ | |
242 | virtual void addIndirectRoot(const Path & path) = 0; | |
243 | ||
244 | /* Acquire the global GC lock, then immediately release it. This | |
245 | function must be called after registering a new permanent root, | |
246 | but before exiting. Otherwise, it is possible that a running | |
247 | garbage collector doesn't see the new root and deletes the | |
248 | stuff we've just built. By acquiring the lock briefly, we | |
249 | ensure that either: | |
250 | ||
251 | - The collector is already running, and so we block until the | |
252 | collector is finished. The collector will know about our | |
253 | *temporary* locks, which should include whatever it is we | |
254 | want to register as a permanent lock. | |
255 | ||
256 | - The collector isn't running, or it's just started but hasn't | |
257 | acquired the GC lock yet. In that case we get and release | |
258 | the lock right away, then exit. The collector scans the | |
259 | permanent root and sees our's. | |
260 | ||
261 | In either case the permanent root is seen by the collector. */ | |
262 | virtual void syncWithGC() = 0; | |
263 | ||
264 | /* Find the roots of the garbage collector. Each root is a pair | |
265 | (link, storepath) where `link' is the path of the symlink | |
266 | outside of the Nix store that point to `storePath'. */ | |
267 | virtual Roots findRoots() = 0; | |
268 | ||
269 | /* Perform a garbage collection. */ | |
270 | virtual void collectGarbage(const GCOptions & options, GCResults & results) = 0; | |
271 | ||
272 | /* Return the set of paths that have failed to build.*/ | |
273 | virtual PathSet queryFailedPaths() = 0; | |
274 | ||
275 | /* Clear the "failed" status of the given paths. The special | |
276 | value `*' causes all failed paths to be cleared. */ | |
277 | virtual void clearFailedPaths(const PathSet & paths) = 0; | |
278 | ||
279 | /* Return a string representing information about the path that | |
280 | can be loaded into the database using `nix-store --load-db' or | |
281 | `nix-store --register-validity'. */ | |
282 | string makeValidityRegistration(const PathSet & paths, | |
283 | bool showDerivers, bool showHash); | |
2bb04905 LC |
284 | |
285 | /* Optimise the disk space usage of the Nix store by hard-linking files | |
286 | with the same contents. */ | |
287 | virtual void optimiseStore() = 0; | |
54c260e6 LC |
288 | |
289 | /* Check the integrity of the Nix store. Returns true if errors | |
290 | remain. */ | |
291 | virtual bool verifyStore(bool checkContents, bool repair) = 0; | |
81c580c8 LC |
292 | |
293 | /* Create a profile for the given user. This is done by the daemon | |
294 | because the 'profiles/per-user' directory is not writable by users. */ | |
295 | virtual void createUser(const std::string & userName, uid_t userId) = 0; | |
36457566 LC |
296 | }; |
297 | ||
298 | ||
299 | /* !!! These should be part of the store API, I guess. */ | |
300 | ||
301 | /* Throw an exception if `path' is not directly in the Nix store. */ | |
302 | void assertStorePath(const Path & path); | |
303 | ||
304 | bool isInStore(const Path & path); | |
305 | bool isStorePath(const Path & path); | |
306 | ||
307 | /* Extract the name part of the given store path. */ | |
308 | string storePathToName(const Path & path); | |
54c260e6 | 309 | |
36457566 LC |
310 | void checkStoreName(const string & name); |
311 | ||
312 | ||
313 | /* Chop off the parts after the top-level store name, e.g., | |
314 | /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */ | |
315 | Path toStorePath(const Path & path); | |
316 | ||
317 | ||
36457566 LC |
318 | /* Constructs a unique store path name. */ |
319 | Path makeStorePath(const string & type, | |
320 | const Hash & hash, const string & name); | |
54c260e6 | 321 | |
36457566 LC |
322 | Path makeOutputPath(const string & id, |
323 | const Hash & hash, const string & name); | |
324 | ||
325 | Path makeFixedOutputPath(bool recursive, | |
326 | HashType hashAlgo, Hash hash, string name); | |
327 | ||
328 | ||
36457566 LC |
329 | /* Preparatory part of addTextToStore(). |
330 | ||
331 | !!! Computation of the path should take the references given to | |
332 | addTextToStore() into account, otherwise we have a (relatively | |
333 | minor) security hole: a caller can register a source file with | |
334 | bogus references. If there are too many references, the path may | |
335 | not be garbage collected when it has to be (not really a problem, | |
336 | the caller could create a root anyway), or it may be garbage | |
337 | collected when it shouldn't be (more serious). | |
338 | ||
339 | Hashing the references would solve this (bogus references would | |
340 | simply yield a different store path, so other users wouldn't be | |
341 | affected), but it has some backwards compatibility issues (the | |
342 | hashing scheme changes), so I'm not doing that for now. */ | |
343 | Path computeStorePathForText(const string & name, const string & s, | |
344 | const PathSet & references); | |
345 | ||
346 | ||
347 | /* Remove the temporary roots file for this process. Any temporary | |
348 | root becomes garbage after this point unless it has been registered | |
349 | as a (permanent) root. */ | |
350 | void removeTempRoots(); | |
351 | ||
352 | ||
353 | /* Register a permanent GC root. */ | |
354 | Path addPermRoot(StoreAPI & store, const Path & storePath, | |
355 | const Path & gcRoot, bool indirect, bool allowOutsideRootsDir = false); | |
356 | ||
357 | ||
358 | /* Sort a set of paths topologically under the references relation. | |
359 | If p refers to q, then p preceeds q in this list. */ | |
360 | Paths topoSortPaths(StoreAPI & store, const PathSet & paths); | |
361 | ||
362 | ||
363 | /* For now, there is a single global store API object, but we'll | |
364 | purify that in the future. */ | |
365 | extern std::shared_ptr<StoreAPI> store; | |
366 | ||
367 | ||
36457566 LC |
368 | /* Display a set of paths in human-readable form (i.e., between quotes |
369 | and separated by commas). */ | |
370 | string showPaths(const PathSet & paths); | |
371 | ||
36457566 LC |
372 | MakeError(SubstError, Error) |
373 | MakeError(BuildError, Error) /* denotes a permanent build failure */ | |
374 | ||
375 | ||
376 | } |