* Refactoring: move all database manipulation into store.cc.

* Removed `--query --generators'.
This commit is contained in:
Eelco Dolstra 2003-10-15 12:42:39 +00:00
parent 5fc7127643
commit ebff82222c
10 changed files with 143 additions and 170 deletions

View file

@ -70,6 +70,14 @@ void Transaction::abort()
} }
void Transaction::moveTo(Transaction & t)
{
if (t.txn) throw Error("target txn already exists");
t.txn = txn;
txn = 0;
}
void Database::requireEnv() void Database::requireEnv()
{ {
if (!env) throw Error("database environment not open"); if (!env) throw Error("database environment not open");

View file

@ -29,6 +29,8 @@ public:
void abort(); void abort();
void commit(); void commit();
void moveTo(Transaction & t);
}; };

View file

@ -39,12 +39,9 @@ Path writeTerm(ATerm t, const string & suffix)
(string) h + suffix + ".nix"); (string) h + suffix + ".nix");
if (!isValidPath(path)) { if (!isValidPath(path)) {
if (!ATwriteToNamedTextFile(t, path.c_str())) char * s = ATwriteToString(t);
throw Error(format("cannot write aterm %1%") % path); if (!s) throw Error(format("cannot write aterm to `%1%'") % path);
addTextToStore(path, string(s));
Transaction txn(nixDB);
registerValidPath(txn, path);
txn.commit();
} }
return path; return path;

View file

@ -1,37 +1,8 @@
#include "globals.hh" #include "globals.hh"
#include "db.hh"
Database nixDB;
TableId dbValidPaths;
TableId dbSuccessors;
TableId dbSuccessorsRev;
TableId dbSubstitutes;
TableId dbSubstitutesRev;
string nixStore = "/UNINIT"; string nixStore = "/UNINIT";
string nixDataDir = "/UNINIT"; string nixDataDir = "/UNINIT";
string nixLogDir = "/UNINIT"; string nixLogDir = "/UNINIT";
string nixDBPath = "/UNINIT"; string nixDBPath = "/UNINIT";
bool keepFailed = false; bool keepFailed = false;
void openDB()
{
nixDB.open(nixDBPath);
dbValidPaths = nixDB.openTable("validpaths");
dbSuccessors = nixDB.openTable("successors");
dbSuccessorsRev = nixDB.openTable("successors-rev");
dbSubstitutes = nixDB.openTable("substitutes");
dbSubstitutesRev = nixDB.openTable("substitutes-rev");
}
void initDB()
{
}

View file

@ -3,65 +3,8 @@
#include <string> #include <string>
#include "db.hh"
using namespace std; using namespace std;
extern Database nixDB;
/* Database tables. */
/* dbValidPaths :: Path -> ()
The existence of a key $p$ indicates that path $p$ is valid (that
is, produced by a succesful build). */
extern TableId dbValidPaths;
/* dbSuccessors :: Path -> Path
Each pair $(p_1, p_2)$ in this mapping records the fact that the
Nix expression stored at path $p_1$ has a successor expression
stored at path $p_2$.
Note that a term $y$ is a successor of $x$ iff there exists a
sequence of rewrite steps that rewrites $x$ into $y$.
*/
extern TableId dbSuccessors;
/* dbSuccessorsRev :: Path -> [Path]
The reverse mapping of dbSuccessors (i.e., it stores the
predecessors of a Nix expression).
*/
extern TableId dbSuccessorsRev;
/* dbSubstitutes :: Path -> [Path]
Each pair $(p, [ps])$ tells Nix that it can realise any of the
Nix expressions stored at paths $ps$ to produce a path $p$.
The main purpose of this is for distributed caching of derivates.
One system can compute a derivate and put it on a website (as a Nix
archive), for instance, and then another system can register a
substitute for that derivate. The substitute in this case might be
a Nix expression that fetches the Nix archive.
*/
extern TableId dbSubstitutes;
/* dbSubstitutesRev :: Path -> [Path]
The reverse mapping of dbSubstitutes.
*/
extern TableId dbSubstitutesRev;
/* Path names. */ /* Path names. */
/* nixStore is the directory where we generally store atomic and /* nixStore is the directory where we generally store atomic and
@ -83,11 +26,4 @@ extern string nixDBPath;
extern bool keepFailed; extern bool keepFailed;
/* Open the database environment. */
void openDB();
/* Create the required database tables. */
void initDB();
#endif /* !__GLOBALS_H */ #endif /* !__GLOBALS_H */

