* Refactoring: move all database manipulation into store.cc.
* Removed `--query --generators'.
This commit is contained in:
parent
5fc7127643
commit
ebff82222c
|
@ -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()
|
||||
{
|
||||
if (!env) throw Error("database environment not open");
|
||||
|
|
|
@ -29,6 +29,8 @@ public:
|
|||
|
||||
void abort();
|
||||
void commit();
|
||||
|
||||
void moveTo(Transaction & t);
|
||||
};
|
||||
|
||||
|
||||
|
|
11
src/expr.cc
11
src/expr.cc
|
@ -39,14 +39,11 @@ Path writeTerm(ATerm t, const string & suffix)
|
|||
(string) h + suffix + ".nix");
|
||||
|
||||
if (!isValidPath(path)) {
|
||||
if (!ATwriteToNamedTextFile(t, path.c_str()))
|
||||
throw Error(format("cannot write aterm %1%") % path);
|
||||
|
||||
Transaction txn(nixDB);
|
||||
registerValidPath(txn, path);
|
||||
txn.commit();
|
||||
char * s = ATwriteToString(t);
|
||||
if (!s) throw Error(format("cannot write aterm to `%1%'") % path);
|
||||
addTextToStore(path, string(s));
|
||||
}
|
||||
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,37 +1,8 @@
|
|||
#include "globals.hh"
|
||||
#include "db.hh"
|
||||
|
||||
|
||||
Database nixDB;
|
||||
|
||||
|
||||
TableId dbValidPaths;
|
||||
TableId dbSuccessors;
|
||||
TableId dbSuccessorsRev;
|
||||
TableId dbSubstitutes;
|
||||
TableId dbSubstitutesRev;
|
||||
|
||||
|
||||
string nixStore = "/UNINIT";
|
||||
string nixDataDir = "/UNINIT";
|
||||
string nixLogDir = "/UNINIT";
|
||||
string nixDBPath = "/UNINIT";
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -3,65 +3,8 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "db.hh"
|
||||
|
||||
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. */
|
||||
|
||||
/* nixStore is the directory where we generally store atomic and
|
||||
|
@ -83,11 +26,4 @@ extern string nixDBPath;
|
|||
extern bool keepFailed;
|
||||
|
||||
|
||||
/* Open the database environment. */
|
||||
void openDB();
|
||||
|
||||
/* Create the required database tables. */
|
||||
void initDB();
|
||||
|
||||
|
||||
#endif /* !__GLOBALS_H */
|
||||
|
|
|
@ -23,7 +23,6 @@ Query flags:
|
|||
|
||||
--list / -l: query the output paths (roots) of a Nix expression (default)
|
||||
--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
|
||||
--graph: print a dot graph rooted at given ids
|
||||
|
||||
|
|
22
src/nix.cc
22
src/nix.cc
|
@ -73,7 +73,7 @@ Path maybeNormalise(const Path & ne, bool normalise)
|
|||
/* Perform various sorts of queries. */
|
||||
static void opQuery(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
enum { qList, qRequisites, qGenerators, qPredecessors, qGraph
|
||||
enum { qList, qRequisites, qPredecessors, qGraph
|
||||
} query = qList;
|
||||
bool normalise = false;
|
||||
bool includeExprs = true;
|
||||
|
@ -83,7 +83,6 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
|||
i != opFlags.end(); i++)
|
||||
if (*i == "--list" || *i == "-l") query = qList;
|
||||
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 == "--graph") query = qGraph;
|
||||
else if (*i == "--normalise" || *i == "-n") normalise = true;
|
||||
|
@ -124,22 +123,6 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
|||
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: {
|
||||
for (Strings::iterator i = opArgs.begin();
|
||||
i != opArgs.end(); i++)
|
||||
|
@ -172,7 +155,8 @@ static void opSuccessor(Strings opFlags, Strings opArgs)
|
|||
if (!opFlags.empty()) throw UsageError("unknown flag");
|
||||
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();
|
||||
i != opArgs.end(); )
|
||||
{
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "normalise.hh"
|
||||
#include "references.hh"
|
||||
#include "db.hh"
|
||||
#include "exec.hh"
|
||||
#include "pathlocks.hh"
|
||||
#include "globals.hh"
|
||||
|
@ -11,7 +10,7 @@
|
|||
static Path useSuccessor(const Path & path)
|
||||
{
|
||||
string pathSucc;
|
||||
if (nixDB.queryString(noTxn, dbSuccessors, path, pathSucc)) {
|
||||
if (querySuccessor(path, pathSucc)) {
|
||||
debug(format("successor %1% -> %2%") % (string) path % pathSucc);
|
||||
return pathSucc;
|
||||
} else
|
||||
|
@ -349,7 +348,8 @@ Path normaliseNixExpr(const Path & _nePath, PathSet pending)
|
|||
for recoverability: unregistered paths in the store can be
|
||||
deleted arbitrarily, while registered paths can only be deleted
|
||||
by running the garbage collector. */
|
||||
Transaction txn(nixDB);
|
||||
Transaction txn;
|
||||
createStoreTransaction(txn);
|
||||
for (PathSet::iterator i = ne.derivation.outputs.begin();
|
||||
i != ne.derivation.outputs.end(); i++)
|
||||
registerValidPath(txn, *i);
|
||||
|
@ -434,50 +434,3 @@ PathSet nixExprRequisites(const Path & nePath,
|
|||
paths, doneSet);
|
||||
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
|
||||
|
|
105
src/store.cc
105
src/store.cc
|
@ -1,7 +1,10 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "store.hh"
|
||||
#include "globals.hh"
|
||||
|
@ -10,6 +13,81 @@
|
|||
#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
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
Path path(canonPath(_path));
|
||||
|
|
18
src/store.hh
18
src/store.hh
|
@ -9,6 +9,15 @@
|
|||
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. */
|
||||
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,
|
||||
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
|
||||
path. */
|
||||
Paths queryPredecessors(const Path & sucPath);
|
||||
|
@ -42,6 +55,11 @@ bool isValidPath(const Path & path);
|
|||
the resulting path. The resulting path is returned. */
|
||||
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. */
|
||||
void deleteFromStore(const Path & path);
|
||||
|
||||
|
|
Loading…
Reference in a new issue