* Implement isValidPath().
This commit is contained in:
		
							parent
							
								
									cfb09e0fad
								
							
						
					
					
						commit
						885e22b16e
					
				
					 2 changed files with 100 additions and 159 deletions
				
			
		|  | @ -54,6 +54,14 @@ void SQLiteStmt::create(sqlite3 * db, const string & s) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | void SQLiteStmt::reset() | ||||||
|  | { | ||||||
|  |     assert(stmt); | ||||||
|  |     if (sqlite3_reset(stmt) != SQLITE_OK) | ||||||
|  |         throw SQLiteError(db, "resetting statement"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| SQLiteStmt::~SQLiteStmt() | SQLiteStmt::~SQLiteStmt() | ||||||
| { | { | ||||||
|     try { |     try { | ||||||
|  | @ -188,14 +196,11 @@ LocalStore::LocalStore() | ||||||
| LocalStore::~LocalStore() | LocalStore::~LocalStore() | ||||||
| { | { | ||||||
|     try { |     try { | ||||||
|         flushDelayedUpdates(); |  | ||||||
| 
 |  | ||||||
|         foreach (RunningSubstituters::iterator, i, runningSubstituters) { |         foreach (RunningSubstituters::iterator, i, runningSubstituters) { | ||||||
|             i->second.to.close(); |             i->second.to.close(); | ||||||
|             i->second.from.close(); |             i->second.from.close(); | ||||||
|             i->second.pid.wait(true); |             i->second.pid.wait(true); | ||||||
|         } |         } | ||||||
|                  |  | ||||||
|     } catch (...) { |     } catch (...) { | ||||||
|         ignoreException(); |         ignoreException(); | ||||||
|     } |     } | ||||||
|  | @ -231,6 +236,7 @@ void LocalStore::prepareStatements() | ||||||
|         "insert into ValidPaths (path, hash, registrationTime, deriver) values (?, ?, ?, ?);"); |         "insert into ValidPaths (path, hash, registrationTime, deriver) values (?, ?, ?, ?);"); | ||||||
|     stmtAddReference.create(db, |     stmtAddReference.create(db, | ||||||
|         "insert into Refs (referrer, reference) values (?, ?);"); |         "insert into Refs (referrer, reference) values (?, ?);"); | ||||||
|  |     stmtIsValidPath.create(db, "select 1 from ValidPaths where path = ?;"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -308,98 +314,6 @@ void canonicalisePathMetaData(const Path & path) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static Path infoFileFor(const Path & path) |  | ||||||
| { |  | ||||||
|     string baseName = baseNameOf(path); |  | ||||||
|     return (format("%1%/info/%2%") % nixDBPath % baseName).str(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static Path referrersFileFor(const Path & path) |  | ||||||
| { |  | ||||||
|     string baseName = baseNameOf(path); |  | ||||||
|     return (format("%1%/referrer/%2%") % nixDBPath % baseName).str(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static Path failedFileFor(const Path & path) |  | ||||||
| { |  | ||||||
|     string baseName = baseNameOf(path); |  | ||||||
|     return (format("%1%/failed/%2%") % nixDBPath % baseName).str(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static Path tmpFileForAtomicUpdate(const Path & path) |  | ||||||
| { |  | ||||||
|     return (format("%1%/.%2%.%3%") % dirOf(path) % getpid() % baseNameOf(path)).str(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void LocalStore::appendReferrer(const Path & from, const Path & to, bool lock) |  | ||||||
| { |  | ||||||
|     Path referrersFile = referrersFileFor(from); |  | ||||||
|      |  | ||||||
|     PathLocks referrersLock; |  | ||||||
|     if (lock) { |  | ||||||
|         referrersLock.lockPaths(singleton<PathSet, Path>(referrersFile)); |  | ||||||
|         referrersLock.setDeletion(true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     AutoCloseFD fd = open(referrersFile.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666); |  | ||||||
|     if (fd == -1) throw SysError(format("opening file `%1%'") % referrersFile); |  | ||||||
|      |  | ||||||
|     string s = " " + to; |  | ||||||
|     writeFull(fd, (const unsigned char *) s.c_str(), s.size()); |  | ||||||
| 
 |  | ||||||
|     if (doFsync) fdatasync(fd); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* Atomically update the referrers file.  If `purge' is true, the set
 |  | ||||||
|    of referrers is set to `referrers'.  Otherwise, the current set of |  | ||||||
|    referrers is purged of invalid paths. */ |  | ||||||
| void LocalStore::rewriteReferrers(const Path & path, bool purge, PathSet referrers) |  | ||||||
| { |  | ||||||
|     Path referrersFile = referrersFileFor(path); |  | ||||||
|      |  | ||||||
|     PathLocks referrersLock(singleton<PathSet, Path>(referrersFile)); |  | ||||||
|     referrersLock.setDeletion(true); |  | ||||||
| 
 |  | ||||||
|     if (purge) |  | ||||||
|         /* queryReferrers() purges invalid paths, so that's all we
 |  | ||||||
|            need. */ |  | ||||||
|         queryReferrers(path, referrers); |  | ||||||
| 
 |  | ||||||
|     Path tmpFile = tmpFileForAtomicUpdate(referrersFile); |  | ||||||
|      |  | ||||||
|     AutoCloseFD fd = open(tmpFile.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666); |  | ||||||
|     if (fd == -1) throw SysError(format("opening file `%1%'") % referrersFile); |  | ||||||
|      |  | ||||||
|     string s; |  | ||||||
|     foreach (PathSet::const_iterator, i, referrers) { |  | ||||||
|         s += " "; s += *i; |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     writeFull(fd, (const unsigned char *) s.c_str(), s.size()); |  | ||||||
| 
 |  | ||||||
|     if (doFsync) fdatasync(fd); |  | ||||||
|      |  | ||||||
|     fd.close(); /* for Windows; can't rename open file */ |  | ||||||
| 
 |  | ||||||
|     if (rename(tmpFile.c_str(), referrersFile.c_str()) == -1) |  | ||||||
|         throw SysError(format("cannot rename `%1%' to `%2%'") % tmpFile % referrersFile); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void LocalStore::flushDelayedUpdates() |  | ||||||
| { |  | ||||||
|     foreach (PathSet::iterator, i, delayedUpdates) { |  | ||||||
|         rewriteReferrers(*i, true, PathSet()); |  | ||||||
|     } |  | ||||||
|     delayedUpdates.clear(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void LocalStore::registerValidPath(const Path & path, | void LocalStore::registerValidPath(const Path & path, | ||||||
|     const Hash & hash, const PathSet & references, |     const Hash & hash, const PathSet & references, | ||||||
|     const Path & deriver) |     const Path & deriver) | ||||||
|  | @ -415,6 +329,7 @@ void LocalStore::registerValidPath(const Path & path, | ||||||
| 
 | 
 | ||||||
| void LocalStore::registerValidPath(const ValidPathInfo & info, bool ignoreValidity) | void LocalStore::registerValidPath(const ValidPathInfo & info, bool ignoreValidity) | ||||||
| { | { | ||||||
|  | #if 0    
 | ||||||
|     Path infoFile = infoFileFor(info.path); |     Path infoFile = infoFileFor(info.path); | ||||||
| 
 | 
 | ||||||
|     ValidPathInfo oldInfo; |     ValidPathInfo oldInfo; | ||||||
|  | @ -467,22 +382,25 @@ void LocalStore::registerValidPath(const ValidPathInfo & info, bool ignoreValidi | ||||||
|     writeFile(tmpFile, s, doFsync); |     writeFile(tmpFile, s, doFsync); | ||||||
|     if (rename(tmpFile.c_str(), infoFile.c_str()) == -1) |     if (rename(tmpFile.c_str(), infoFile.c_str()) == -1) | ||||||
|         throw SysError(format("cannot rename `%1%' to `%2%'") % tmpFile % infoFile); |         throw SysError(format("cannot rename `%1%' to `%2%'") % tmpFile % infoFile); | ||||||
| 
 | #endif | ||||||
|     pathInfoCache[info.path] = info; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void LocalStore::registerFailedPath(const Path & path) | void LocalStore::registerFailedPath(const Path & path) | ||||||
| { | { | ||||||
|  | #if 0 | ||||||
|     /* Write an empty file in the .../failed directory to denote the
 |     /* Write an empty file in the .../failed directory to denote the
 | ||||||
|        failure of the builder for `path'. */ |        failure of the builder for `path'. */ | ||||||
|     writeFile(failedFileFor(path), ""); |     writeFile(failedFileFor(path), ""); | ||||||
|  | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| bool LocalStore::hasPathFailed(const Path & path) | bool LocalStore::hasPathFailed(const Path & path) | ||||||
| { | { | ||||||
|  | #if 0 | ||||||
|     return pathExists(failedFileFor(path)); |     return pathExists(failedFileFor(path)); | ||||||
|  | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -502,6 +420,7 @@ Hash parseHashField(const Path & path, const string & s) | ||||||
| 
 | 
 | ||||||
| ValidPathInfo LocalStore::queryPathInfo(const Path & path, bool ignoreErrors) | ValidPathInfo LocalStore::queryPathInfo(const Path & path, bool ignoreErrors) | ||||||
| { | { | ||||||
|  | #if 0 | ||||||
|     ValidPathInfo res; |     ValidPathInfo res; | ||||||
|     res.path = path; |     res.path = path; | ||||||
| 
 | 
 | ||||||
|  | @ -510,9 +429,6 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path, bool ignoreErrors) | ||||||
|     if (!isValidPath(path)) |     if (!isValidPath(path)) | ||||||
|         throw Error(format("path `%1%' is not valid") % path); |         throw Error(format("path `%1%' is not valid") % path); | ||||||
| 
 | 
 | ||||||
|     std::map<Path, ValidPathInfo>::iterator lookup = pathInfoCache.find(path); |  | ||||||
|     if (lookup != pathInfoCache.end()) return lookup->second; |  | ||||||
|      |  | ||||||
|     /* Read the info file. */ |     /* Read the info file. */ | ||||||
|     Path infoFile = infoFileFor(path); |     Path infoFile = infoFileFor(path); | ||||||
|     if (!pathExists(infoFile)) |     if (!pathExists(infoFile)) | ||||||
|  | @ -550,31 +466,20 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path, bool ignoreErrors) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return pathInfoCache[path] = res; |     return res; | ||||||
|  | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| bool LocalStore::isValidPath(const Path & path) | bool LocalStore::isValidPath(const Path & path) | ||||||
| { | { | ||||||
|     /* Files in the info directory starting with a `.' are temporary
 |     stmtIsValidPath.reset(); | ||||||
|        files. */ |     if (sqlite3_bind_text(stmtIsValidPath, 1, path.c_str(), -1, SQLITE_TRANSIENT) != SQLITE_OK) | ||||||
|     if (baseNameOf(path).at(0) == '.') return false; |         throw SQLiteError(db, "binding argument"); | ||||||
| 
 |     int res = sqlite3_step(stmtIsValidPath); | ||||||
|     /* A path is valid if its info file exists and has a non-zero
 |     if (res != SQLITE_DONE && res != SQLITE_ROW) | ||||||
|        size.  (The non-zero size restriction is to be robust to |         throw SQLiteError(db, "querying path in database"); | ||||||
|        certain kinds of filesystem corruption, particularly with |     return res == SQLITE_ROW; | ||||||
|        ext4.) */ |  | ||||||
|     Path infoFile = infoFileFor(path); |  | ||||||
| 
 |  | ||||||
|     struct stat st; |  | ||||||
|     if (lstat(infoFile.c_str(), &st)) { |  | ||||||
|         if (errno == ENOENT) return false; |  | ||||||
|         throw SysError(format("getting status of `%1%'") % infoFile); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (st.st_size == 0) return false; |  | ||||||
|      |  | ||||||
|     return true; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -598,6 +503,7 @@ void LocalStore::queryReferences(const Path & path, | ||||||
| 
 | 
 | ||||||
| bool LocalStore::queryReferrersInternal(const Path & path, PathSet & referrers) | bool LocalStore::queryReferrersInternal(const Path & path, PathSet & referrers) | ||||||
| { | { | ||||||
|  | #if 0 | ||||||
|     bool allValid = true; |     bool allValid = true; | ||||||
|      |      | ||||||
|     if (!isValidPath(path)) |     if (!isValidPath(path)) | ||||||
|  | @ -623,6 +529,7 @@ bool LocalStore::queryReferrersInternal(const Path & path, PathSet & referrers) | ||||||
|         if (isStorePath(*i) && isValidPath(*i)) referrers.insert(*i); else allValid = false; |         if (isStorePath(*i) && isValidPath(*i)) referrers.insert(*i); else allValid = false; | ||||||
| 
 | 
 | ||||||
|     return allValid; |     return allValid; | ||||||
|  | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -788,6 +695,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) | ||||||
|    there are no referrers. */ |    there are no referrers. */ | ||||||
| void LocalStore::invalidatePath(const Path & path) | void LocalStore::invalidatePath(const Path & path) | ||||||
| { | { | ||||||
|  | #if 0    
 | ||||||
|     debug(format("invalidating path `%1%'") % path); |     debug(format("invalidating path `%1%'") % path); | ||||||
| 
 | 
 | ||||||
|     ValidPathInfo info; |     ValidPathInfo info; | ||||||
|  | @ -805,28 +713,7 @@ void LocalStore::invalidatePath(const Path & path) | ||||||
|     Path p = referrersFileFor(path); |     Path p = referrersFileFor(path); | ||||||
|     if (pathExists(p) && unlink(p.c_str()) == -1) |     if (pathExists(p) && unlink(p.c_str()) == -1) | ||||||
|         throw SysError(format("unlinking `%1%'") % p); |         throw SysError(format("unlinking `%1%'") % p); | ||||||
| 
 | #endif | ||||||
|     /* Clear `path' from the info cache. */ |  | ||||||
|     pathInfoCache.erase(path); |  | ||||||
|     delayedUpdates.erase(path); |  | ||||||
| 
 |  | ||||||
|     /* Cause the referrer files for each path referenced by this one
 |  | ||||||
|        to be updated.  This has to happen after removing the info file |  | ||||||
|        to preserve the invariant (see registerValidPath()). |  | ||||||
| 
 |  | ||||||
|        The referrer files are updated lazily in flushDelayedUpdates() |  | ||||||
|        to prevent quadratic performance in the garbage collector |  | ||||||
|        (i.e., when N referrers to some path X are deleted, we have to |  | ||||||
|        rewrite the referrers file for X N times, causing O(N^2) I/O). |  | ||||||
| 
 |  | ||||||
|        What happens if we die before the referrer file can be updated? |  | ||||||
|        That's not a problem, because stale (invalid) entries in the |  | ||||||
|        referrer file are ignored by queryReferrers().  Thus a referrer |  | ||||||
|        file is allowed to have stale entries; removing them is just an |  | ||||||
|        optimisation.  verifyStore() gets rid of them eventually. |  | ||||||
|     */ |  | ||||||
|     foreach (PathSet::iterator, i, info.references) |  | ||||||
|         if (*i != path) delayedUpdates.insert(*i); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1130,6 +1017,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source) | ||||||
| void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFreed, | void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFreed, | ||||||
|     unsigned long long & blocksFreed) |     unsigned long long & blocksFreed) | ||||||
| { | { | ||||||
|  | #if 0 | ||||||
|     bytesFreed = 0; |     bytesFreed = 0; | ||||||
| 
 | 
 | ||||||
|     assertStorePath(path); |     assertStorePath(path); | ||||||
|  | @ -1149,11 +1037,13 @@ void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFr | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     deletePathWrapped(path, bytesFreed, blocksFreed); |     deletePathWrapped(path, bytesFreed, blocksFreed); | ||||||
|  | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void LocalStore::verifyStore(bool checkContents) | void LocalStore::verifyStore(bool checkContents) | ||||||
| { | { | ||||||
|  | #if 0 | ||||||
|     /* Check whether all valid paths actually exist. */ |     /* Check whether all valid paths actually exist. */ | ||||||
|     printMsg(lvlInfo, "checking path existence"); |     printMsg(lvlInfo, "checking path existence"); | ||||||
| 
 | 
 | ||||||
|  | @ -1279,6 +1169,64 @@ void LocalStore::verifyStore(bool checkContents) | ||||||
| 
 | 
 | ||||||
|         if (update) rewriteReferrers(from, false, referrersNew); |         if (update) rewriteReferrers(from, false, referrersNew); | ||||||
|     } |     } | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Functions for upgrading from the pre-SQLite database. */ | ||||||
|  | 
 | ||||||
|  | static Path infoFileFor(const Path & path) | ||||||
|  | { | ||||||
|  |     string baseName = baseNameOf(path); | ||||||
|  |     return (format("%1%/info/%2%") % nixDBPath % baseName).str(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | PathSet LocalStore::queryValidPathsOld() | ||||||
|  | { | ||||||
|  |     PathSet paths; | ||||||
|  |     Strings entries = readDirectory(nixDBPath + "/info"); | ||||||
|  |     foreach (Strings::iterator, i, entries) | ||||||
|  |         if (i->at(0) != '.') paths.insert(nixStore + "/" + *i); | ||||||
|  |     return paths; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ValidPathInfo LocalStore::queryPathInfoOld(const Path & path) | ||||||
|  | { | ||||||
|  |     ValidPathInfo res; | ||||||
|  |     res.path = path; | ||||||
|  | 
 | ||||||
|  |     /* Read the info file. */ | ||||||
|  |     Path infoFile = infoFileFor(path); | ||||||
|  |     if (!pathExists(infoFile)) | ||||||
|  |         throw Error(format("path `%1%' is not valid") % path); | ||||||
|  |     string info = readFile(infoFile); | ||||||
|  | 
 | ||||||
|  |     /* Parse it. */ | ||||||
|  |     Strings lines = tokenizeString(info, "\n"); | ||||||
|  | 
 | ||||||
|  |     foreach (Strings::iterator, i, lines) { | ||||||
|  |         string::size_type p = i->find(':'); | ||||||
|  |         if (p == string::npos) | ||||||
|  |             throw Error(format("corrupt line in `%1%': %2%") % infoFile % *i); | ||||||
|  |         string name(*i, 0, p); | ||||||
|  |         string value(*i, p + 2); | ||||||
|  |         if (name == "References") { | ||||||
|  |             Strings refs = tokenizeString(value, " "); | ||||||
|  |             res.references = PathSet(refs.begin(), refs.end()); | ||||||
|  |         } else if (name == "Deriver") { | ||||||
|  |             res.deriver = value; | ||||||
|  |         } else if (name == "Hash") { | ||||||
|  |             res.hash = parseHashField(path, value); | ||||||
|  |         } else if (name == "Registered-At") { | ||||||
|  |             int n = 0; | ||||||
|  |             string2Int(value, n); | ||||||
|  |             res.registrationTime = n; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1294,17 +1242,16 @@ void LocalStore::upgradeStore6() | ||||||
| 
 | 
 | ||||||
|     initSchema(); |     initSchema(); | ||||||
| 
 | 
 | ||||||
|     PathSet validPaths = queryValidPaths(); |     PathSet validPaths = queryValidPathsOld(); | ||||||
| 
 | 
 | ||||||
|     SQLiteTxn txn(db); |     SQLiteTxn txn(db); | ||||||
|      |      | ||||||
|     std::map<Path, sqlite3_int64> pathToId; |     std::map<Path, sqlite3_int64> pathToId; | ||||||
|      |      | ||||||
|     foreach (PathSet::iterator, i, validPaths) { |     foreach (PathSet::iterator, i, validPaths) { | ||||||
|         ValidPathInfo info = queryPathInfo(*i, true); |         ValidPathInfo info = queryPathInfoOld(*i); | ||||||
|          |          | ||||||
|         if (sqlite3_reset(stmtRegisterValidPath) != SQLITE_OK) |         stmtRegisterValidPath.reset(); | ||||||
|             throw SQLiteError(db, "resetting statement"); |  | ||||||
|         if (sqlite3_bind_text(stmtRegisterValidPath, 1, i->c_str(), -1, SQLITE_TRANSIENT) != SQLITE_OK) |         if (sqlite3_bind_text(stmtRegisterValidPath, 1, i->c_str(), -1, SQLITE_TRANSIENT) != SQLITE_OK) | ||||||
|             throw SQLiteError(db, "binding argument 1"); |             throw SQLiteError(db, "binding argument 1"); | ||||||
|         string h = "sha256:" + printHash(info.hash); |         string h = "sha256:" + printHash(info.hash); | ||||||
|  | @ -1330,11 +1277,10 @@ void LocalStore::upgradeStore6() | ||||||
|     std::cerr << "|"; |     std::cerr << "|"; | ||||||
|      |      | ||||||
|     foreach (PathSet::iterator, i, validPaths) { |     foreach (PathSet::iterator, i, validPaths) { | ||||||
|         ValidPathInfo info = queryPathInfo(*i, true); |         ValidPathInfo info = queryPathInfoOld(*i); | ||||||
|          |          | ||||||
|         foreach (PathSet::iterator, j, info.references) { |         foreach (PathSet::iterator, j, info.references) { | ||||||
|             if (sqlite3_reset(stmtAddReference) != SQLITE_OK) |             stmtAddReference.reset(); | ||||||
|                 throw SQLiteError(db, "resetting statement"); |  | ||||||
|             if (sqlite3_bind_int(stmtAddReference, 1, pathToId[*i]) != SQLITE_OK) |             if (sqlite3_bind_int(stmtAddReference, 1, pathToId[*i]) != SQLITE_OK) | ||||||
|                 throw SQLiteError(db, "binding argument 1"); |                 throw SQLiteError(db, "binding argument 1"); | ||||||
|             if (pathToId.find(*j) == pathToId.end()) |             if (pathToId.find(*j) == pathToId.end()) | ||||||
|  |  | ||||||
|  | @ -63,6 +63,7 @@ struct SQLiteStmt | ||||||
|     sqlite3_stmt * stmt; |     sqlite3_stmt * stmt; | ||||||
|     SQLiteStmt() { stmt = 0; } |     SQLiteStmt() { stmt = 0; } | ||||||
|     void create(sqlite3 * db, const string & s); |     void create(sqlite3 * db, const string & s); | ||||||
|  |     void reset(); | ||||||
|     ~SQLiteStmt(); |     ~SQLiteStmt(); | ||||||
|     operator sqlite3_stmt * () { return stmt; } |     operator sqlite3_stmt * () { return stmt; } | ||||||
| }; | }; | ||||||
|  | @ -178,13 +179,6 @@ private: | ||||||
|     /* Lock file used for upgrading. */ |     /* Lock file used for upgrading. */ | ||||||
|     AutoCloseFD globalLock; |     AutoCloseFD globalLock; | ||||||
| 
 | 
 | ||||||
|     /* !!! The cache can grow very big.  Maybe it should be pruned
 |  | ||||||
|        every once in a while. */ |  | ||||||
|     std::map<Path, ValidPathInfo> pathInfoCache; |  | ||||||
| 
 |  | ||||||
|     /* Store paths for which the referrers file must be purged. */ |  | ||||||
|     PathSet delayedUpdates; |  | ||||||
| 
 |  | ||||||
|     /* Whether to do an fsync() after writing Nix metadata. */ |     /* Whether to do an fsync() after writing Nix metadata. */ | ||||||
|     bool doFsync; |     bool doFsync; | ||||||
| 
 | 
 | ||||||
|  | @ -194,6 +188,7 @@ private: | ||||||
|     /* Some precompiled SQLite statements. */ |     /* Some precompiled SQLite statements. */ | ||||||
|     SQLiteStmt stmtRegisterValidPath; |     SQLiteStmt stmtRegisterValidPath; | ||||||
|     SQLiteStmt stmtAddReference; |     SQLiteStmt stmtAddReference; | ||||||
|  |     SQLiteStmt stmtIsValidPath; | ||||||
| 
 | 
 | ||||||
|     int getSchema(); |     int getSchema(); | ||||||
| 
 | 
 | ||||||
|  | @ -209,13 +204,13 @@ private: | ||||||
|      |      | ||||||
|     void rewriteReferrers(const Path & path, bool purge, PathSet referrers); |     void rewriteReferrers(const Path & path, bool purge, PathSet referrers); | ||||||
| 
 | 
 | ||||||
|     void flushDelayedUpdates(); |  | ||||||
|      |  | ||||||
|     bool queryReferrersInternal(const Path & path, PathSet & referrers); |     bool queryReferrersInternal(const Path & path, PathSet & referrers); | ||||||
|      |      | ||||||
|     void invalidatePath(const Path & path); |     void invalidatePath(const Path & path); | ||||||
| 
 | 
 | ||||||
|     void upgradeStore6(); |     void upgradeStore6(); | ||||||
|  |     PathSet queryValidPathsOld(); | ||||||
|  |     ValidPathInfo queryPathInfoOld(const Path & path); | ||||||
| 
 | 
 | ||||||
|     struct GCState; |     struct GCState; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue