From 53a6b9aaa5e0872747aedf47ffdaf0cf18c82d1a Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Fri, 17 Aug 2007 15:35:34 +0000 Subject: [PATCH] * Fixed very old transactional bug that caused a freeze sometimes * State components that get their state at runtime can now be (un)installed with nix-env --- corepkgs/buildenv/builder.pl.in | 59 ++++++++++++++++++++++++--------- corepkgs/buildenv/default.nix | 3 +- src/libexpr/get-drvs.cc | 23 +++++++++++++ src/libexpr/get-drvs.hh | 7 ++++ src/libexpr/primops.cc | 16 ++++----- src/libstore/Makefile.am | 2 +- src/libstore/build.cc | 16 ++++++--- src/libstore/build.hh | 12 +++++++ src/libstore/db.cc | 2 +- src/libstore/derivations.cc | 12 +++---- src/libstore/derivations.hh | 12 ++++--- src/libstore/gc.cc | 2 +- src/libstore/local-store.cc | 32 +++++++++--------- src/libstore/local-store.hh | 2 ++ src/libstore/misc.cc | 10 +++--- src/libstore/misc.hh | 2 +- src/libstore/store-state.cc | 2 +- src/nix-env/nix-env.cc | 47 +++++++++++++++++--------- src/nix-state/nix-state.cc | 4 +-- src/nix-store/nix-store.cc | 8 ++--- 20 files changed, 186 insertions(+), 87 deletions(-) create mode 100644 src/libstore/build.hh diff --git a/corepkgs/buildenv/builder.pl.in b/corepkgs/buildenv/builder.pl.in index ef8495144..917efc4a5 100755 --- a/corepkgs/buildenv/builder.pl.in +++ b/corepkgs/buildenv/builder.pl.in @@ -10,9 +10,12 @@ STDOUT->autoflush(1); my $out = $ENV{"out"}; mkdir "$out", 0755 || die "error creating $out"; +sub readlink_or_StateWrapper; my $symlinks = 0; -my %path_identifier; +my %path_state_identifier; +my %path_runtimeArgs; + my $nixBinDir = $ENV{"nixBinDir"}; my $nixStore = $ENV{"nixStore"}; @@ -22,12 +25,13 @@ my $nixStore = $ENV{"nixStore"}; sub createLinks { my $srcDir = shift; - #Lookup each $stateIdentifiers in $path_identifier + #Lookup each $stateIdentifiers in $path_state_identifier #we strip $srcDir to its rootdir e.g. /nix/store/......./ my @srcDirParts = split /\// , substr($srcDir, length ($nixStore), length ($srcDir)); my $srcDirRoot = $nixStore . "/" . $srcDirParts[1]; # print "srcDirRoot $srcDirRoot \n"; - my $pkgStateIdentifier = $path_identifier{$srcDirRoot}; + my $pkgStateIdentifier = $path_state_identifier{$srcDirRoot}; + my $pkgRuntimeStateArgs = $path_runtimeArgs{$srcDirRoot}; my $dstDir = shift; my $ignoreCollisions = shift; @@ -93,7 +97,7 @@ sub createLinks { if( $parentDir eq "bin" || $parentDir eq "sbin"){ #hacky.... - print "STATELINK $srcFile to $dstFile \n"; + print "STATELINK $srcFile to $dstFile - $pkgStateIdentifier \n"; my $new_dstFile; my $new_stateIdentifier; @@ -106,23 +110,29 @@ sub createLinks { $new_stateIdentifier = $pkgStateIdentifier; } - if (-l $new_dstFile) { + # We also check with -e if the wrapperscript-file exists, and if is it a symlink (with -l) + if (-l $new_dstFile || -e $new_dstFile) { if (!$ignoreCollisions) { - my $target = readlink $new_dstFile; - die "(state) collission between `$srcFile' and `$target'"; + my $target = readlink_or_StateWrapper $new_dstFile; + die "(state) collission between `$srcFile' and `$target' (over $new_dstFile)"; } } sysopen (DSTFILEHANDLE, $new_dstFile, O_RDWR|O_EXCL|O_CREAT, 0755); printf DSTFILEHANDLE "#! @shell@ \n"; - printf DSTFILEHANDLE "$nixBinDir/nix-state --run --identifier=$new_stateIdentifier $srcFile \"\$@\" \n"; + + if($pkgRuntimeStateArgs eq "__NOARGS__") + { printf DSTFILEHANDLE "$nixBinDir/nix-state --run --identifier=$new_stateIdentifier $srcFile \"\$@\" \n"; } + else + { printf DSTFILEHANDLE "$nixBinDir/nix-state --run --identifier=$new_stateIdentifier $srcFile \"\$@\" $pkgRuntimeStateArgs \n"; } # TODO, maybe first R.T.A. then other args ? + close (DSTFILEHANDLE); } } else{ - if (-l $dstFile) { + if (-l $dstFile || -e $dstFile) { if (!$ignoreCollisions) { - my $target = readlink $dstFile; + my $target = readlink_or_StateWrapper $dstFile; die "collission between `$srcFile' and `$target'"; } } @@ -162,18 +172,37 @@ sub addPkg { } } +sub readlink_or_StateWrapper { + + my $src = shift; + my $target; + + if (-l $src) + { $target = readlink $src; } + else{ + open(DAT, $src) || die("Could not open file!"); + my @raw_data=; + close(DAT); + $target = $raw_data[1]; + } + return $target +} # Symlink to the packages that have been installed explicitly by the user. my @storePaths = split ' ', $ENV{"derivations"}; my @stateIdentifiers = split ' ', $ENV{"stateIdentifiers"}; +my @runtimeStateArgs = split ' ', $ENV{"runtimeStateArgs_arg"}; my $si_counter = 0; foreach my $pkgDir (@storePaths) { #Commented the sort out - #Link each $pkgDir to a $stateIdentifiers in $path_identifier - #print "SP: $pkgDir \n"; - $path_identifier{$pkgDir} = $stateIdentifiers[$si_counter]; - #print "SI: $path_identifier{$pkgDir} \n"; + #Link each $pkgDir to a $stateIdentifiers in $path_state_identifier + $path_state_identifier{$pkgDir} = $stateIdentifiers[$si_counter]; + $path_runtimeArgs{$pkgDir} = $runtimeStateArgs[$si_counter]; + + # print "SP: $pkgDir \n"; + # print "SI: $path_state_identifier{$pkgDir} \n"; + # print "RT: $path_runtimeArgs{$pkgDir} \n"; addPkg($pkgDir, 0); $si_counter++; @@ -193,8 +222,6 @@ while (scalar(keys %postponed) > 0) { } } - print STDERR "created $symlinks symlinks in user environment\n"; - symlink($ENV{"manifest"}, "$out/manifest") or die "cannot create manifest"; diff --git a/corepkgs/buildenv/default.nix b/corepkgs/buildenv/default.nix index 7b6c81263..4804304ae 100644 --- a/corepkgs/buildenv/default.nix +++ b/corepkgs/buildenv/default.nix @@ -1,10 +1,11 @@ -{system, derivations, stateIdentifiers, manifest, nixBinDir, nixStore}: +{system, derivations, stateIdentifiers, runtimeStateArgs, manifest, nixBinDir, nixStore}: derivation { name = "user-environment"; system = system; builder = ./builder.pl; derivations = derivations; + runtimeStateArgs_arg = runtimeStateArgs; stateIdentifiers = stateIdentifiers; manifest = manifest; inherit nixBinDir nixStore; diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 1010c0709..7c16a7798 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -59,6 +59,29 @@ string DrvInfo::queryStateIdentifier(EvalState & state) const return stateIdentifier; } +string DrvInfo::queryRuntimeStateArgs(EvalState & state) const +{ + if (runtimeStateArgs == "") { + ATermMap attrs2 = *attrs; + + for (ATermMap::const_iterator i = attrs2.begin(); i != attrs2.end(); ++i) { + + string key = (string)aterm2String(i->key); //cast because aterm2String returns a char* + if(key == "runtimeStateArgs"){ + PathSet context; + string value = coerceToString(state, i->value, context); + (string &) runtimeStateArgs = value; + } + } + + //If still empty + if (trim(runtimeStateArgs) == "") + (string &) runtimeStateArgs = "__NOARGS__"; + } + + return runtimeStateArgs; +} + MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const { diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index f0ca9205b..5fffd434a 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -21,6 +21,7 @@ private: string drvPath; string outPath; string stateIdentifier; + string runtimeStateArgs; public: string name; @@ -35,6 +36,7 @@ public: string queryDrvPath(EvalState & state) const; string queryOutPath(EvalState & state) const; string queryStateIdentifier(EvalState & state) const; + string queryRuntimeStateArgs(EvalState & state) const; MetaInfo queryMetaInfo(EvalState & state) const; void setDrvPath(const string & s) @@ -52,6 +54,11 @@ public: stateIdentifier = s; } + void setRuntimeStateArgs(const string & s) + { + runtimeStateArgs = s; + } + void setMetaInfo(const MetaInfo & meta); }; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 3cf5f6361..47d60de1a 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -347,7 +347,7 @@ static Hash hashDerivationModulo(EvalState & state, Derivation drv) DerivationStateOutput drvso = drv.stateOutputs["state"]; - if(drvso.runtimeStateParamters != ""){ //Has runtime parameters --> Clear all state parameters + if(drvso.runtimeStateArgs != ""){ //Has runtime parameters --> Clear all state parameters drv.stateOutputs.clear(); drv.stateOutputDirs.clear(); drv.env["statePath"] = ""; @@ -365,7 +365,7 @@ static Hash hashDerivationModulo(EvalState & state, Derivation drv) { Hash h = state.drvHashes[i->first]; if (h.type == htUnknown) { - Derivation drv2 = derivationFromPath(i->first); + Derivation drv2 = derivationFromPathTxn(noTxn, i->first); h = hashDerivationModulo(state, drv2); state.drvHashes[i->first] = h; } @@ -421,7 +421,7 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) string syncState = "none"; string stateIdentifier = ""; bool createDirsBeforeInstall = false; - string runtimeStateParamters = ""; + string runtimeStateArgs = ""; string sharedState = ""; vector stateDirs; @@ -526,7 +526,7 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) else if(key == "disableState") { disableState = evalBool(state, value); } else if(key == "identifier"){ stateIdentifier = coerceToString(state, value, context, true); } else if(key == "createDirsBeforeInstall"){ createDirsBeforeInstall = evalBool(state, value); } - else if(key == "runtimeStateParamters"){ runtimeStateParamters = coerceToString(state, value, context, true); } + else if(key == "runtimeStateArgs"){ runtimeStateArgs = coerceToString(state, value, context, true); } else if(key == "shareStateFrom"){ sharedState = coerceToString(state, value, context, true); } /* All other attributes are passed to the builder through @@ -611,12 +611,12 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) /* If there are no runtime paratermers, then we need to take the the stateIdentifier into account for the hash calcaulation below: hashDerivationModulo(...) * We also add enableState to make it parse the drv to a state-drv - * We also add runtimeStateParamters for the hash calc in hashDerivationModulo(...) to check if its needs to take the stateIdentiefier into account in the hash + * We also add runtimeStateArgs for the hash calc in hashDerivationModulo(...) to check if its needs to take the stateIdentiefier into account in the hash */ if(enableState && !disableState){ - if(runtimeStateParamters == ""){ + if(runtimeStateArgs == ""){ string enableStateS = bool2string("true"); - drv.stateOutputs["state"] = DerivationStateOutput("", "", "", "", stateIdentifier, enableStateS, "", "", "", runtimeStateParamters, getCallingUserName(), "", false); + drv.stateOutputs["state"] = DerivationStateOutput("", "", "", "", stateIdentifier, enableStateS, "", "", "", runtimeStateArgs, getCallingUserName(), "", false); } } @@ -652,7 +652,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, runtimeStateParamters, getCallingUserName(), sharedState); + shareType, syncState, createDirsBeforeInstallS, runtimeStateArgs, getCallingUserName(), sharedState); for(vector::iterator i = stateDirs.begin(); i != stateDirs.end(); ++i) drv.stateOutputDirs[(*i).path] = *(i); diff --git a/src/libstore/Makefile.am b/src/libstore/Makefile.am index 484ba6f4e..e445d2b53 100644 --- a/src/libstore/Makefile.am +++ b/src/libstore/Makefile.am @@ -7,7 +7,7 @@ libstore_la_SOURCES = \ pkginclude_HEADERS = \ store-api.hh local-store.hh remote-store.hh derivations.hh misc.hh \ globals.hh db.hh references.hh pathlocks.hh \ - worker-protocol.hh store-state.hh + worker-protocol.hh store-state.hh build.hh libstore_la_LIBADD = ../libutil/libutil.la \ ../libext3cow/libext3cow.la \ diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 1390588e7..d8c1e2d20 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -6,6 +6,7 @@ #include "db.hh" #include "util.hh" #include "store-state.hh" +#include "build.hh" #include #include @@ -770,7 +771,7 @@ void DerivationGoal::haveDerivation() assert(store->isValidPath(drvPath)); /* Get the derivation. */ - drv = derivationFromPath(drvPath); + drv = derivationFromPathTxn(noTxn, drvPath); for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i) @@ -1319,7 +1320,7 @@ bool DerivationGoal::prepareBuild() `*i' as input paths. Only add the closures of output paths that are specified as inputs. */ assert(store->isValidPath(i->first)); - Derivation inDrv = derivationFromPath(i->first); + Derivation inDrv = derivationFromPathTxn(noTxn, i->first); for (StringSet::iterator j = i->second.begin(); j != i->second.end(); ++j) if (inDrv.outputs.find(*j) != inDrv.outputs.end()){ computeFSClosure(inDrv.outputs[*j].path, inputPaths, true, false, -1); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO COPY STATE (done?) @@ -2600,10 +2601,12 @@ void LocalStore::buildDerivations(const PathSet & drvPaths) } -void LocalStore::ensurePath(const Path & path) +void ensurePathTxn(const Transaction & txn, const Path & path) { /* If the path is already valid, we're done. */ - if (store->isValidPath(path)) return; + + if (isValidPathTxn(txn, path)) + return; Worker worker; GoalPtr goal = worker.makeSubstitutionGoal(path); @@ -2615,5 +2618,10 @@ void LocalStore::ensurePath(const Path & path) throw Error(format("path `%1%' does not exist and cannot be created") % path); } +void LocalStore::ensurePath(const Path & path) +{ + ensurePathTxn(noTxn, path); +} + } diff --git a/src/libstore/build.hh b/src/libstore/build.hh new file mode 100644 index 000000000..369a6acea --- /dev/null +++ b/src/libstore/build.hh @@ -0,0 +1,12 @@ +#ifndef BUILD_HH_ +#define BUILD_HH_ + +#include "db.hh" + +namespace nix { + + void ensurePathTxn(const Transaction & txn, const Path & path); + +} + +#endif /*BUILD_HH_*/ diff --git a/src/libstore/db.cc b/src/libstore/db.cc index 6ec74019c..230254b26 100644 --- a/src/libstore/db.cc +++ b/src/libstore/db.cc @@ -701,7 +701,7 @@ bool Database::queryStateRevisions(const Transaction & txn, TableId revisions_ta //query state versioined directorys/files vector sortedPaths; - Derivation drv = derivationFromPath(queryStatePathDrvTxn(txn, getStatePath)); + Derivation drv = derivationFromPathTxn(txn, queryStatePathDrvTxn(txn, getStatePath)); DerivationStateOutputs stateOutputs = drv.stateOutputs; DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs; for (DerivationStateOutputDirs::const_iterator j = stateOutputDirs.begin(); j != stateOutputDirs.end(); ++j){ diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index c92978b27..66039bd1d 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -66,8 +66,8 @@ void throwBadDrv(ATerm t) Derivation parseDerivation(ATerm t) { Derivation drv; - ATermList outs, solidStateDeps, inDrvs, inSrcs, args, bnds; - ATermList stateOuts = ATempty, stateOutDirs = ATempty; + ATermList outs, inDrvs, inSrcs, args, bnds; + ATermList stateOuts = ATempty, stateOutDirs = ATempty, solidStateDeps = ATempty; ATerm builder, platform; @@ -93,8 +93,8 @@ Derivation parseDerivation(ATerm t) { //parse state part for (ATermIterator i(stateOuts); i; ++i) { - ATerm id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shareType, synchronization, createDirsBeforeInstall, runtimeStateParamters, username, sharedState; - if (!matchDerivationStateOutput(*i, id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shareType, synchronization, createDirsBeforeInstall, runtimeStateParamters, username, sharedState)) + ATerm id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shareType, synchronization, createDirsBeforeInstall, runtimeStateArgs, username, sharedState; + if (!matchDerivationStateOutput(*i, id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shareType, synchronization, createDirsBeforeInstall, runtimeStateArgs, username, sharedState)) throwBadDrv(t); DerivationStateOutput stateOut; stateOut.statepath = aterm2String(statepath); @@ -107,7 +107,7 @@ Derivation parseDerivation(ATerm t) stateOut.shareType = aterm2String(shareType); stateOut.synchronization = aterm2String(synchronization); stateOut.createDirsBeforeInstall = aterm2String(createDirsBeforeInstall); - stateOut.runtimeStateParamters = aterm2String(runtimeStateParamters); + stateOut.runtimeStateArgs = aterm2String(runtimeStateArgs); stateOut.username = aterm2String(username); stateOut.sharedState = aterm2String(sharedState); drv.stateOutputs[aterm2String(id)] = stateOut; @@ -199,7 +199,7 @@ ATerm unparseDerivation(const Derivation & drv) toATerm(i->second.shareType), toATerm(i->second.synchronization), toATerm(i->second.createDirsBeforeInstall), - toATerm(i->second.runtimeStateParamters), + toATerm(i->second.runtimeStateArgs), toATerm(i->second.username), toATerm(i->second.sharedState) )); diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 40a736197..9025f9ed7 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -49,7 +49,7 @@ struct DerivationStateOutput string commitBinaries; //TODO list of binaries that need (or not) to be committed when these binaries are called string createDirsBeforeInstall; //if true: creates state dirs before installation - string runtimeStateParamters; //if not empty: these are the runtime parameters where state can be found (you can use $statepath here) + string runtimeStateArgs; //if not empty: these are the runtime parameters where state can be found (you can use $statepath here) string username; @@ -60,7 +60,7 @@ struct DerivationStateOutput } //TODO add const ?? - DerivationStateOutput(Path statepath, string componentHash, string hashAlgo, string hash, string stateIdentifier, string enabled, string shareType, string synchronization, string createDirsBeforeInstall, string runtimeStateParamters, string username, string sharedState, bool check=true) + DerivationStateOutput(Path statepath, string componentHash, string hashAlgo, string hash, string stateIdentifier, string enabled, string shareType, string synchronization, string createDirsBeforeInstall, string runtimeStateArgs, string username, string sharedState, bool check=true) { if(check){ if(shareType != "none" && shareType != "full" && shareType != "group") @@ -71,6 +71,10 @@ struct DerivationStateOutput throw Error(format("Username cannot be empty")); if(stateIdentifier == "__EMTPY__" || stateIdentifier == "__NOSTATE__") throw Error(format("the stateIdenfier cannot be this value '%1%'") % stateIdentifier); + if(runtimeStateArgs == "__NOARGS__") + throw Error(format("the runtimeStateArgs cannot be this value '%1%'") % runtimeStateArgs); + + } //TODO @@ -86,7 +90,7 @@ struct DerivationStateOutput this->shareType = shareType; this->synchronization = synchronization; this->createDirsBeforeInstall = createDirsBeforeInstall; - this->runtimeStateParamters = runtimeStateParamters; + this->runtimeStateArgs = runtimeStateArgs; this->username = username; this->sharedState = sharedState; } @@ -112,7 +116,7 @@ struct DerivationStateOutput this->shareType = ""; this->synchronization = ""; this->createDirsBeforeInstall = ""; - this->runtimeStateParamters = ""; + this->runtimeStateArgs = ""; //this->username; //Changes the statepath directly this->sharedState = ""; diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 218ba6e54..ab4347e49 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -489,7 +489,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete, for (PathSet::iterator i = livePaths.begin(); i != livePaths.end(); ++i) if (isDerivation(*i)) { - Derivation drv = derivationFromPath(*i); + Derivation drv = derivationFromPathTxn(noTxn, *i); for (DerivationOutputs::iterator j = drv.outputs.begin(); j != drv.outputs.end(); ++j) if (store->isValidPath(j->second.path)) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 37303a951..3d69bc952 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -453,7 +453,6 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath, throw Error(format("cannot set references for path `%1%' which is invalid and has no substitutes") % store_or_statePath); - printMsg(lvlError, format("Setting references for %1% (revision:%2%)") % store_or_statePath % int2String(revision)); /* for (PathSet::iterator i = references.begin(); i != references.end(); ++i) printMsg(lvlError, format("'%2%' has references: %1%") % *i % store_or_statePath); @@ -463,6 +462,8 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath, if(isRealisablePath(txn, store_or_statePath)) { + printMsg(lvlError, format("Setting references for storepath '%1%'") % store_or_statePath); + //Just overwrite the old references, since there is oly 1 revision of a storePath Paths oldReferences_c_c; @@ -481,6 +482,8 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath, else if(isRealisableStatePath(txn, store_or_statePath)) { + printMsg(lvlError, format("Setting references for statepath '%1%' (revision:%2%)") % store_or_statePath % int2String(revision)); + //Write references to a special revision (since there are multiple revisions of a statePath) //query the references of revision (-1 is query the latest references) @@ -498,7 +501,7 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath, } else throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath); - + } void queryXReferencesTxn(const Transaction & txn, const Path & store_or_statePath, PathSet & references, const bool component_or_state, const int revision, int timestamp) @@ -693,9 +696,7 @@ void setDeriver(const Transaction & txn, const Path & storePath, const Path & de if (!isRealisablePath(txn, storePath)) throw Error(format("path `%1%' is not valid") % storePath); - //printMsg(lvlError, format("Ttttttttttttttttttttttttt %1%") % deriver); - - if (isStateDrvPathTxn(txn, deriver)){ //Redirect if its a state component //hanges somtimes !!!!!!!!!!!!!!!!!!! + if (isStateDrvPathTxn(txn, deriver)){ //Redirect if its a state component addStateDeriver(txn, storePath, deriver); } else{ @@ -712,14 +713,14 @@ PathSet mergeNewDerivationIntoList(const Path & storepath, const Path & newdrv, { PathSet newdrvs; - Derivation drv = derivationFromPath(newdrv); + Derivation drv = derivationFromPathTxn(noTxn, newdrv); string identifier = drv.stateOutputs.find("state")->second.stateIdentifier; string user = drv.stateOutputs.find("state")->second.username; for (PathSet::iterator i = drvs.begin(); i != drvs.end(); ++i) //Check if we need to remove old drvs { Path drv = *i; - Derivation getdrv = derivationFromPath(drv); + Derivation getdrv = derivationFromPathTxn(noTxn, drv); string getIdentifier = getdrv.stateOutputs.find("state")->second.stateIdentifier; string getUser = getdrv.stateOutputs.find("state")->second.username; @@ -747,7 +748,7 @@ void addStateDeriver(const Transaction & txn, const Path & storePath, const Path if (!isRealisablePath(txn, storePath)) throw Error(format("path `%1%' is not valid") % storePath); - Derivation drv = derivationFromPath(deriver); + Derivation drv = derivationFromPathTxn(txn, deriver); string identifier = drv.stateOutputs.find("state")->second.stateIdentifier; string user = drv.stateOutputs.find("state")->second.username; @@ -786,8 +787,7 @@ bool LocalStore::isStateComponent(const Path & storePath) bool isStateDrvPathTxn(const Transaction & txn, const Path & drvPath) { - //printMsg(lvlError, format("Sssssssssssssssssss %1%") % drvPath); - Derivation drv = derivationFromPath(drvPath); + Derivation drv = derivationFromPathTxn(txn, drvPath); return isStateDrvTxn(txn, drv); } @@ -817,7 +817,7 @@ Path queryDeriver(const Transaction & txn, const Path & storePath) bool b = nixDB.queryString(txn, dbDerivers, storePath, deriver); - Derivation drv = derivationFromPath(deriver); + Derivation drv = derivationFromPathTxn(txn, deriver); if (isStateDrvTxn(txn, drv)) throw Error(format("This deriver `%1%' is a state deriver, u should use queryDerivers instead of queryDeriver") % deriver); @@ -843,7 +843,7 @@ PathSet queryDerivers(const Transaction & txn, const Path & storePath, const str for (Strings::iterator i = alldata.begin(); i != alldata.end(); ++i) { //filter on username and identifier string derivationpath = (*i); - Derivation drv = derivationFromPath(derivationpath); + Derivation drv = derivationFromPathTxn(txn, derivationpath); if (drv.outputs.size() != 1) throw Error(format("The call queryDerivers with storepath %1% is not a statePath") % storePath); @@ -1093,8 +1093,9 @@ void registerValidPaths(const Transaction & txn, const ValidPathInfos & infos) //We cannot check the statePath since registerValidPath is called twice, first for the component path, and then for the state path.... - if(isStorePath_b) + if(isStorePath_b){ setDeriver(txn, i->path, i->deriver); + } //TODO maybe also set a state deriver into dbStateDerivers .... well state is already linked to a drvpath in dbValidStatePaths .... } @@ -1649,7 +1650,7 @@ void storePathRequisitesTxn(const Transaction & txn, const Path & storeOrstatePa for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) if (isDerivation(*i)) { - Derivation drv = derivationFromPath(*i); + Derivation drv = derivationFromPathTxn(txn, *i); for (DerivationOutputs::iterator j = drv.outputs.begin(); j != drv.outputs.end(); ++j) if (isValidPathTxn(txn, j->second.path)) @@ -1816,9 +1817,8 @@ PathSet getSharedWithPathSetRecTxn(const Transaction & txn, const Path & statePa Path statePath_ns = toNonSharedPathTxn(txn, statePath); PathSet empty; return getSharedWithPathSetRecTxn_private(txn, statePath_ns, empty); -} +} - /* Upgrade from schema 1 (Nix <= 0.7) to schema 2 (Nix >= 0.8). */ static void upgradeStore07() { diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index ef1b7d770..d9e6877d2 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -244,6 +244,8 @@ PathSet toNonSharedPathSetTxn(const Transaction & txn, const PathSet & statePath Path toNonSharedPathTxn(const Transaction & txn, const Path & statePath); PathSet getSharedWithPathSetRecTxn(const Transaction & txn, const Path & statePath); +void ensurePathTxn(const Transaction & txn, const Path & path); + } diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 81ce67bbb..6364c40d6 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -9,13 +9,13 @@ namespace nix { -Derivation derivationFromPath(const Path & drvPath) +Derivation derivationFromPathTxn(const Transaction & txn, const Path & drvPath) { assertStorePath(drvPath); - store->ensurePath(drvPath); - //printMsg(lvlError, format("uuuuuuuuuuuuuuuuuu")); + ensurePathTxn(txn, drvPath); ATerm t = ATreadFromNamedFile(drvPath.c_str()); - if (!t) throw Error(format("cannot read aterm from `%1%'") % drvPath); + if (!t) + throw Error(format("cannot read aterm from `%1%'") % drvPath); return parseDerivation(t); } @@ -103,7 +103,7 @@ void queryMissing(const PathSet & targets, if (isDerivation(p)) { if (!store->isValidPath(p)) continue; - Derivation drv = derivationFromPath(p); + Derivation drv = derivationFromPathTxn(noTxn, p); bool mustBuild = false; for (DerivationOutputs::iterator i = drv.outputs.begin(); diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh index 75446e5e4..8290ccb93 100644 --- a/src/libstore/misc.hh +++ b/src/libstore/misc.hh @@ -10,7 +10,7 @@ namespace nix { /* Read a derivation, after ensuring its existence through ensurePath(). */ -Derivation derivationFromPath(const Path & drvPath); +Derivation derivationFromPathTxn(const Transaction & txn, 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 diff --git a/src/libstore/store-state.cc b/src/libstore/store-state.cc index 16f2cb1d1..5f775015b 100644 --- a/src/libstore/store-state.cc +++ b/src/libstore/store-state.cc @@ -73,7 +73,7 @@ Snapshots commitStatePathTxn(const Transaction & txn, const Path & statePath) throw Error(format("path `%1%' is not a valid state path") % statePath); //queryDeriversStatePath?? - Derivation drv = derivationFromPath(queryStatePathDrvTxn(txn, statePath)); + Derivation drv = derivationFromPathTxn(txn, queryStatePathDrvTxn(txn, statePath)); DerivationStateOutputs stateOutputs = drv.stateOutputs; DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs; diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 5deae1792..f9f97d674 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -162,6 +162,7 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, ATermList manifest = ATempty; ATermList inputs = ATempty; ATermList stateIdentifiers = ATempty; + ATermList runtimeStateArgs = ATempty; for (DrvInfos::const_iterator i = elems.begin(); i != elems.end(); ++i) { @@ -193,6 +194,8 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, //Insert the new stateIdentifier into the stateIdentifiers Atermlist stateIdentifiers = ATinsert(stateIdentifiers, makeStr(i->queryStateIdentifier(state))); + //Insert the new runtime state args into the runtimeStateArgs Atermlist + runtimeStateArgs = ATinsert(runtimeStateArgs, makeStr(i->queryRuntimeStateArgs(state))); inputs = ATinsert(inputs, makeStr(i->queryOutPath(state))); @@ -207,25 +210,34 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, } //printMsg(lvlError, format("TEST '%1%'") % atPrint(canonicaliseExpr(makeList(ATreverse(stateIdentifiers)))) ); + //printMsg(lvlError, format("TEST '%1%'") % atPrint(canonicaliseExpr(makeList(ATreverse(runtimeStateArgs)))) ); /* Also write a copy of the list of inputs to the store; we need it for future modifications of the environment. */ Path manifestFile = store->addTextToStore("env-manifest", atPrint(canonicaliseExpr(makeList(ATreverse(manifest)))), references); - Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList6( - makeBind(toATerm("system"), - makeStr(thisSystem), makeNoPos()), - makeBind(toATerm("derivations"), - makeList(ATreverse(manifest)), makeNoPos()), - makeBind(toATerm("stateIdentifiers"), - makeList(ATreverse(stateIdentifiers)), makeNoPos()), - makeBind(toATerm("manifest"), - makeStr(manifestFile, singleton(manifestFile)), makeNoPos()), - makeBind(toATerm("nixBinDir"), - makeStr(nixBinDir), makeNoPos()), + Expr topLevel = makeCall(envBuilder, makeAttrs( + + ATinsert( + ATmakeList6( + makeBind(toATerm("system"), + makeStr(thisSystem), makeNoPos()), + makeBind(toATerm("derivations"), + makeList(ATreverse(manifest)), makeNoPos()), + makeBind(toATerm("stateIdentifiers"), + makeList(ATreverse(stateIdentifiers)), makeNoPos()), + makeBind(toATerm("runtimeStateArgs"), + makeList(ATreverse(runtimeStateArgs)), makeNoPos()), + makeBind(toATerm("manifest"), + makeStr(manifestFile, singleton(manifestFile)), makeNoPos()), + makeBind(toATerm("nixBinDir"), + makeStr(nixBinDir), makeNoPos()) ) + , makeBind(toATerm("nixStore"), makeStr(nixStore), makeNoPos()) - ))); + ) + + )); /* Instantiate it. */ debug(format("evaluating builder expression `%1%'") % topLevel); @@ -391,7 +403,7 @@ static void queryInstSources(EvalState & state, if (isDerivation(*i)) { elem.setDrvPath(*i); - elem.setOutPath(findOutput(derivationFromPath(*i), "out")); + elem.setOutPath(findOutput(derivationFromPathTxn(noTxn, *i), "out")); if (name.size() >= drvExtension.size() && string(name, name.size() - drvExtension.size()) == drvExtension) @@ -484,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 = derivationFromPath(i->queryDrvPath(globals.state)); + Derivation drv = derivationFromPathTxn(noTxn, i->queryDrvPath(globals.state)); if(store->isStateDrv(drv)) { DerivationStateOutputs stateOutputs = drv.stateOutputs; @@ -515,6 +527,7 @@ static void installDerivations(Globals & globals, { DrvName drvName(i->name); + //We may need to share state if (!globals.preserveInstalled && newNames.find(drvName.name) != newNames.end()){ //******** We're gonna check if the component and state indentifiers are the same, @@ -530,7 +543,7 @@ static void installDerivations(Globals & globals, for (DrvInfos::iterator j = newElems.begin(); j != newElems.end(); ++j) { DrvName newDrvName(j->name); if(newDrvName.name == drvName.name){ - Derivation newDrv = derivationFromPath(j->queryDrvPath(globals.state)); + Derivation newDrv = derivationFromPathTxn(noTxn, j->queryDrvPath(globals.state)); DerivationStateOutputs newStateOutputs = newDrv.stateOutputs; newStateIdentifier = newStateOutputs.find("state")->second.stateIdentifier; newStatePath = newDrv.stateOutputs.find("state")->second.statepath; @@ -540,6 +553,8 @@ static void installDerivations(Globals & globals, } //printMsg(lvlError, format("old '%1%' new '%2%'") % oldStateIdentifier % newStateIdentifier); + //if it doesnt need to share state with some other component + //&& the identifiers are equal if( newSharedState == "" && (oldStateIdentifier == newStateIdentifier @@ -553,7 +568,7 @@ static void installDerivations(Globals & globals, throw Error(format("Internal Error: There is not exactly one deriver with state_identifier '%1%' for path '%2%'") % newStateIdentifier % i->queryOutPath(globals.state)); Path oldDrvPath = *(derivers.begin()); - Derivation oldDrv = derivationFromPath(oldDrvPath); + Derivation oldDrv = derivationFromPathTxn(noTxn, oldDrvPath); oldStatePath = oldDrv.stateOutputs.find("state")->second.statepath; //SharePaths diff --git a/src/nix-state/nix-state.cc b/src/nix-state/nix-state.cc index 6a8fba675..8996eba96 100644 --- a/src/nix-state/nix-state.cc +++ b/src/nix-state/nix-state.cc @@ -83,7 +83,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 = derivationFromPath(derivationPath); + Derivation drv = derivationFromPathTxn(noTxn, derivationPath); if(isStateComponent){ DerivationStateOutputs stateOutputs = drv.stateOutputs; @@ -275,7 +275,7 @@ static void revertToRevision(Strings opFlags, Strings opArgs) int timestamp = getTimestamps[statePath]; //get its derivation-state-items - Derivation statePath_drv = derivationFromPath(queryStatePathDrvTxn(noTxn, statePath)); + Derivation statePath_drv = derivationFromPathTxn(noTxn, queryStatePathDrvTxn(noTxn, statePath)); DerivationStateOutputDirs stateOutputDirs = statePath_drv.stateOutputDirs; //TODO Sort snapshots??? eg first restore root, then the subdirs?? diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 35e79bffd..f7faa5c1d 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(derivationFromPath(path), "out"); + Path outPath = findOutput(derivationFromPathTxn(noTxn, path), "out"); if (gcRoot == "") printGCWarning(); @@ -184,7 +184,7 @@ static Path maybeUseOutput(const Path & storePath, bool useOutput, bool forceRea if (forceRealise) realisePath(storePath); if (useOutput && isDerivation(storePath)) { - Derivation drv = derivationFromPath(storePath); + Derivation drv = derivationFromPathTxn(noTxn, storePath); return findOutput(drv, "out"); } else return storePath; @@ -290,7 +290,7 @@ static void opQuery(Strings opFlags, Strings opArgs) { *i = fixPath(*i); if (forceRealise) realisePath(*i); - Derivation drv = derivationFromPath(*i); + Derivation drv = derivationFromPathTxn(noTxn, *i); cout << format("%1%\n") % findOutput(drv, "out"); } break; @@ -342,7 +342,7 @@ static void opQuery(Strings opFlags, Strings opArgs) i != opArgs.end(); ++i) { Path path = useDeriver(fixPath(*i)); - Derivation drv = derivationFromPath(path); + Derivation drv = derivationFromPathTxn(noTxn, path); StringPairs::iterator j = drv.env.find(bindingName); if (j == drv.env.end()) throw Error(format("derivation `%1%' has no environment binding named `%2%'")