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