1 : #ifndef __STOREAPI_H
2 : #define __STOREAPI_H
3 :
4 : #include <string>
5 : #include <map>
6 :
7 : #include <boost/shared_ptr.hpp>
8 :
9 : #include "hash.hh"
10 : #include "serialise.hh"
11 :
12 :
13 : namespace nix {
14 :
15 :
16 : typedef std::map<Path, Path> Roots;
17 :
18 :
19 :
20 :
21 : struct GCOptions
22 23 : {
23 : /* Garbage collector operation:
24 :
25 : - `gcReturnRoots': find and return the set of roots for the
26 : garbage collector. These are the store paths symlinked to in
27 : the `gcroots' directory.
28 :
29 : - `gcReturnLive': return the set of paths reachable from
30 : (i.e. in the closure of) the roots.
31 :
32 : - `gcReturnDead': return the set of paths not reachable from
33 : the roots.
34 :
35 : - `gcDeleteDead': actually delete the latter set.
36 :
37 : - `gcDeleteSpecific': delete the paths listed in
38 : `pathsToDelete', insofar as they are not reachable.
39 : */
40 : typedef enum {
41 : gcReturnRoots,
42 : gcReturnLive,
43 : gcReturnDead,
44 : gcDeleteDead,
45 : gcDeleteSpecific,
46 : } GCAction;
47 :
48 : GCAction action;
49 :
50 : /* If `ignoreLiveness' is set, then reachability from the roots is
51 : ignored (dangerous!). However, the paths must still be
52 : unreferenced *within* the store (i.e., there can be no other
53 : store paths that depend on them). */
54 : bool ignoreLiveness;
55 :
56 : /* For `gcDeleteSpecific', the paths to delete. */
57 : PathSet pathsToDelete;
58 :
59 : /* Stop after at least `maxFreed' bytes have been freed. */
60 : unsigned long long maxFreed;
61 :
62 : /* Stop after the number of hard links to the Nix store directory
63 : has dropped below `maxLinks'. */
64 : unsigned int maxLinks;
65 :
66 : /* Delete paths in order of ascending last access time. I.e.,
67 : prefer deleting unrecently used paths. Useful in conjunction
68 : with `maxFreed' and `maxLinks' (or manual interruption). The
69 : access time of a path is defined as the highest atime of any
70 : non-directory, non-symlink file under that path. Directories
71 : and symlinks are ignored because their atimes are frequently
72 : mass-updated, e.g. by `locate'. Note that optimiseStore()
73 : somewhat reduces the usefulness of this option: it hard-links
74 : regular files and symlink together, giving them a "shared"
75 : atime. */
76 : bool useAtime;
77 :
78 : /* Do not delete paths newer than `maxAtime'. -1 means no age
79 : limit. */
80 : time_t maxAtime;
81 :
82 : GCOptions();
83 : };
84 :
85 :
86 : struct GCResults
87 23 : {
88 : /* Depending on the action, the GC roots, or the paths that would
89 : be or have been deleted. */
90 : PathSet paths;
91 :
92 : /* For `gcReturnDead', `gcDeleteDead' and `gcDeleteSpecific', the
93 : number of bytes that would be or was freed. */
94 : unsigned long long bytesFreed;
95 :
96 : /* The number of file system blocks that would be or was freed. */
97 : unsigned long long blocksFreed;
98 :
99 23 : GCResults()
100 23 : {
101 23 : bytesFreed = 0;
102 23 : blocksFreed = 0;
103 23 : }
104 : };
105 :
106 :
107 : struct SubstitutablePathInfo
108 798 : {
109 : Path deriver;
110 : PathSet references;
111 : unsigned long long downloadSize; /* 0 = unknown or inapplicable */
112 : };
113 :
114 :
115 : class StoreAPI
116 512 : {
117 : public:
118 :
119 512 : virtual ~StoreAPI() { }
120 :
121 : /* Checks whether a path is valid. */
122 : virtual bool isValidPath(const Path & path) = 0;
123 :
124 : /* Query the set of valid paths. */
125 : virtual PathSet queryValidPaths() = 0;
126 :
127 : /* Queries the hash of a valid path. */
128 : virtual Hash queryPathHash(const Path & path) = 0;
129 :
130 : /* Queries the set of outgoing FS references for a store path.
131 : The result is not cleared. */
132 : virtual void queryReferences(const Path & path,
133 : PathSet & references) = 0;
134 :
135 : /* Like queryReferences, but with self-references filtered out. */
136 0 : PathSet queryReferencesNoSelf(const Path & path)
137 : {
138 0 : PathSet res;
139 0 : queryReferences(path, res);
140 0 : res.erase(path);
141 0 : return res;
142 : }
143 :
144 : /* Queries the set of incoming FS references for a store path.
145 : The result is not cleared. */
146 : virtual void queryReferrers(const Path & path,
147 : PathSet & referrers) = 0;
148 :
149 : /* Like queryReferrers, but with self-references filtered out. */
150 0 : PathSet queryReferrersNoSelf(const Path & path)
151 : {
152 0 : PathSet res;
153 0 : queryReferrers(path, res);
154 0 : res.erase(path);
155 0 : return res;
156 : }
157 :
158 : /* Query the deriver of a store path. Return the empty string if
159 : no deriver has been set. */
160 : virtual Path queryDeriver(const Path & path) = 0;
161 :
162 : /* Query whether a path has substitutes. */
163 : virtual bool hasSubstitutes(const Path & path) = 0;
164 :
165 : /* Query the references, deriver and download size of a
166 : substitutable path. */
167 : virtual bool querySubstitutablePathInfo(const Path & path,
168 : SubstitutablePathInfo & info) = 0;
169 :
170 : /* Copy the contents of a path to the store and register the
171 : validity the resulting path. The resulting path is returned.
172 : If `fixed' is true, then the output of a fixed-output
173 : derivation is pre-loaded into the Nix store. The function
174 : object `filter' can be used to exclude files (see
175 : libutil/archive.hh). */
176 : virtual Path addToStore(const Path & srcPath, bool fixed = false,
177 : bool recursive = false, string hashAlgo = "",
178 : PathFilter & filter = defaultPathFilter) = 0;
179 :
180 : /* Like addToStore, but the contents written to the output path is
181 : a regular file containing the given string. */
182 : virtual Path addTextToStore(const string & suffix, const string & s,
183 : const PathSet & references) = 0;
184 :
185 : /* Export a store path, that is, create a NAR dump of the store
186 : path and append its references and its deriver. Optionally, a
187 : cryptographic signature (created by OpenSSL) of the preceding
188 : data is attached. */
189 : virtual void exportPath(const Path & path, bool sign,
190 : Sink & sink) = 0;
191 :
192 : /* Import a NAR dump created by exportPath() into the Nix
193 : store. */
194 : virtual Path importPath(bool requireSignature, Source & source) = 0;
195 :
196 : /* Ensure that the output paths of the derivation are valid. If
197 : they are already valid, this is a no-op. Otherwise, validity
198 : can be reached in two ways. First, if the output paths is
199 : substitutable, then build the path that way. Second, the
200 : output paths can be created by running the builder, after
201 : recursively building any sub-derivations. */
202 : virtual void buildDerivations(const PathSet & drvPaths) = 0;
203 :
204 : /* Ensure that a path is valid. If it is not currently valid, it
205 : may be made valid by running a substitute (if defined for the
206 : path). */
207 : virtual void ensurePath(const Path & path) = 0;
208 :
209 : /* Add a store path as a temporary root of the garbage collector.
210 : The root disappears as soon as we exit. */
211 : virtual void addTempRoot(const Path & path) = 0;
212 :
213 : /* Add an indirect root, which is merely a symlink to `path' from
214 : /nix/var/nix/gcroots/auto/<hash of `path'>. `path' is supposed
215 : to be a symlink to a store path. The garbage collector will
216 : automatically remove the indirect root when it finds that
217 : `path' has disappeared. */
218 : virtual void addIndirectRoot(const Path & path) = 0;
219 :
220 : /* Acquire the global GC lock, then immediately release it. This
221 : function must be called after registering a new permanent root,
222 : but before exiting. Otherwise, it is possible that a running
223 : garbage collector doesn't see the new root and deletes the
224 : stuff we've just built. By acquiring the lock briefly, we
225 : ensure that either:
226 :
227 : - The collector is already running, and so we block until the
228 : collector is finished. The collector will know about our
229 : *temporary* locks, which should include whatever it is we
230 : want to register as a permanent lock.
231 :
232 : - The collector isn't running, or it's just started but hasn't
233 : acquired the GC lock yet. In that case we get and release
234 : the lock right away, then exit. The collector scans the
235 : permanent root and sees our's.
236 :
237 : In either case the permanent root is seen by the collector. */
238 : virtual void syncWithGC() = 0;
239 :
240 : /* Find the roots of the garbage collector. Each root is a pair
241 : (link, storepath) where `link' is the path of the symlink
242 : outside of the Nix store that point to `storePath'. */
243 : virtual Roots findRoots() = 0;
244 :
245 : /* Perform a garbage collection. */
246 : virtual void collectGarbage(const GCOptions & options, GCResults & results) = 0;
247 : };
248 :
249 :
250 : /* !!! These should be part of the store API, I guess. */
251 :
252 : /* Throw an exception if `path' is not directly in the Nix store. */
253 : void assertStorePath(const Path & path);
254 :
255 : bool isInStore(const Path & path);
256 : bool isStorePath(const Path & path);
257 :
258 : void checkStoreName(const string & name);
259 :
260 :
261 : /* Chop off the parts after the top-level store name, e.g.,
262 : /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */
263 : Path toStorePath(const Path & path);
264 :
265 :
266 : /* Follow symlinks until we end up with a path in the Nix store. */
267 : Path followLinksToStore(const Path & path);
268 :
269 :
270 : /* Same as followLinksToStore(), but apply toStorePath() to the
271 : result. */
272 : Path followLinksToStorePath(const Path & path);
273 :
274 :
275 : /* Constructs a unique store path name. */
276 : Path makeStorePath(const string & type,
277 : const Hash & hash, const string & suffix);
278 :
279 : Path makeFixedOutputPath(bool recursive,
280 : string hashAlgo, Hash hash, string name);
281 :
282 :
283 : /* This is the preparatory part of addToStore() and addToStoreFixed();
284 : it computes the store path to which srcPath is to be copied.
285 : Returns the store path and the cryptographic hash of the
286 : contents of srcPath. */
287 : std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
288 : bool fixed = false, bool recursive = false, string hashAlgo = "",
289 : PathFilter & filter = defaultPathFilter);
290 :
291 : /* Preparatory part of addTextToStore().
292 :
293 : !!! Computation of the path should take the references given to
294 : addTextToStore() into account, otherwise we have a (relatively
295 : minor) security hole: a caller can register a source file with
296 : bogus references. If there are too many references, the path may
297 : not be garbage collected when it has to be (not really a problem,
298 : the caller could create a root anyway), or it may be garbage
299 : collected when it shouldn't be (more serious).
300 :
301 : Hashing the references would solve this (bogus references would
302 : simply yield a different store path, so other users wouldn't be
303 : affected), but it has some backwards compatibility issues (the
304 : hashing scheme changes), so I'm not doing that for now. */
305 : Path computeStorePathForText(const string & suffix, const string & s,
306 : const PathSet & references);
307 :
308 :
309 : /* Remove the temporary roots file for this process. Any temporary
310 : root becomes garbage after this point unless it has been registered
311 : as a (permanent) root. */
312 : void removeTempRoots();
313 :
314 :
315 : /* Register a permanent GC root. */
316 : Path addPermRoot(const Path & storePath, const Path & gcRoot,
317 : bool indirect, bool allowOutsideRootsDir = false);
318 :
319 :
320 : /* Sort a set of paths topologically under the references relation.
321 : If p refers to q, then p follows q in this list. */
322 : Paths topoSortPaths(const PathSet & paths);
323 :
324 :
325 : /* For now, there is a single global store API object, but we'll
326 : purify that in the future. */
327 : extern boost::shared_ptr<StoreAPI> store;
328 :
329 :
330 : /* Factory method: open the Nix database, either through the local or
331 : remote implementation. */
332 : boost::shared_ptr<StoreAPI> openStore();
333 :
334 :
335 : /* Display a set of paths in human-readable form (i.e., between quotes
336 : and separated by commas). */
337 : string showPaths(const PathSet & paths);
338 :
339 :
340 : string makeValidityRegistration(const PathSet & paths,
341 : bool showDerivers, bool showHash);
342 :
343 : struct ValidPathInfo
344 128104 : {
345 : Path path;
346 : Path deriver;
347 : Hash hash;
348 : PathSet references;
349 : time_t registrationTime;
350 32404 : ValidPathInfo() : registrationTime(0) { }
351 : };
352 :
353 : typedef list<ValidPathInfo> ValidPathInfos;
354 :
355 : ValidPathInfo decodeValidPathInfo(std::istream & str,
356 : bool hashGiven = false);
357 :
358 :
359 : }
360 :
361 :
362 : #endif /* !__STOREAPI_H */
|