2006-11-30 21:19:59 +02:00
|
|
|
#include "shared.hh"
|
|
|
|
#include "local-store.hh"
|
|
|
|
#include "util.hh"
|
2006-11-30 21:54:43 +02:00
|
|
|
#include "serialise.hh"
|
2006-11-30 22:13:59 +02:00
|
|
|
#include "worker-protocol.hh"
|
2006-11-30 22:45:20 +02:00
|
|
|
#include "archive.hh"
|
2006-11-30 21:19:59 +02:00
|
|
|
|
|
|
|
using namespace nix;
|
|
|
|
|
|
|
|
|
2006-12-01 00:43:55 +02:00
|
|
|
Path readStorePath(Source & from)
|
|
|
|
{
|
|
|
|
Path path = readString(from);
|
|
|
|
assertStorePath(path);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PathSet readStorePaths(Source & from)
|
|
|
|
{
|
|
|
|
PathSet paths = readStringSet(from);
|
|
|
|
for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i)
|
|
|
|
assertStorePath(*i);
|
|
|
|
return paths;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-30 21:54:43 +02:00
|
|
|
void processConnection(Source & from, Sink & to)
|
2006-11-30 21:19:59 +02:00
|
|
|
{
|
2006-11-30 21:54:43 +02:00
|
|
|
store = boost::shared_ptr<StoreAPI>(new LocalStore(true));
|
2006-11-30 21:19:59 +02:00
|
|
|
|
2006-11-30 21:54:43 +02:00
|
|
|
unsigned int magic = readInt(from);
|
2006-11-30 22:13:59 +02:00
|
|
|
if (magic != WORKER_MAGIC_1) throw Error("protocol mismatch");
|
2006-11-30 21:19:59 +02:00
|
|
|
|
2006-11-30 22:13:59 +02:00
|
|
|
writeInt(WORKER_MAGIC_2, to);
|
2006-11-30 21:54:43 +02:00
|
|
|
|
|
|
|
debug("greeting exchanged");
|
2006-11-30 22:13:59 +02:00
|
|
|
|
|
|
|
bool quit = false;
|
2006-12-01 20:00:01 +02:00
|
|
|
|
|
|
|
unsigned int opCount = 0;
|
2006-11-30 22:13:59 +02:00
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
|
|
WorkerOp op = (WorkerOp) readInt(from);
|
|
|
|
|
2006-12-01 20:00:01 +02:00
|
|
|
opCount++;
|
|
|
|
|
2006-11-30 22:13:59 +02:00
|
|
|
switch (op) {
|
|
|
|
|
|
|
|
case wopQuit:
|
|
|
|
/* Close the database. */
|
|
|
|
store.reset((StoreAPI *) 0);
|
|
|
|
writeInt(1, to);
|
|
|
|
quit = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case wopIsValidPath: {
|
2006-12-01 00:43:55 +02:00
|
|
|
Path path = readStorePath(from);
|
2006-11-30 22:13:59 +02:00
|
|
|
writeInt(store->isValidPath(path), to);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-12-01 00:43:55 +02:00
|
|
|
case wopHasSubstitutes: {
|
|
|
|
Path path = readStorePath(from);
|
|
|
|
writeInt(store->hasSubstitutes(path), to);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case wopQueryReferences:
|
|
|
|
case wopQueryReferrers: {
|
|
|
|
Path path = readStorePath(from);
|
|
|
|
PathSet paths;
|
|
|
|
if (op == wopQueryReferences)
|
|
|
|
store->queryReferences(path, paths);
|
|
|
|
else
|
|
|
|
store->queryReferrers(path, paths);
|
|
|
|
writeStringSet(paths, to);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-12-01 20:00:01 +02:00
|
|
|
case wopAddToStore:
|
|
|
|
case wopAddToStoreFixed: {
|
2006-11-30 22:45:20 +02:00
|
|
|
/* !!! uberquick hack */
|
|
|
|
string baseName = readString(from);
|
2006-12-01 20:00:01 +02:00
|
|
|
bool recursive = false;
|
|
|
|
string hashAlgo;
|
|
|
|
if (op == wopAddToStoreFixed) {
|
|
|
|
recursive = readInt(from) == 1;
|
|
|
|
hashAlgo = readString(from);
|
|
|
|
}
|
|
|
|
|
2006-11-30 22:45:20 +02:00
|
|
|
Path tmp = createTempDir();
|
|
|
|
Path tmp2 = tmp + "/" + baseName;
|
|
|
|
restorePath(tmp2, from);
|
2006-12-01 20:00:01 +02:00
|
|
|
|
|
|
|
if (op == wopAddToStoreFixed)
|
|
|
|
writeString(store->addToStoreFixed(recursive, hashAlgo, tmp2), to);
|
|
|
|
else
|
|
|
|
writeString(store->addToStore(tmp2), to);
|
|
|
|
|
2006-11-30 22:45:20 +02:00
|
|
|
deletePath(tmp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case wopAddTextToStore: {
|
|
|
|
string suffix = readString(from);
|
|
|
|
string s = readString(from);
|
2006-12-01 00:43:55 +02:00
|
|
|
PathSet refs = readStorePaths(from);
|
2006-11-30 22:45:20 +02:00
|
|
|
writeString(store->addTextToStore(suffix, s, refs), to);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-12-01 00:43:55 +02:00
|
|
|
case wopBuildDerivations: {
|
|
|
|
PathSet drvs = readStorePaths(from);
|
|
|
|
store->buildDerivations(drvs);
|
|
|
|
writeInt(1, to);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case wopEnsurePath: {
|
|
|
|
Path path = readStorePath(from);
|
|
|
|
store->ensurePath(path);
|
|
|
|
writeInt(1, to);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-11-30 22:13:59 +02:00
|
|
|
default:
|
2006-11-30 22:45:20 +02:00
|
|
|
throw Error(format("invalid operation %1%") % op);
|
2006-11-30 22:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} while (!quit);
|
2006-12-01 20:00:01 +02:00
|
|
|
|
|
|
|
printMsg(lvlError, format("%1% worker operations") % opCount);
|
2006-11-30 21:19:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void run(Strings args)
|
|
|
|
{
|
|
|
|
bool slave = false;
|
|
|
|
bool daemon = false;
|
|
|
|
|
|
|
|
for (Strings::iterator i = args.begin(); i != args.end(); ) {
|
|
|
|
string arg = *i++;
|
|
|
|
if (arg == "--slave") slave = true;
|
2006-12-01 20:02:05 +02:00
|
|
|
if (arg == "--daemon") daemon = true;
|
2006-11-30 21:19:59 +02:00
|
|
|
}
|
|
|
|
|
2006-11-30 21:54:43 +02:00
|
|
|
if (slave) {
|
|
|
|
FdSource source(STDIN_FILENO);
|
|
|
|
FdSink sink(STDOUT_FILENO);
|
|
|
|
processConnection(source, sink);
|
|
|
|
}
|
2006-11-30 21:19:59 +02:00
|
|
|
|
|
|
|
else if (daemon)
|
|
|
|
throw Error("daemon mode not implemented");
|
|
|
|
|
|
|
|
else
|
|
|
|
throw Error("must be run in either --slave or --daemon mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void printHelp()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-01 20:02:05 +02:00
|
|
|
string programId = "nix-worker";
|