* `nix-store --verify --check-contents': don't hold the global GC lock

while checking the contents, since this operation can take a very
  long time to finish.  Also, fill in missing narSize fields in the DB
  while doing this.
This commit is contained in:
Eelco Dolstra 2010-12-06 15:29:38 +00:00
parent de79d23f76
commit 8062d3af30
2 changed files with 48 additions and 10 deletions

View file

@ -353,6 +353,8 @@ void LocalStore::openDB(bool create)
/* Prepare SQL statements. */ /* Prepare SQL statements. */
stmtRegisterValidPath.create(db, stmtRegisterValidPath.create(db,
"insert into ValidPaths (path, hash, registrationTime, deriver, narSize) values (?, ?, ?, ?, ?);"); "insert into ValidPaths (path, hash, registrationTime, deriver, narSize) values (?, ?, ?, ?, ?);");
stmtUpdatePathInfo.create(db,
"update ValidPaths set narSize = ? where path = ?;");
stmtAddReference.create(db, stmtAddReference.create(db,
"insert or replace into Refs (referrer, reference) values (?, ?);"); "insert or replace into Refs (referrer, reference) values (?, ?);");
stmtQueryPathInfo.create(db, stmtQueryPathInfo.create(db,
@ -645,6 +647,21 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
} }
/* Update path info in the database. Currently only updated the
narSize field. */
void LocalStore::updatePathInfo(const ValidPathInfo & info)
{
SQLiteStmtUse use(stmtUpdatePathInfo);
if (info.narSize != 0)
stmtUpdatePathInfo.bind64(info.narSize);
else
stmtUpdatePathInfo.bind(); // null
stmtUpdatePathInfo.bind(info.path);
if (sqlite3_step(stmtUpdatePathInfo) != SQLITE_DONE)
throwSQLiteError(db, format("updating info of path `%1%' in database") % info.path);
}
unsigned long long LocalStore::queryValidPathId(const Path & path) unsigned long long LocalStore::queryValidPathId(const Path & path)
{ {
SQLiteStmtUse use(stmtQueryPathInfo); SQLiteStmtUse use(stmtQueryPathInfo);
@ -1305,23 +1322,41 @@ void LocalStore::verifyStore(bool checkContents)
foreach (PathSet::iterator, i, validPaths2) foreach (PathSet::iterator, i, validPaths2)
verifyPath(*i, store, done, validPaths); verifyPath(*i, store, done, validPaths);
/* Release the GC lock so that checking content hashes (which can
take ages) doesn't block the GC or builds. */
fdGCLock.close();
/* Optionally, check the content hashes (slow). */ /* Optionally, check the content hashes (slow). */
if (checkContents) { if (checkContents) {
printMsg(lvlInfo, "checking hashes..."); printMsg(lvlInfo, "checking hashes...");
foreach (PathSet::iterator, i, validPaths) { foreach (PathSet::iterator, i, validPaths) {
try {
ValidPathInfo info = queryPathInfo(*i); ValidPathInfo info = queryPathInfo(*i);
/* Check the content hash (optionally - slow). */ /* Check the content hash (optionally - slow). */
printMsg(lvlTalkative, format("checking contents of `%1%'") % *i); printMsg(lvlTalkative, format("checking contents of `%1%'") % *i);
Hash current = hashPath(info.hash.type, *i).first; HashResult current = hashPath(info.hash.type, *i);
if (current != info.hash) {
if (current.first != info.hash) {
printMsg(lvlError, format("path `%1%' was modified! " printMsg(lvlError, format("path `%1%' was modified! "
"expected hash `%2%', got `%3%'") "expected hash `%2%', got `%3%'")
% *i % printHash(info.hash) % printHash(current)); % *i % printHash(info.hash) % printHash(current.first));
} else {
/* Fill in missing narSize fields (from old stores). */
if (info.narSize == 0) {
printMsg(lvlError, format("updating size field on `%1%' to %2%") % *i % current.second);
info.narSize = current.second;
updatePathInfo(info);
}
} }
/* !!! Check info.narSize */ } catch (Error & e) {
/* It's possible that the path got GC'ed, so ignore
errors on invalid paths. */
if (isValidPath(*i)) throw;
printMsg(lvlError, format("warning: %1%") % e.msg());
}
} }
} }
} }

View file

@ -203,6 +203,7 @@ private:
/* Some precompiled SQLite statements. */ /* Some precompiled SQLite statements. */
SQLiteStmt stmtRegisterValidPath; SQLiteStmt stmtRegisterValidPath;
SQLiteStmt stmtUpdatePathInfo;
SQLiteStmt stmtAddReference; SQLiteStmt stmtAddReference;
SQLiteStmt stmtQueryPathInfo; SQLiteStmt stmtQueryPathInfo;
SQLiteStmt stmtQueryReferences; SQLiteStmt stmtQueryReferences;
@ -235,6 +236,8 @@ private:
void verifyPath(const Path & path, const PathSet & store, void verifyPath(const Path & path, const PathSet & store,
PathSet & done, PathSet & validPaths); PathSet & done, PathSet & validPaths);
void updatePathInfo(const ValidPathInfo & info);
void upgradeStore6(); void upgradeStore6();
PathSet queryValidPathsOld(); PathSet queryValidPathsOld();
ValidPathInfo queryPathInfoOld(const Path & path); ValidPathInfo queryPathInfoOld(const Path & path);