diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 54c48cf91..ab1011981 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -660,7 +660,7 @@ void DerivationGoal::haveStoreExpr() i != invalidOutputs.end(); ++i) /* Don't bother creating a substitution goal if there are no substitutes. */ - if (store->querySubstitutes(*i).size() > 0) + if (store->hasSubstitutes(*i)) addWaitee(worker.makeSubstitutionGoal(*i)); if (waitees.empty()) /* to prevent hang (no wake-up event) */ diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index aa8166d7e..e3f22a9c9 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -481,15 +481,15 @@ void registerSubstitute(const Transaction & txn, } -Substitutes querySubstitutes(const Transaction & txn, const Path & srcPath) +Substitutes querySubstitutes(const Transaction & txn, const Path & path) { - return readSubstitutes(txn, srcPath); + return readSubstitutes(txn, path); } -Substitutes LocalStore::querySubstitutes(const Path & srcPath) +Substitutes LocalStore::querySubstitutes(const Path & path) { - return nix::querySubstitutes(noTxn, srcPath); + return nix::querySubstitutes(noTxn, path); } diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 6849e2c1a..1319245c0 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -64,7 +64,7 @@ void queryMissing(const PathSet & targets, for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i) if (!store->isValidPath(i->second.path) && - store->querySubstitutes(i->second.path).size() == 0) + !store->hasSubstitutes(i->second.path)) mustBuild = true; if (mustBuild) { @@ -81,7 +81,7 @@ void queryMissing(const PathSet & targets, else { if (store->isValidPath(p)) continue; - if (store->querySubstitutes(p).size() > 0) + if (store->hasSubstitutes(p)) willSubstitute.insert(p); PathSet refs; store->queryReferences(p, todo); diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 99f9589be..ce09ddada 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -39,7 +39,7 @@ RemoteStore::RemoteStore() throw SysError("dupping read side"); execlp(worker.c_str(), worker.c_str(), - "-vvv", "--slave", NULL); + "--slave", NULL); throw SysError(format("executing `%1%'") % worker); @@ -81,32 +81,44 @@ bool RemoteStore::isValidPath(const Path & path) } -Substitutes RemoteStore::querySubstitutes(const Path & srcPath) +Substitutes RemoteStore::querySubstitutes(const Path & path) { - // writeInt(wopQuerySubstitutes); - - // throw Error("not implemented 2"); - return Substitutes(); + throw Error("not implemented 2"); +} + + +bool RemoteStore::hasSubstitutes(const Path & path) +{ + writeInt(wopHasSubstitutes, to); + writeString(path, to); + unsigned int reply = readInt(from); + return reply != 0; } Hash RemoteStore::queryPathHash(const Path & path) { - throw Error("not implemented"); + throw Error("not implemented 3"); } -void RemoteStore::queryReferences(const Path & storePath, +void RemoteStore::queryReferences(const Path & path, PathSet & references) { - throw Error("not implemented"); + writeInt(wopQueryReferences, to); + writeString(path, to); + PathSet references2 = readStringSet(from); + references.insert(references2.begin(), references2.end()); } -void RemoteStore::queryReferrers(const Path & storePath, +void RemoteStore::queryReferrers(const Path & path, PathSet & referrers) { - throw Error("not implemented"); + writeInt(wopQueryReferrers, to); + writeString(path, to); + PathSet referrers2 = readStringSet(from); + referrers.insert(referrers2.begin(), referrers2.end()); } @@ -123,7 +135,7 @@ Path RemoteStore::addToStore(const Path & srcPath) Path RemoteStore::addToStoreFixed(bool recursive, string hashAlgo, const Path & srcPath) { - throw Error("not implemented 4"); + throw Error("not implemented 6"); } @@ -133,9 +145,7 @@ Path RemoteStore::addTextToStore(const string & suffix, const string & s, writeInt(wopAddTextToStore, to); writeString(suffix, to); writeString(s, to); - writeInt(references.size(), to); - for (PathSet::iterator i = references.begin(); i != references.end(); ++i) - writeString(*i, to); + writeStringSet(references, to); Path path = readString(from); return path; @@ -144,13 +154,17 @@ Path RemoteStore::addTextToStore(const string & suffix, const string & s, void RemoteStore::buildDerivations(const PathSet & drvPaths) { - throw Error("not implemented 6"); + writeInt(wopBuildDerivations, to); + writeStringSet(drvPaths, to); + readInt(from); } -void RemoteStore::ensurePath(const Path & storePath) +void RemoteStore::ensurePath(const Path & path) { - throw Error("not implemented 7"); + writeInt(wopEnsurePath, to); + writeString(path, to); + readInt(from); } diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index da6911cf4..eaa9b82ee 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -27,15 +27,15 @@ public: bool isValidPath(const Path & path); - Substitutes querySubstitutes(const Path & srcPath); + Substitutes querySubstitutes(const Path & path); + bool hasSubstitutes(const Path & path); + Hash queryPathHash(const Path & path); - void queryReferences(const Path & storePath, - PathSet & references); + void queryReferences(const Path & path, PathSet & references); - void queryReferrers(const Path & storePath, - PathSet & referrers); + void queryReferrers(const Path & path, PathSet & referrers); Path addToStore(const Path & srcPath); @@ -47,7 +47,7 @@ public: void buildDerivations(const PathSet & drvPaths); - void ensurePath(const Path & storePath); + void ensurePath(const Path & path); private: Pipe toChild; diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 9e8bc36d7..f1e7c3562 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -6,6 +6,12 @@ namespace nix { +bool StoreAPI::hasSubstitutes(const Path & path) +{ + return !querySubstitutes(path).empty(); +} + + bool isInStore(const Path & path) { return path[0] == '/' diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index abf27a346..31e8152e8 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -43,7 +43,11 @@ public: virtual bool isValidPath(const Path & path) = 0; /* Return the substitutes for the given path. */ - virtual Substitutes querySubstitutes(const Path & srcPath) = 0; + virtual Substitutes querySubstitutes(const Path & path) = 0; + + /* More efficient variant if we just want to know if a path has + substitutes. */ + virtual bool hasSubstitutes(const Path & path); /* Queries the hash of a valid path. */ virtual Hash queryPathHash(const Path & path) = 0; @@ -121,7 +125,6 @@ extern boost::shared_ptr store; boost::shared_ptr openStore(bool reserveSpace = true); - } diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index dd711f330..16b616c80 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -10,8 +10,15 @@ typedef enum { wopQuit, wopIsValidPath, wopQuerySubstitutes, + wopHasSubstitutes, + wopQueryPathHash, + wopQueryReferences, + wopQueryReferrers, wopAddToStore, + wopAddToStoreFixed, wopAddTextToStore, + wopBuildDerivations, + wopEnsurePath, } WorkerOp; diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index aa11c590a..969f638ef 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -48,6 +48,14 @@ void writeString(const string & s, Sink & sink) } +void writeStringSet(const StringSet & ss, Sink & sink) +{ + writeInt(ss.size(), sink); + for (StringSet::iterator i = ss.begin(); i != ss.end(); ++i) + writeString(*i, sink); +} + + void readPadding(unsigned int len, Source & source) { if (len % 8) { @@ -84,4 +92,14 @@ string readString(Source & source) } +StringSet readStringSet(Source & source) +{ + unsigned int count = readInt(source); + StringSet ss; + while (count--) + ss.insert(readString(source)); + return ss; +} + + } diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index 6be10b552..fe3492235 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -69,12 +69,14 @@ struct FdSource : Source void writePadding(unsigned int len, Sink & sink); void writeInt(unsigned int n, Sink & sink); void writeString(const string & s, Sink & sink); +void writeStringSet(const StringSet & ss, Sink & sink); void readPadding(unsigned int len, Source & source); unsigned int readInt(Source & source); string readString(Source & source); +StringSet readStringSet(Source & source); + - } diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc index ce0bef069..a9f343870 100644 --- a/src/nix-env/main.cc +++ b/src/nix-env/main.cc @@ -832,18 +832,18 @@ static void opQuery(Globals & globals, XMLAttrs attrs; if (printStatus) { - Substitutes subs = store->querySubstitutes(i->queryOutPath(globals.state)); + bool hasSubs = store->hasSubstitutes(i->queryOutPath(globals.state)); bool isInstalled = installed.find(i->queryOutPath(globals.state)) != installed.end(); bool isValid = store->isValidPath(i->queryOutPath(globals.state)); if (xmlOutput) { attrs["installed"] = isInstalled ? "1" : "0"; attrs["valid"] = isValid ? "1" : "0"; - attrs["substitutable"] = !subs.empty() ? "1" : "0"; + attrs["substitutable"] = hasSubs ? "1" : "0"; } else columns.push_back( (string) (isInstalled ? "I" : "-") + (isValid ? "P" : "-") - + (!subs.empty() ? "S" : "-")); + + (hasSubs ? "S" : "-")); } if (xmlOutput) diff --git a/src/nix-worker/main.cc b/src/nix-worker/main.cc index d834e625e..8ac69561f 100644 --- a/src/nix-worker/main.cc +++ b/src/nix-worker/main.cc @@ -8,6 +8,23 @@ using namespace nix; +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; +} + + void processConnection(Source & from, Sink & to) { store = boost::shared_ptr(new LocalStore(true)); @@ -35,12 +52,29 @@ void processConnection(Source & from, Sink & to) break; case wopIsValidPath: { - Path path = readString(from); - assertStorePath(path); + Path path = readStorePath(from); writeInt(store->isValidPath(path), to); break; } + 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; + } + case wopAddToStore: { /* !!! uberquick hack */ string baseName = readString(from); @@ -55,17 +89,25 @@ void processConnection(Source & from, Sink & to) case wopAddTextToStore: { string suffix = readString(from); string s = readString(from); - unsigned int refCount = readInt(from); - PathSet refs; - while (refCount--) { - Path ref = readString(from); - assertStorePath(ref); - refs.insert(ref); - } + PathSet refs = readStorePaths(from); writeString(store->addTextToStore(suffix, s, refs), to); break; } + 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; + } + default: throw Error(format("invalid operation %1%") % op); }