From 627afcc1aa981dc0cbb3880ae54f37878755e1d6 Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Tue, 28 Aug 2007 15:22:27 +0000 Subject: [PATCH] Fixed a lot of remote store issues. But there is still a bug with 32bit unsigned integers: 'implementation cannot deal with > 32-bit integers' --- src/libexpr/primops.cc | 4 +- src/libstore/build.cc | 2 +- src/libstore/db.cc | 10 ++-- src/libstore/db.hh | 2 +- src/libstore/globals.cc | 19 ++++--- src/libstore/globals.hh | 7 +++ src/libstore/misc.cc | 17 +++++- src/libstore/misc.hh | 3 ++ src/libstore/remote-store.cc | 17 +++--- src/libstore/worker-protocol.hh | 2 +- src/libutil/serialise.cc | 2 +- src/libutil/util.cc | 4 +- src/nix-env/nix-env.cc | 2 +- src/nix-state/nix-state.cc | 9 ++-- src/nix-store/nix-store.cc | 4 +- src/nix-worker/nix-worker.cc | 94 ++++++++++++++++++++++++++------- 16 files changed, 144 insertions(+), 54 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index d99d2b6fb..846cc259c 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -621,7 +621,7 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) if(enableState && !disableState){ if(runtimeStateArgs == ""){ string enableStateS = bool2string("true"); - drv.stateOutputs["state"] = DerivationStateOutput("", "", "", "", stateIdentifier, enableStateS, "", "", "", runtimeStateArgs, queryCallingUsername(), "", false); + drv.stateOutputs["state"] = DerivationStateOutput("", "", "", "", stateIdentifier, enableStateS, "", "", "", runtimeStateArgs, queryCurrentUsername(), "", false); } } @@ -657,7 +657,7 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) string enableStateS = bool2string("true"); string createDirsBeforeInstallS = bool2string(createDirsBeforeInstall); drv.stateOutputs["state"] = DerivationStateOutput(stateOutPath, printHash(componentHash), outputHashAlgo, outputHash, stateIdentifier, enableStateS, - shareType, syncState, createDirsBeforeInstallS, runtimeStateArgs, queryCallingUsername(), sharedState); + shareType, syncState, createDirsBeforeInstallS, runtimeStateArgs, queryCurrentUsername(), sharedState); for(vector::iterator i = stateDirs.begin(); i != stateDirs.end(); ++i) drv.stateOutputDirs[(*i).path] = *(i); diff --git a/src/libstore/build.cc b/src/libstore/build.cc index ff1281630..e5c2a82eb 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1830,7 +1830,7 @@ void DerivationGoal::computeClosure() } txn.commit(); - + /* It is now safe to delete the lock files, since all future lockers will see that the output paths are valid; they will not create new lock files with the same names as the old (unlinked) diff --git a/src/libstore/db.cc b/src/libstore/db.cc index 230254b26..309bd4c8a 100644 --- a/src/libstore/db.cc +++ b/src/libstore/db.cc @@ -71,7 +71,7 @@ Transaction::~Transaction() void Transaction::begin(Database & db) { assert(txn == 0); - db.requireEnv(); + db.requireEnv("begin transaction"); try { db.env->txn_begin(0, &txn, 0); } catch (DbException e) { rethrow(e); } @@ -110,11 +110,11 @@ void Transaction::moveTo(Transaction & t) } -void Database::requireEnv() +void Database::requireEnv(string debug) { checkInterrupt(); - if (!env) throw Error("database environment is not open " - "(maybe you don't have sufficient permission?)"); + if (!env) throw Error(format("database environment is not open while trying '%1%'" + "(maybe you don't have sufficient permission?)") % debug); } @@ -300,7 +300,7 @@ void Database::close() TableId Database::openTable(const string & tableName, bool sorted) { - requireEnv(); + requireEnv(tableName); TableId table = nextId++; try { diff --git a/src/libstore/db.hh b/src/libstore/db.hh index a15ab22c5..b932ba432 100644 --- a/src/libstore/db.hh +++ b/src/libstore/db.hh @@ -54,7 +54,7 @@ private: TableId nextId; std::map tables; - void requireEnv(); + void requireEnv(string debug); Db * getDb(TableId table); diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 4575d96b2..bd5e75984 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -28,8 +28,8 @@ bool readOnlyMode = false; string thisSystem = "unset"; unsigned int maxSilentTime = 0; static bool settingsRead = false; -uid_t callingUID = 0; -bool debugWorker = true; +uid_t callingUID = 0; //A root user will not set this value, so the default uid is 0 +bool debugWorker = false; //TODO still experimental static std::map settings; @@ -132,16 +132,23 @@ void setCallingUID(uid_t uid, bool reset) callingUID = uid; } -string queryCallingUsername() +string uidToUsername(uid_t uid) { - uid_t uid = queryCallingUID(); - passwd *pwd = getpwuid(uid); char *pw_name = pwd->pw_name; - return (string)pw_name; } +string queryCallingUsername() +{ + uid_t uid = queryCallingUID(); + return uidToUsername(uid); +} + +string queryCurrentUsername() +{ + return uidToUsername(geteuid()); +} } diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index a85c2f63c..cf72f3621 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -86,9 +86,16 @@ extern uid_t callingUID; /* get/set the UID of the user that calls the nix-worker daemon */ uid_t queryCallingUID(); void setCallingUID(uid_t uid, bool reset = false); + +/* Convert a uid to a username: Watch it! this segfaults when given a wrong uid !! */ +string uidToUsername(uid_t uid); + /* get the username based on the UID of the user that calls the nix-worker daemon */ string queryCallingUsername(); +/* get the username based on the UID of the user currently runs the process */ +string queryCurrentUsername(); + extern bool debugWorker; } diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 6364c40d6..f38d91a08 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -9,16 +9,29 @@ namespace nix { -Derivation derivationFromPathTxn(const Transaction & txn, const Path & drvPath) +Derivation derivationFromPathPrivate(const bool dotxn, const Transaction & txn, const Path & drvPath) { assertStorePath(drvPath); - ensurePathTxn(txn, drvPath); + if(dotxn) + ensurePathTxn(txn, drvPath); + else + store->ensurePath(drvPath); ATerm t = ATreadFromNamedFile(drvPath.c_str()); if (!t) throw Error(format("cannot read aterm from `%1%'") % drvPath); return parseDerivation(t); } +//Wrappers +Derivation derivationFromPath(const Path & drvPath) +{ + return derivationFromPathPrivate(false, noTxn, drvPath); +} +Derivation derivationFromPathTxn(const Transaction & txn, const Path & drvPath) +{ + return derivationFromPathPrivate(true, txn, drvPath); +} + void computeFSClosure(const Path & path, PathSet & paths, const bool & withComponents, const bool & withState, const int revision, bool flipDirection) { computeFSClosureTxn(noTxn, path, paths, withComponents, withState, revision, flipDirection); diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh index 8290ccb93..6f77fafbb 100644 --- a/src/libstore/misc.hh +++ b/src/libstore/misc.hh @@ -12,6 +12,9 @@ namespace nix { ensurePath(). */ Derivation derivationFromPathTxn(const Transaction & txn, const Path & drvPath); +/* Same as above, but wihouth a txn now. This function can be called from the user side */ +Derivation derivationFromPath(const Path & drvPath); + /* Place in `paths' the set of all store paths in the file system closure of `storePath'; that is, all paths than can be directly or indirectly reached from it. `paths' is not cleared. If diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 6fc73cda5..c88bbb2bb 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -274,9 +274,7 @@ Path RemoteStore::addToStore(const Path & _srcPath, bool fixed, writeString(hashAlgo, to); dumpPath(srcPath, to, filter); processStderr(); - printMsg(lvlInfo, format("REMOTESTORE: ADD TO STORE REMOTE 1")); Path path = readStorePath(from); - printMsg(lvlInfo, format("REMOTESTORE: ADD TO STORE REMOTE 2")); return path; } @@ -396,6 +394,14 @@ void RemoteStore::collectGarbage(GCAction action, const PathSet & pathsToDelete, bytesFreed = (((unsigned long long) hi) << 32) | lo; } +Path RemoteStore::queryDeriver(const Path & path) +{ + writeInt(wopQueryDeriver, to); + writeString(path, to); + processStderr(); + return readStorePath(from); +} + PathSet RemoteStore::queryDerivers(const Path & storePath, const string & identifier, const string & user) { writeInt(wopQueryDerivers, to); @@ -498,13 +504,6 @@ void RemoteStore::scanAndUpdateAllReferences(const Path & statePath, const bool readInt(from); } -Path RemoteStore::queryDeriver(const Path & path) -{ - writeInt(wopQueryDeriver, to); - writeString(path, to); - processStderr(); - return readStorePath(from); -} PathSet RemoteStore::toNonSharedPathSet(const PathSet & statePaths) { diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index 807b0a093..1cf0c98c8 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -24,7 +24,7 @@ typedef enum { wopQueryStateReferrers, wopAddToStore, wopAddTextToStore, - wopBuildDerivations, + wopBuildDerivations, //TODO HANGS SOMETIMES !!!!! wopEnsurePath, wopAddTempRoot, wopAddIndirectRoot, diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 635e90e97..5d1791262 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -117,7 +117,7 @@ unsigned int readInt(Source & source) unsigned char buf[8]; source(buf, sizeof(buf)); if (buf[4] || buf[5] || buf[6] || buf[7]) - throw Error("implementation cannot deal with > 32-bit integers"); + throw Error("implementation cannot deal with > 32-bit integers"); //TODO !!!!!!!!!!!!!!!!! unsigned Int reader return buf[0] | (buf[1] << 8) | diff --git a/src/libutil/util.cc b/src/libutil/util.cc index f19c80277..52b86ed79 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -370,9 +370,9 @@ void writeStringToFile(const Path & path, const string & s) LogType logType = ltPretty; -//Verbosity verbosity = lvlInfo; +Verbosity verbosity = lvlInfo; //Verbosity verbosity = lvlDebug; -Verbosity verbosity = lvlVomit; +//Verbosity verbosity = lvlVomit; static int nestingLevel = 0; diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 6e15bc519..3065edf21 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -496,7 +496,7 @@ static void installDerivations(Globals & globals, //Set the state indentifier if it is a state-component printMsg(lvlError, format("New component to install DRV: '%1%'") % i->queryDrvPath(globals.state)); - Derivation drv = derivationFromPathTxn(noTxn, i->queryDrvPath(globals.state)); + Derivation drv = derivationFromPath(i->queryDrvPath(globals.state)); if(isStateDrv(drv)) { DerivationStateOutputs stateOutputs = drv.stateOutputs; diff --git a/src/nix-state/nix-state.cc b/src/nix-state/nix-state.cc index 06a050dc8..3e1eba3e3 100644 --- a/src/nix-state/nix-state.cc +++ b/src/nix-state/nix-state.cc @@ -84,7 +84,7 @@ Derivation getDerivation(const string & fullPath, const Strings & program_args, //Retrieve the derivation, there is only 1 drvPath in derivers derivationPath = *(derivers.begin()); - Derivation drv = derivationFromPathTxn(noTxn, derivationPath); + Derivation drv = derivationFromPath(derivationPath); if(isStateComponent){ DerivationStateOutputs stateOutputs = drv.stateOutputs; @@ -474,6 +474,9 @@ void run(Strings args) return; printMsg(lvlError, format("header: '%1%'") % nixExt3CowHeader); + + printMsg(lvlError, format("Username fail: '%1%'") % uidToUsername(23423)); //Segfaults correctly + return; */ @@ -551,9 +554,9 @@ void run(Strings args) throw UsageError("only one operation may be specified"); } - //If no username given: take the username of the caller + //If no username given get it if(username == "") - username = int2String(geteuid()); + username = queryCurrentUsername(); if (!op) throw UsageError("no operation specified"); diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 86d4c1ed6..07f5aa3fb 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -75,7 +75,7 @@ static Path realisePath(const Path & path) PathSet paths; paths.insert(path); store->buildDerivations(paths); - Path outPath = findOutput(derivationFromPathTxn(noTxn, path), "out"); + Path outPath = findOutput(derivationFromPath(path), "out"); if (gcRoot == "") printGCWarning(); @@ -100,7 +100,7 @@ static void opRealise(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) *i = fixPath(*i); - + if (opArgs.size() > 1) { PathSet drvPaths; for (Strings::iterator i = opArgs.begin(); diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc index eb6876119..5ba64b654 100644 --- a/src/nix-worker/nix-worker.cc +++ b/src/nix-worker/nix-worker.cc @@ -337,23 +337,16 @@ static void performOp(Source & from, Sink & to, unsigned int op) bool recursive = readInt(from) == 1; string hashAlgo = readString(from); - printMsg(lvlInfo, format("NIXWORKER: WOP 1")); - /* !!! uberquick hack */ Path tmp = createTempDir(); AutoDelete delTmp(tmp); Path tmp2 = tmp + "/" + baseName; restorePath(tmp2, from); - printMsg(lvlInfo, format("NIXWORKER: WOP 2")); - startWork(); Path path = store->addToStore(tmp2, fixed, recursive, hashAlgo); stopWork(); - - printMsg(lvlInfo, format("NIXWORKER: WOP 3 '%1%'") % path); writeString(path, to); - printMsg(lvlInfo, format("NIXWORKER: WOP 4")); break; } @@ -478,57 +471,122 @@ static void performOp(Source & from, Sink & to, unsigned int op) } case wopSetStatePathsInterval: { - + PathSet statePaths = readStringSet(from); + IntVector intervals = readIntVector(from); + bool allZero = readInt(from) == 1; + startWork(); + store->setStatePathsInterval(statePaths, intervals, allZero); + stopWork(); + writeInt(1, to); break; } case wopGetStatePathsInterval: { - + PathSet statePaths = readStringSet(from); + startWork(); + IntVector iv = store->getStatePathsInterval(statePaths); + stopWork(); + writeIntVector(iv, to); break; } case wopIsStateComponent: { - + Path path = readString(from); + startWork(); + bool result = store->isStateComponent(path); + stopWork(); + writeInt(result, to); break; } case wopStorePathRequisites: { - + Path storeOrstatePath = readString(from); + bool includeOutputs = readInt(from) == 1; + PathSet paths = readStringSet(from); + bool withComponents = readInt(from) == 1; + bool withState = readInt(from) == 1; + int revision = readInt(from); + startWork(); + store->storePathRequisites(storeOrstatePath, includeOutputs, paths, withComponents, withState, revision); + stopWork(); + writeInt(1, to); break; } case wopSetStateRevisions: { - + RevisionClosure revisions = readRevisionClosure(from); + Path rootStatePath = readString(from); + string comment = readString(from); + startWork(); + store->setStateRevisions(revisions, rootStatePath, comment); + stopWork(); + writeInt(1, to); break; } case wopQueryStateRevisions: { - + Path statePath = readString(from); + int revision = readInt(from); + RevisionClosure revisions; + RevisionClosureTS timestamps; + startWork(); + bool result = store->queryStateRevisions(statePath, revisions, timestamps, revision); + stopWork(); + writeRevisionClosure(revisions, to); + writeRevisionClosureTS(timestamps, to); + writeInt(result, to); break; } case wopQueryAvailableStateRevisions: { - + Path statePath = readString(from); + RevisionInfos revisions; + startWork(); + bool result = store->queryAvailableStateRevisions(statePath, revisions); + stopWork(); + writeRevisionInfos(revisions, to); + writeInt(result, to); break; } case wopCommitStatePath: { - + Path statePath = readString(from); + startWork(); + Snapshots ss = store->commitStatePath(statePath); + stopWork(); + writeSnapshots(ss, to); break; } case wopScanAndUpdateAllReferences: { - + Path statePath = readString(from); + bool recursive = readInt(from) == 1; + startWork(); + store->scanAndUpdateAllReferences(statePath, recursive); + stopWork(); + writeInt(1, to); break; } case wopToNonSharedPathSet: { - + PathSet statePaths = readStringSet(from); + startWork(); + PathSet statePaths_ns = store->toNonSharedPathSet(statePaths); + stopWork(); + writeStringSet(statePaths_ns, to); break; } case wopRevertToRevision: { - + Path componentPath = readString(from); + Path derivationPath = readString(from); + Path statePath = readString(from); + int revision_arg = readInt(from); + bool recursive = readInt(from) == 1; + startWork(); + store->revertToRevision(componentPath, derivationPath, statePath, revision_arg, recursive); + stopWork(); + writeInt(1, to); break; }