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