View file

@ -23,7 +23,6 @@ Query flags:
--list / -l: query the output paths (roots) of a Nix expression (default) --list / -l: query the output paths (roots) of a Nix expression (default)
--requisites / -r: print all paths necessary to realise expression --requisites / -r: print all paths necessary to realise expression
--generators / -g: find expressions producing a subset of given ids
--predecessors: print predecessors of a Nix expression --predecessors: print predecessors of a Nix expression
--graph: print a dot graph rooted at given ids --graph: print a dot graph rooted at given ids

View file

@ -73,7 +73,7 @@ Path maybeNormalise(const Path & ne, bool normalise)
/* Perform various sorts of queries. */ /* Perform various sorts of queries. */
static void opQuery(Strings opFlags, Strings opArgs) static void opQuery(Strings opFlags, Strings opArgs)
{ {
enum { qList, qRequisites, qGenerators, qPredecessors, qGraph enum { qList, qRequisites, qPredecessors, qGraph
} query = qList; } query = qList;
bool normalise = false; bool normalise = false;
bool includeExprs = true; bool includeExprs = true;
@ -83,7 +83,6 @@ static void opQuery(Strings opFlags, Strings opArgs)
i != opFlags.end(); i++) i != opFlags.end(); i++)
if (*i == "--list" || *i == "-l") query = qList; if (*i == "--list" || *i == "-l") query = qList;
else if (*i == "--requisites" || *i == "-r") query = qRequisites; else if (*i == "--requisites" || *i == "-r") query = qRequisites;
else if (*i == "--generators" || *i == "-g") query = qGenerators;
else if (*i == "--predecessors") query = qPredecessors; else if (*i == "--predecessors") query = qPredecessors;
else if (*i == "--graph") query = qGraph; else if (*i == "--graph") query = qGraph;
else if (*i == "--normalise" || *i == "-n") normalise = true; else if (*i == "--normalise" || *i == "-n") normalise = true;
@ -124,22 +123,6 @@ static void opQuery(Strings opFlags, Strings opArgs)
break; break;
} }
#if 0
case qGenerators: {
FSIds outIds;
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); i++)
outIds.push_back(checkPath(*i));
FSIds genIds = findGenerators(outIds);
for (FSIds::iterator i = genIds.begin();
i != genIds.end(); i++)
cout << format("%s\n") % expandId(*i);
break;
}
#endif
case qPredecessors: { case qPredecessors: {
for (Strings::iterator i = opArgs.begin(); for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); i++) i != opArgs.end(); i++)
@ -172,7 +155,8 @@ static void opSuccessor(Strings opFlags, Strings opArgs)
if (!opFlags.empty()) throw UsageError("unknown flag"); if (!opFlags.empty()) throw UsageError("unknown flag");
if (opArgs.size() % 2) throw UsageError("expecting even number of arguments"); if (opArgs.size() % 2) throw UsageError("expecting even number of arguments");
Transaction txn(nixDB); /* !!! this could be a big transaction */ Transaction txn;
createStoreTransaction(txn);
for (Strings::iterator i = opArgs.begin(); for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ) i != opArgs.end(); )
{ {

View file

@ -2,7 +2,6 @@
#include "normalise.hh" #include "normalise.hh"
#include "references.hh" #include "references.hh"
#include "db.hh"
#include "exec.hh" #include "exec.hh"
#include "pathlocks.hh" #include "pathlocks.hh"
#include "globals.hh" #include "globals.hh"
@ -11,7 +10,7 @@
static Path useSuccessor(const Path & path) static Path useSuccessor(const Path & path)
{ {
string pathSucc; string pathSucc;
if (nixDB.queryString(noTxn, dbSuccessors, path, pathSucc)) { if (querySuccessor(path, pathSucc)) {
debug(format("successor %1% -> %2%") % (string) path % pathSucc); debug(format("successor %1% -> %2%") % (string) path % pathSucc);
return pathSucc; return pathSucc;
} else } else
@ -349,7 +348,8 @@ Path normaliseNixExpr(const Path & _nePath, PathSet pending)
for recoverability: unregistered paths in the store can be for recoverability: unregistered paths in the store can be
deleted arbitrarily, while registered paths can only be deleted deleted arbitrarily, while registered paths can only be deleted
by running the garbage collector. */ by running the garbage collector. */
Transaction txn(nixDB); Transaction txn;
createStoreTransaction(txn);
for (PathSet::iterator i = ne.derivation.outputs.begin(); for (PathSet::iterator i = ne.derivation.outputs.begin();
i != ne.derivation.outputs.end(); i++) i != ne.derivation.outputs.end(); i++)
registerValidPath(txn, *i); registerValidPath(txn, *i);
@ -434,50 +434,3 @@ PathSet nixExprRequisites(const Path & nePath,
paths, doneSet); paths, doneSet);
return paths; return paths;
} }
#if 0
PathSet findGenerators(const PathSet & outputs)
{
FSIdSet ids(_ids.begin(), _ids.end());
FSIds generators;
/* !!! hack; for performance, we just look at the rhs of successor
mappings, since we know that those are Nix expressions. */
Strings sucs;
nixDB.enumTable(noTxn, dbSuccessors, sucs);
for (Strings::iterator i = sucs.begin();
i != sucs.end(); i++)
{
string s;
if (!nixDB.queryString(noTxn, dbSuccessors, *i, s)) continue;
FSId id = parseHash(s);
NixExpr ne;
try {
/* !!! should substitutes be used? */
ne = parseNixExpr(termFromId(id));
} catch (...) { /* !!! only catch parse errors */
continue;
}
if (ne.type != NixExpr::neClosure) continue;
bool okay = true;
for (ClosureElems::const_iterator i = ne.closure.elems.begin();
i != ne.closure.elems.end(); i++)
if (ids.find(i->second.id) == ids.end()) {
okay = false;
break;
}
if (!okay) continue;
generators.push_back(id);
}
return generators;
}
#endif

View file

@ -1,7 +1,10 @@
#include <iostream> #include <iostream>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include "store.hh" #include "store.hh"
#include "globals.hh" #include "globals.hh"
@ -10,6 +13,81 @@
#include "pathlocks.hh" #include "pathlocks.hh"
/* Nix database. */
static Database nixDB;
/* Database tables. */
/* dbValidPaths :: Path -> ()
The existence of a key $p$ indicates that path $p$ is valid (that
is, produced by a succesful build). */
static TableId dbValidPaths;
/* dbSuccessors :: Path -> Path
Each pair $(p_1, p_2)$ in this mapping records the fact that the
Nix expression stored at path $p_1$ has a successor expression
stored at path $p_2$.
Note that a term $y$ is a successor of $x$ iff there exists a
sequence of rewrite steps that rewrites $x$ into $y$.
*/
static TableId dbSuccessors;
/* dbSuccessorsRev :: Path -> [Path]
The reverse mapping of dbSuccessors (i.e., it stores the
predecessors of a Nix expression).
*/
static TableId dbSuccessorsRev;
/* dbSubstitutes :: Path -> [Path]
Each pair $(p, [ps])$ tells Nix that it can realise any of the
Nix expressions stored at paths $ps$ to produce a path $p$.
The main purpose of this is for distributed caching of derivates.
One system can compute a derivate and put it on a website (as a Nix
archive), for instance, and then another system can register a
substitute for that derivate. The substitute in this case might be
a Nix expression that fetches the Nix archive.
*/
static TableId dbSubstitutes;
/* dbSubstitutesRev :: Path -> [Path]
The reverse mapping of dbSubstitutes.
*/
static TableId dbSubstitutesRev;
void openDB()
{
nixDB.open(nixDBPath);
dbValidPaths = nixDB.openTable("validpaths");
dbSuccessors = nixDB.openTable("successors");
dbSuccessorsRev = nixDB.openTable("successors-rev");
dbSubstitutes = nixDB.openTable("substitutes");
dbSubstitutesRev = nixDB.openTable("substitutes-rev");
}
void initDB()
{
}
void createStoreTransaction(Transaction & txn)
{
Transaction txn2(nixDB);
txn2.moveTo(txn);
}
/* Path copying. */
struct CopySink : DumpSink struct CopySink : DumpSink
{ {
int fd; int fd;
@ -104,6 +182,12 @@ void registerSuccessor(const Transaction & txn,
} }
bool querySuccessor(const Path & srcPath, Path & sucPath)
{
return nixDB.queryString(noTxn, dbSuccessors, srcPath, sucPath);
}
Paths queryPredecessors(const Path & sucPath) Paths queryPredecessors(const Path & sucPath)
{ {
Paths revs; Paths revs;
@ -204,6 +288,27 @@ Path addToStore(const Path & _srcPath)
} }
void addTextToStore(const Path & dstPath, const string & s)
{
if (!isValidPath(dstPath)) {
/* !!! locking? -> parallel writes are probably idempotent */
int fd = open(dstPath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666);
if (fd == -1) throw SysError(format("creating store file `%1%'") % dstPath);
if (write(fd, s.c_str(), s.size()) != (ssize_t) s.size())
throw SysError(format("writing store file `%1%'") % dstPath);
close(fd); /* !!! close on exception */
Transaction txn(nixDB);
registerValidPath(txn, dstPath);
txn.commit();
}
}
void deleteFromStore(const Path & _path) void deleteFromStore(const Path & _path)
{ {
Path path(canonPath(_path)); Path path(canonPath(_path));

View file

@ -9,6 +9,15 @@
using namespace std; using namespace std;
/* Open the database environment. */
void openDB();
/* Create the required database tables. */
void initDB();
/* Get a transaction object. */
void createStoreTransaction(Transaction & txn);
/* Copy a path recursively. */ /* Copy a path recursively. */
void copyPath(const Path & src, const Path & dst); void copyPath(const Path & src, const Path & dst);
@ -22,6 +31,10 @@ void copyPath(const Path & src, const Path & dst);
void registerSuccessor(const Transaction & txn, void registerSuccessor(const Transaction & txn,
const Path & srcPath, const Path & sucPath); const Path & srcPath, const Path & sucPath);
/* Return the predecessors of the Nix expression stored at the given
path. */
bool querySuccessor(const Path & srcPath, Path & sucPath);
/* Return the predecessors of the Nix expression stored at the given /* Return the predecessors of the Nix expression stored at the given
path. */ path. */
Paths queryPredecessors(const Path & sucPath); Paths queryPredecessors(const Path & sucPath);
@ -42,6 +55,11 @@ bool isValidPath(const Path & path);
the resulting path. The resulting path is returned. */ the resulting path. The resulting path is returned. */
Path addToStore(const Path & srcPath); Path addToStore(const Path & srcPath);
/* Like addToStore, but the path of the output is given, and the
contents written to the output path is a regular file containing
the given string. */
void addTextToStore(const Path & dstPath, const string & s);
/* Delete a value from the nixStore directory. */ /* Delete a value from the nixStore directory. */
void deleteFromStore(const Path & path); void deleteFromStore(const Path & path);