Commit | Line | Data |
---|---|---|
36457566 LC |
1 | #pragma once |
2 | ||
3 | #include <string> | |
2bb04905 | 4 | #include <unordered_set> |
36457566 LC |
5 | |
6 | #include "store-api.hh" | |
7 | #include "util.hh" | |
8 | #include "pathlocks.hh" | |
9 | ||
10 | ||
11 | class sqlite3; | |
12 | class sqlite3_stmt; | |
13 | ||
14 | ||
15 | namespace nix { | |
16 | ||
17 | ||
18 | /* Nix store and database schema version. Version 1 (or 0) was Nix <= | |
19 | 0.7. Version 2 was Nix 0.8 and 0.9. Version 3 is Nix 0.10. | |
20 | Version 4 is Nix 0.11. Version 5 is Nix 0.12-0.16. Version 6 is | |
21 | Nix 1.0. Version 7 is Nix 1.3. */ | |
22 | const int nixSchemaVersion = 7; | |
23 | ||
24 | ||
25 | extern string drvsLogDir; | |
26 | ||
27 | ||
28 | struct Derivation; | |
29 | ||
30 | ||
31 | struct OptimiseStats | |
32 | { | |
36457566 LC |
33 | unsigned long filesLinked; |
34 | unsigned long long bytesFreed; | |
35 | unsigned long long blocksFreed; | |
36 | OptimiseStats() | |
37 | { | |
15ddeff5 | 38 | filesLinked = 0; |
36457566 LC |
39 | bytesFreed = blocksFreed = 0; |
40 | } | |
41 | }; | |
42 | ||
43 | ||
44 | struct RunningSubstituter | |
45 | { | |
46 | Path program; | |
47 | Pid pid; | |
48 | AutoCloseFD to, from, error; | |
49 | FdSource fromBuf; | |
50 | bool disabled; | |
51 | RunningSubstituter() : disabled(false) { }; | |
52 | }; | |
53 | ||
54 | ||
55 | /* Wrapper object to close the SQLite database automatically. */ | |
56 | struct SQLite | |
57 | { | |
58 | sqlite3 * db; | |
59 | SQLite() { db = 0; } | |
60 | ~SQLite(); | |
61 | operator sqlite3 * () { return db; } | |
62 | }; | |
63 | ||
64 | ||
65 | /* Wrapper object to create and destroy SQLite prepared statements. */ | |
66 | struct SQLiteStmt | |
67 | { | |
68 | sqlite3 * db; | |
69 | sqlite3_stmt * stmt; | |
70 | unsigned int curArg; | |
71 | SQLiteStmt() { stmt = 0; } | |
72 | void create(sqlite3 * db, const string & s); | |
73 | void reset(); | |
74 | ~SQLiteStmt(); | |
75 | operator sqlite3_stmt * () { return stmt; } | |
76 | void bind(const string & value); | |
77 | void bind(int value); | |
78 | void bind64(long long value); | |
79 | void bind(); | |
80 | }; | |
81 | ||
82 | ||
83 | class LocalStore : public StoreAPI | |
84 | { | |
85 | private: | |
86 | typedef std::map<Path, RunningSubstituter> RunningSubstituters; | |
87 | RunningSubstituters runningSubstituters; | |
88 | ||
89 | Path linksDir; | |
90 | ||
91 | public: | |
92 | ||
93 | /* Initialise the local store, upgrading the schema if | |
94 | necessary. */ | |
95 | LocalStore(bool reserveSpace = true); | |
96 | ||
97 | ~LocalStore(); | |
98 | ||
99 | /* Implementations of abstract store API methods. */ | |
100 | ||
101 | bool isValidPath(const Path & path); | |
102 | ||
103 | PathSet queryValidPaths(const PathSet & paths); | |
104 | ||
105 | PathSet queryAllValidPaths(); | |
106 | ||
107 | ValidPathInfo queryPathInfo(const Path & path); | |
108 | ||
109 | Hash queryPathHash(const Path & path); | |
110 | ||
111 | void queryReferences(const Path & path, PathSet & references); | |
112 | ||
113 | void queryReferrers(const Path & path, PathSet & referrers); | |
114 | ||
115 | Path queryDeriver(const Path & path); | |
116 | ||
117 | PathSet queryValidDerivers(const Path & path); | |
118 | ||
119 | PathSet queryDerivationOutputs(const Path & path); | |
120 | ||
121 | StringSet queryDerivationOutputNames(const Path & path); | |
122 | ||
123 | Path queryPathFromHashPart(const string & hashPart); | |
124 | ||
125 | PathSet querySubstitutablePaths(const PathSet & paths); | |
126 | ||
127 | void querySubstitutablePathInfos(const Path & substituter, | |
128 | PathSet & paths, SubstitutablePathInfos & infos); | |
129 | ||
130 | void querySubstitutablePathInfos(const PathSet & paths, | |
131 | SubstitutablePathInfos & infos); | |
132 | ||
54c260e6 | 133 | Path addToStore(const string & name, const Path & srcPath, |
36457566 LC |
134 | bool recursive = true, HashType hashAlgo = htSHA256, |
135 | PathFilter & filter = defaultPathFilter, bool repair = false); | |
136 | ||
137 | /* Like addToStore(), but the contents of the path are contained | |
138 | in `dump', which is either a NAR serialisation (if recursive == | |
139 | true) or simply the contents of a regular file (if recursive == | |
140 | false). */ | |
141 | Path addToStoreFromDump(const string & dump, const string & name, | |
142 | bool recursive = true, HashType hashAlgo = htSHA256, bool repair = false); | |
143 | ||
144 | Path addTextToStore(const string & name, const string & s, | |
145 | const PathSet & references, bool repair = false); | |
146 | ||
147 | void exportPath(const Path & path, bool sign, | |
148 | Sink & sink); | |
149 | ||
150 | Paths importPaths(bool requireSignature, Source & source); | |
151 | ||
152 | void buildPaths(const PathSet & paths, BuildMode buildMode); | |
153 | ||
154 | void ensurePath(const Path & path); | |
155 | ||
156 | void addTempRoot(const Path & path); | |
157 | ||
158 | void addIndirectRoot(const Path & path); | |
159 | ||
160 | void syncWithGC(); | |
161 | ||
162 | Roots findRoots(); | |
163 | ||
164 | void collectGarbage(const GCOptions & options, GCResults & results); | |
165 | ||
166 | /* Optimise the disk space usage of the Nix store by hard-linking | |
167 | files with the same contents. */ | |
168 | void optimiseStore(OptimiseStats & stats); | |
169 | ||
2bb04905 LC |
170 | /* Generic variant of the above method. */ |
171 | void optimiseStore(); | |
172 | ||
36457566 LC |
173 | /* Optimise a single store path. */ |
174 | void optimisePath(const Path & path); | |
175 | ||
176 | /* Check the integrity of the Nix store. Returns true if errors | |
177 | remain. */ | |
178 | bool verifyStore(bool checkContents, bool repair); | |
179 | ||
180 | /* Register the validity of a path, i.e., that `path' exists, that | |
181 | the paths referenced by it exists, and in the case of an output | |
182 | path of a derivation, that it has been produced by a successful | |
183 | execution of the derivation (or something equivalent). Also | |
184 | register the hash of the file system contents of the path. The | |
185 | hash must be a SHA-256 hash. */ | |
186 | void registerValidPath(const ValidPathInfo & info); | |
187 | ||
188 | void registerValidPaths(const ValidPathInfos & infos); | |
189 | ||
190 | /* Register that the build of a derivation with output `path' has | |
191 | failed. */ | |
192 | void registerFailedPath(const Path & path); | |
193 | ||
194 | /* Query whether `path' previously failed to build. */ | |
195 | bool hasPathFailed(const Path & path); | |
196 | ||
197 | PathSet queryFailedPaths(); | |
198 | ||
199 | void clearFailedPaths(const PathSet & paths); | |
200 | ||
201 | void vacuumDB(); | |
202 | ||
203 | /* Repair the contents of the given path by redownloading it using | |
204 | a substituter (if available). */ | |
205 | void repairPath(const Path & path); | |
206 | ||
207 | /* Check whether the given valid path exists and has the right | |
208 | contents. */ | |
209 | bool pathContentsGood(const Path & path); | |
210 | ||
211 | void markContentsGood(const Path & path); | |
212 | ||
213 | void setSubstituterEnv(); | |
214 | ||
215 | private: | |
216 | ||
217 | Path schemaPath; | |
218 | ||
219 | /* Lock file used for upgrading. */ | |
220 | AutoCloseFD globalLock; | |
221 | ||
222 | /* The SQLite database object. */ | |
223 | SQLite db; | |
224 | ||
225 | /* Some precompiled SQLite statements. */ | |
226 | SQLiteStmt stmtRegisterValidPath; | |
227 | SQLiteStmt stmtUpdatePathInfo; | |
228 | SQLiteStmt stmtAddReference; | |
229 | SQLiteStmt stmtQueryPathInfo; | |
230 | SQLiteStmt stmtQueryReferences; | |
231 | SQLiteStmt stmtQueryReferrers; | |
232 | SQLiteStmt stmtInvalidatePath; | |
233 | SQLiteStmt stmtRegisterFailedPath; | |
234 | SQLiteStmt stmtHasPathFailed; | |
235 | SQLiteStmt stmtQueryFailedPaths; | |
236 | SQLiteStmt stmtClearFailedPath; | |
237 | SQLiteStmt stmtAddDerivationOutput; | |
238 | SQLiteStmt stmtQueryValidDerivers; | |
239 | SQLiteStmt stmtQueryDerivationOutputs; | |
240 | SQLiteStmt stmtQueryPathFromHashPart; | |
241 | ||
242 | /* Cache for pathContentsGood(). */ | |
243 | std::map<Path, bool> pathContentsGoodCache; | |
244 | ||
245 | bool didSetSubstituterEnv; | |
246 | ||
2bb04905 LC |
247 | /* The file to which we write our temporary roots. */ |
248 | Path fnTempRoots; | |
249 | AutoCloseFD fdTempRoots; | |
250 | ||
36457566 LC |
251 | int getSchema(); |
252 | ||
253 | void openDB(bool create); | |
254 | ||
255 | void makeStoreWritable(); | |
256 | ||
257 | unsigned long long queryValidPathId(const Path & path); | |
258 | ||
259 | unsigned long long addValidPath(const ValidPathInfo & info, bool checkOutputs = true); | |
260 | ||
261 | void addReference(unsigned long long referrer, unsigned long long reference); | |
262 | ||
263 | void appendReferrer(const Path & from, const Path & to, bool lock); | |
264 | ||
265 | void rewriteReferrers(const Path & path, bool purge, PathSet referrers); | |
266 | ||
267 | void invalidatePath(const Path & path); | |
268 | ||
269 | /* Delete a path from the Nix store. */ | |
270 | void invalidatePathChecked(const Path & path); | |
271 | ||
272 | void verifyPath(const Path & path, const PathSet & store, | |
273 | PathSet & done, PathSet & validPaths, bool repair, bool & errors); | |
274 | ||
275 | void updatePathInfo(const ValidPathInfo & info); | |
276 | ||
277 | void upgradeStore6(); | |
278 | void upgradeStore7(); | |
279 | PathSet queryValidPathsOld(); | |
280 | ValidPathInfo queryPathInfoOld(const Path & path); | |
281 | ||
282 | struct GCState; | |
283 | ||
284 | void deleteGarbage(GCState & state, const Path & path); | |
285 | ||
286 | void tryToDelete(GCState & state, const Path & path); | |
287 | ||
288 | bool canReachRoot(GCState & state, PathSet & visited, const Path & path); | |
289 | ||
290 | void deletePathRecursive(GCState & state, const Path & path); | |
291 | ||
292 | bool isActiveTempFile(const GCState & state, | |
293 | const Path & path, const string & suffix); | |
294 | ||
295 | int openGCLock(LockType lockType); | |
296 | ||
297 | void removeUnusedLinks(const GCState & state); | |
298 | ||
299 | void startSubstituter(const Path & substituter, | |
300 | RunningSubstituter & runningSubstituter); | |
301 | ||
302 | string getLineFromSubstituter(RunningSubstituter & run); | |
303 | ||
304 | template<class T> T getIntLineFromSubstituter(RunningSubstituter & run); | |
305 | ||
306 | Path createTempDirInStore(); | |
307 | ||
308 | Path importPath(bool requireSignature, Source & source); | |
309 | ||
310 | void checkDerivationOutputs(const Path & drvPath, const Derivation & drv); | |
311 | ||
2bb04905 | 312 | typedef std::unordered_set<ino_t> InodeHash; |
15ddeff5 LC |
313 | |
314 | InodeHash loadInodeHash(); | |
315 | Strings readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash); | |
316 | void optimisePath_(OptimiseStats & stats, const Path & path, InodeHash & inodeHash); | |
36457566 LC |
317 | |
318 | // Internal versions that are not wrapped in retry_sqlite. | |
319 | bool isValidPath_(const Path & path); | |
320 | void queryReferrers_(const Path & path, PathSet & referrers); | |
321 | }; | |
322 | ||
323 | ||
324 | typedef std::pair<dev_t, ino_t> Inode; | |
325 | typedef set<Inode> InodesSeen; | |
326 | ||
327 | ||
328 | /* "Fix", or canonicalise, the meta-data of the files in a store path | |
329 | after it has been built. In particular: | |
330 | - the last modification date on each file is set to 1 (i.e., | |
331 | 00:00:01 1/1/1970 UTC) | |
332 | - the permissions are set of 444 or 555 (i.e., read-only with or | |
333 | without execute permission; setuid bits etc. are cleared) | |
334 | - the owner and group are set to the Nix user and group, if we're | |
335 | running as root. */ | |
336 | void canonicalisePathMetaData(const Path & path, uid_t fromUid, InodesSeen & inodesSeen); | |
337 | void canonicalisePathMetaData(const Path & path, uid_t fromUid); | |
338 | ||
339 | void canonicaliseTimestampAndPermissions(const Path & path); | |
340 | ||
341 | MakeError(PathInUse, Error); | |
342 | ||
343 | } |