* For debugging: `nix --verify' to check the consistency of the

database and store.
This commit is contained in:
Eelco Dolstra 2003-07-17 12:27:55 +00:00
parent 71cc3ceae5
commit b3fc38bf6a
7 changed files with 139 additions and 14 deletions

View file

@ -157,7 +157,7 @@ void delDB(const string & filename, const string & dbname,
void enumDB(const string & filename, const string & dbname, void enumDB(const string & filename, const string & dbname,
DBPairs & contents) Strings & keys)
{ {
try { try {
@ -168,11 +168,9 @@ void enumDB(const string & filename, const string & dbname,
DbcClose cursorCloser(cursor); DbcClose cursorCloser(cursor);
Dbt kt, dt; Dbt kt, dt;
while (cursor->get(&kt, &dt, DB_NEXT) != DB_NOTFOUND) { while (cursor->get(&kt, &dt, DB_NEXT) != DB_NOTFOUND)
string key((char *) kt.get_data(), kt.get_size()); keys.push_back(
string data((char *) dt.get_data(), dt.get_size()); string((char *) kt.get_data(), kt.get_size()));
contents.push_back(DBPair(key, data));
}
} catch (DbException e) { rethrow(e); } } catch (DbException e) { rethrow(e); }
} }

View file

@ -8,9 +8,6 @@
using namespace std; using namespace std;
typedef pair<string, string> DBPair;
typedef list<DBPair> DBPairs;
void createDB(const string & filename, const string & dbname); void createDB(const string & filename, const string & dbname);
bool queryDB(const string & filename, const string & dbname, bool queryDB(const string & filename, const string & dbname,
@ -29,6 +26,6 @@ void delDB(const string & filename, const string & dbname,
const string & key); const string & key);
void enumDB(const string & filename, const string & dbname, void enumDB(const string & filename, const string & dbname,
DBPairs & contents); Strings & keys);
#endif /* !__DB_H */ #endif /* !__DB_H */

View file

@ -1,8 +1,6 @@
#ifndef __FSTATE_H #ifndef __FSTATE_H
#define __FSTATE_H #define __FSTATE_H
#include <set>
extern "C" { extern "C" {
#include <aterm2.h> #include <aterm2.h>
} }
@ -53,8 +51,6 @@ using namespace std;
typedef ATerm FState; typedef ATerm FState;
typedef ATerm Content; typedef ATerm Content;
typedef set<string> StringSet;
typedef list<FSId> FSIds; typedef list<FSId> FSIds;

View file

@ -283,6 +283,13 @@ static void opInit(Strings opFlags, Strings opArgs)
} }
/* Verify the consistency of the Nix environment. */
static void opVerify(Strings opFlags, Strings opArgs)
{
verifyStore();
}
/* Scan the arguments; find the operation, set global flags, put all /* Scan the arguments; find the operation, set global flags, put all
other flags in a list, and put all other arguments in another other flags in a list, and put all other arguments in another
list. */ list. */
@ -316,6 +323,8 @@ void run(Strings args)
op = opRestore; op = opRestore;
else if (arg == "--init") else if (arg == "--init")
op = opInit; op = opInit;
else if (arg == "--verify")
op = opVerify;
else if (arg[0] == '-') else if (arg[0] == '-')
opFlags.push_back(arg); opFlags.push_back(arg);
else else

View file

@ -260,3 +260,124 @@ void deleteFromStore(const string & path)
deletePath(path); deletePath(path);
} }
void verifyStore()
{
Strings paths;
enumDB(nixDB, dbPath2Id, paths);
for (Strings::iterator i = paths.begin();
i != paths.end(); i++)
{
bool erase = true;
string path = *i;
if (!pathExists(path)) {
debug(format("path `%1%' disappeared") % path);
}
else {
string id;
if (!queryDB(nixDB, dbPath2Id, path, id)) abort();
Strings idPaths;
queryListDB(nixDB, dbId2Paths, id, idPaths);
bool found = false;
for (Strings::iterator j = idPaths.begin();
j != idPaths.end(); j++)
if (path == *j) {
found = true;
break;
}
if (found)
erase = false;
else
/* !!! perhaps we should add path to idPaths? */
debug(format("reverse mapping for path `%1%' missing") % path);
}
if (erase) delDB(nixDB, dbPath2Id, path);
}
Strings ids;
enumDB(nixDB, dbId2Paths, ids);
for (Strings::iterator i = ids.begin();
i != ids.end(); i++)
{
FSId id = parseHash(*i);
Strings idPaths;
queryListDB(nixDB, dbId2Paths, id, idPaths);
for (Strings::iterator j = idPaths.begin();
j != idPaths.end(); )
{
string id2;
if (!queryDB(nixDB, dbPath2Id, *j, id2) ||
id != parseHash(id2)) {
debug(format("erasing path `%1%' from mapping for id %2%")
% *j % (string) id);
j = idPaths.erase(j);
} else j++;
}
setListDB(nixDB, dbId2Paths, id, idPaths);
}
Strings subs;
enumDB(nixDB, dbSubstitutes, subs);
for (Strings::iterator i = subs.begin();
i != subs.end(); i++)
{
FSId srcId = parseHash(*i);
Strings subIds;
queryListDB(nixDB, dbSubstitutes, srcId, subIds);
for (Strings::iterator j = subIds.begin();
j != subIds.end(); )
{
FSId subId = parseHash(*j);
Strings subPaths;
queryListDB(nixDB, dbId2Paths, subId, subPaths);
if (subPaths.size() == 0) {
debug(format("erasing substitute %1% for %2%")
% (string) subId % (string) srcId);
j = subIds.erase(j);
} else j++;
}
setListDB(nixDB, dbSubstitutes, srcId, subIds);
}
Strings sucs;
enumDB(nixDB, dbSuccessors, sucs);
for (Strings::iterator i = sucs.begin();
i != sucs.end(); i++)
{
FSId id1 = parseHash(*i);
string id2;
if (!queryDB(nixDB, dbSuccessors, id1, id2)) abort();
Strings id2Paths;
queryListDB(nixDB, dbId2Paths, id2, id2Paths);
if (id2Paths.size() == 0) {
Strings id2Subs;
queryListDB(nixDB, dbSubstitutes, id2, id2Subs);
if (id2Subs.size() == 0) {
debug(format("successor %1% for %2% missing")
% id2 % (string) id1);
delDB(nixDB, dbSuccessors, (string) id1);
}
}
}
}

View file

@ -35,5 +35,7 @@ void addToStore(string srcPath, string & dstPath, FSId & id,
/* Delete a value from the nixStore directory. */ /* Delete a value from the nixStore directory. */
void deleteFromStore(const string & path); void deleteFromStore(const string & path);
void verifyStore();
#endif /* !__STORE_H */ #endif /* !__STORE_H */

View file

@ -3,6 +3,7 @@
#include <string> #include <string>
#include <list> #include <list>
#include <set>
#include <sstream> #include <sstream>
#include <unistd.h> #include <unistd.h>
@ -38,6 +39,7 @@ public:
typedef list<string> Strings; typedef list<string> Strings;
typedef set<string> StringSet;
/* The canonical system name, as returned by config.guess. */ /* The canonical system name, as returned by config.guess. */