From 4089bd5f197bd878ad8b6c96618ae4985a70c2f6 Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Mon, 13 Aug 2007 15:35:12 +0000 Subject: [PATCH] State is now maintained (their paths are automatically shared), unless sharedState is set in the nix-expr, when a new version with the same drv-name of the component is installed --- corepkgs/buildenv/builder.pl.in | 14 ++-- src/libexpr/get-drvs.cc | 4 +- src/libstore/build.cc | 14 +--- src/libstore/local-store.cc | 6 +- src/libstore/local-store.hh | 2 +- src/libutil/util.cc | 12 ++- src/libutil/util.hh | 2 + src/nix-env/nix-env.cc | 129 +++++++++++++++++++------------- src/nix-env/profiles.cc | 2 - 9 files changed, 110 insertions(+), 75 deletions(-) diff --git a/corepkgs/buildenv/builder.pl.in b/corepkgs/buildenv/builder.pl.in index 22ac48f50..b5f4f0c7b 100755 --- a/corepkgs/buildenv/builder.pl.in +++ b/corepkgs/buildenv/builder.pl.in @@ -20,6 +20,8 @@ my $srcDirSlashes = 3; sub createLinks { my $srcDir = shift; + #Lookup each $stateIdentifiers in $path_identifier + #we strip $srcDir to its rootdir e.g. /nix/store/......./ my @srcDirParts = split /\// , $srcDir; my $srcDirRoot = ""; my $srcDirCounter=1; @@ -28,8 +30,8 @@ sub createLinks { $srcDirCounter++; } #print "srcDirRoot $srcDirRoot \n"; - my $pkgStateIdentifier = $path_identifier{$srcDirRoot}; + my $dstDir = shift; my $ignoreCollisions = shift; @@ -138,7 +140,6 @@ my %postponed; sub addPkg; sub addPkg { my $pkgDir = shift; - my $pkgStateIdentifier = shift; my $ignoreCollisions = shift; return if (defined $done{$pkgDir}); @@ -167,11 +168,12 @@ my $si_counter = 0; foreach my $pkgDir (@storePaths) { #Commented the sort out - print "SP: $pkgDir \n"; + #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"; + #print "SI: $path_identifier{$pkgDir} \n"; - addPkg($pkgDir, $stateIdentifiers[$si_counter], 0); + addPkg($pkgDir, 0); $si_counter++; } @@ -182,7 +184,7 @@ foreach my $pkgDir (@storePaths) { #Commented the sort out # priority in case of collisions. while (scalar(keys %postponed) > 0) { - my @pkgDirs = keys %postponed; # TODODODODODOD !!!!!!!!!!!!!!!!!!!!! + my @pkgDirs = keys %postponed; %postponed = (); foreach my $pkgDir (sort @pkgDirs) { addPkg($pkgDir, 1); diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index f4f4e8813..1010c0709 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -143,7 +143,9 @@ static bool getDerivation(EvalState & state, Expr e, drv.system = evalStringNoCtx(state, a); drv.attrs = attrs; - + + //printMsg(lvlError, format("TEST '%1%'") % evalStringNoCtx(state, a) ); + drv.attrPath = attrPath; drvs.push_back(drv); diff --git a/src/libstore/build.cc b/src/libstore/build.cc index a9dbac70a..1390588e7 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1821,16 +1821,10 @@ void DerivationGoal::computeClosure() if(sharedState != ""){ //Remove state path deletePathWrapped(statePath); - - //Symlink link to the share path - Strings p_args; - p_args.push_back("-sf"); - p_args.push_back(sharedState); - p_args.push_back(statePath); - runProgram_AndPrintOutput("ln", true, p_args, "ln"); //run + sharePath(sharedState, statePath); //Set in database - setSharedStateTxn(txn, statePath, sharedState); + setSharedStateTxn(txn, sharedState, statePath); } } @@ -2587,9 +2581,7 @@ void LocalStore::buildDerivations(const PathSet & drvPaths) Worker worker; Goals goals; for (PathSet::const_iterator i = drvPaths.begin(); i != drvPaths.end(); ++i){ - - printMsg(lvlError, format("BUILD: '%1%'") % *i); - + //printMsg(lvlError, format("BUILD: '%1%'") % *i); goals.insert(worker.makeDerivationGoal(*i)); } diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index e777d1b3b..fdfed2004 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1729,13 +1729,13 @@ bool querySolidStateReferencesTxn(const Transaction & txn, const Path & statePat return notempty; } -void setSharedStateTxn(const Transaction & txn, const Path & statePath, const Path & shared_with) +void setSharedStateTxn(const Transaction & txn, const Path & fromExisting, const Path & toNew) { //Remove earlier entries - nixDB.delPair(txn, dbSharedState, statePath); + nixDB.delPair(txn, dbSharedState, toNew); //Set new entry - nixDB.setString(txn, dbSharedState, statePath, shared_with); + nixDB.setString(txn, dbSharedState, toNew, fromExisting); } bool querySharedStateTxn(const Transaction & txn, const Path & statePath, Path & shared_with) diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index e8a3766d3..3447c6a1a 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -239,7 +239,7 @@ bool isValidStatePathTxn(const Transaction & txn, const Path & path); void setSolidStateReferencesTxn(const Transaction & txn, const Path & statePath, const PathSet & paths); bool querySolidStateReferencesTxn(const Transaction & txn, const Path & statePath, PathSet & paths); -void setSharedStateTxn(const Transaction & txn, const Path & statePath, const Path & shared_with); +void setSharedStateTxn(const Transaction & txn, const Path & fromExisting, const Path & toNew); PathSet toNonSharedPathSetTxn(const Transaction & txn, const PathSet & statePaths); Path toNonSharedPathTxn(const Transaction & txn, const Path & statePath); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index e9223bae0..174f739d0 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1262,6 +1262,16 @@ string padd(const string & s, char c , unsigned int size, bool front) ss = ss + c; } return ss; -} +} + +void sharePath(const Path & fromExisting, const Path & toNew) +{ + //Symlink link to the share path + Strings p_args; + p_args.push_back("-sf"); + p_args.push_back(fromExisting); + p_args.push_back(toNew); + runProgram_AndPrintOutput("ln", true, p_args, "ln"); //run +} } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 692437109..73f6c6f89 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -322,6 +322,8 @@ void ensureDirExists(const Path & path); string padd(const string & s, char c , unsigned int size, bool front = false); +void sharePath(const Path & fromExisting, const Path & toNew); + } #endif /* !__UTIL_H */ diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index bb5c59ce0..bcedffd12 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -15,6 +15,7 @@ #include "store-api.hh" #include "db.hh" #include "util.hh" +#include "local-store.hh" #include #include @@ -189,15 +190,10 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, strictEvalExpr(state, i->attrs->get(toATerm("meta"))), makeNoPos())); manifest = ATinsert(manifest, makeAttrs(as)); //All DrvInfo's are inserted here - - /*ATermList ass = ATmakeList1( - makeBind(toATerm("stateIdentifier"), makeStr(i->queryStateIdentifier(state)), makeNoPos()) - );*/ - + + //Insert the new stateIdentifier into the stateIdentifiers Atermlist stateIdentifiers = ATinsert(stateIdentifiers, makeStr(i->queryStateIdentifier(state))); - //printMsg(lvlError, format("TEST2 '%1%'") % makeAttrs(as)); - inputs = ATinsert(inputs, makeStr(i->queryOutPath(state))); /* This is only necessary when installing store paths, e.g., @@ -210,13 +206,7 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, references.insert(drvPath); } - //printMsg(lvlError, format("TEST '%1%'") % atPrint(canonicaliseExpr(makeList(ATreverse(manifest)))) ); - //printMsg(lvlError, format("TEST2 '%1%'") % makeList(ATreverse(manifest)) ); - //printMsg(lvlError, format("TEST2 '%1%'") % makeBind(toATerm("stateIdentifiers"), makeList(ATreverse(manifest)), makeNoPos()) ); - printMsg(lvlError, format("TEST '%1%'") % atPrint(canonicaliseExpr(makeList(ATreverse(stateIdentifiers)))) ); - - /* Extract ... */ - + //printMsg(lvlError, format("TEST '%1%'") % atPrint(canonicaliseExpr(makeList(ATreverse(stateIdentifiers)))) ); /* Also write a copy of the list of inputs to the store; we need it for future modifications of the environment. */ @@ -233,24 +223,15 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, makeStr(manifestFile, singleton(manifestFile)), makeNoPos()) ))); - //printMsg(lvlError, format("Write manifest '%1%'") % topLevel); - /* Instantiate it. */ debug(format("evaluating builder expression `%1%'") % topLevel); DrvInfo topLevelDrv; if (!getDerivation(state, topLevel, topLevelDrv)) abort(); - printMsg(lvlError, format("TEST5 '%1%'") % topLevelDrv.queryStateIdentifier(state)); - printMsg(lvlError, format("BUILD ENV DRV: '%1%'") % topLevelDrv.queryDrvPath(state) ); - /* Realise the resulting store expression. */ debug(format("building user environment")); - store->buildDerivations(singleton(topLevelDrv.queryDrvPath(state))); //HERE IS THE DRV !!!!!!!!!!! - - //switch ..... - - printMsg(lvlError, format("TEST6")); + store->buildDerivations(singleton(topLevelDrv.queryDrvPath(state))); /* Switch the current user environment to the output path. */ debug(format("switching to new user environment")); @@ -342,10 +323,6 @@ static void queryInstSources(EvalState & state, { InstallSourceType type = instSource.type; - for (Strings::const_iterator i = args.begin(); i != args.end(); ++i) - printMsg(lvlError, format("queryInstSources arg '%1%'") % *i); - printMsg(lvlError, format("queryInstSources TYPE '%1%'") % (type == srcUnknown)); - if (type == srcUnknown && args.size() > 0 && args.front()[0] == '/') type = srcStorePaths; @@ -399,12 +376,8 @@ static void queryInstSources(EvalState & state, for (Strings::const_iterator i = args.begin(); i != args.end(); ++i) { - printMsg(lvlError, format("AAAAA333 %1%'") % *i); - assertStorePath(*i); - printMsg(lvlError, format("AAAAA444 %1%'") % *i); - DrvInfo elem; elem.attrs = boost::shared_ptr(new ATermMap(0)); /* ugh... */ string name = baseNameOf(*i); @@ -421,12 +394,7 @@ static void queryInstSources(EvalState & state, name = string(name, 0, name.size() - drvExtension.size()); } else - { elem.setOutPath(*i); - - //if(drv.stateOutputs.size() != 0) - // elem.setStateIdentifier(drv.stateOutputs.find("state")->second.stateIdentifier); - } elem.name = name; @@ -510,14 +478,14 @@ static void installDerivations(Globals & globals, path is not the one we want (e.g., `java-front' versus `java-front-0.9pre15899'). */ - //printMsg(lvlError, format("New component to install DRV: '%1%'") % i->queryDrvPath(globals.state)); - - //Set the state indentifier - if( store->isStateComponent(i->queryOutPath(globals.state)) ) + //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)); + if(store->isStateDrv(drv)) { - Derivation drv = derivationFromPath(i->queryDrvPath(globals.state)); DerivationStateOutputs stateOutputs = drv.stateOutputs; string stateIdentifier = stateOutputs.find("state")->second.stateIdentifier; + printMsg(lvlError, format("Add '%2%' with '%1%'") % stateIdentifier % i->queryOutPath(globals.state) ); if(stateIdentifier == "") i->setStateIdentifier("__EMTPY__"); else @@ -535,19 +503,67 @@ static void installDerivations(Globals & globals, lockProfile(lock, profile); DrvInfos installedElems = queryInstalled(globals.state, profile); + + StringPairs toBeShared; //Mapping from old --> new statePath + DrvInfos allElems(newElems); for (DrvInfos::iterator i = installedElems.begin(); i != installedElems.end(); ++i) { DrvName drvName(i->name); - //TODO !!!!!!!!!!!!!!!!!!!!!!!! SHARE (OR COPY) STATE HERE IF NEEDED - //if( newNames.find(drvName.name) != newNames.end() && identifier == identifier ) - //{ - - //} - - if (!globals.preserveInstalled && newNames.find(drvName.name) != newNames.end()) - printMsg(lvlInfo, format("replacing old `%1%'") % i->name); + if (!globals.preserveInstalled && newNames.find(drvName.name) != newNames.end()){ + + //******** We're gonna check if the component and state indentifiers are the same, + // since we may need to share state in that case. + + string oldStateIdentifier = i->queryStateIdentifier(globals.state); //get the old stateIdentifier + if(oldStateIdentifier != "__NOSTATE__") + { + //get the new stateIdentifier + string newStateIdentifier; + string newStatePath; + string newSharedState; + 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)); + DerivationStateOutputs newStateOutputs = newDrv.stateOutputs; + newStateIdentifier = newStateOutputs.find("state")->second.stateIdentifier; + newStatePath = newDrv.stateOutputs.find("state")->second.statepath; + newSharedState = newDrv.stateOutputs.find("state")->second.sharedState; + break; + } + } + //printMsg(lvlError, format("old '%1%' new '%2%'") % oldStateIdentifier % newStateIdentifier); + + if( newSharedState == "" + && + (oldStateIdentifier == newStateIdentifier + || (oldStateIdentifier == "__EMTPY__" && newStateIdentifier == "")) + ){ + + string oldStatePath; + //query old state path + PathSet derivers = queryDerivers(noTxn, i->queryOutPath(globals.state), newStateIdentifier, getCallingUserName()); + if(derivers.size() != 1) + 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); + oldStatePath = oldDrv.stateOutputs.find("state")->second.statepath; + + //SharePaths + printMsg(lvlError, format("Sharing state from old to new component '%1%' --> '%2%'") % newStatePath % oldStatePath); + toBeShared[oldStatePath] = newStatePath; + } + else{ //If not equal, then we do not replace, so we push back (just like the else branch) + printMsg(lvlError, format("Installing new state-component component '%1%' with identifier '%2%'") % drvName.name % oldStateIdentifier); + allElems.push_back(*i); + } + } + else + printMsg(lvlInfo, format("replacing old `%1%'") % i->name); + } else allElems.push_back(*i); } @@ -562,6 +578,18 @@ static void installDerivations(Globals & globals, createUserEnv(globals.state, allElems, profile, globals.keepDerivations); + + //After all components have been built succesfully, share their state paths with the old ones + for (StringPairs::iterator i = toBeShared.begin(); i != toBeShared.end(); ++i){ + + deletePathWrapped(i->second); //Remove contents of current new state path + sharePath(i->first, i->second); //Share new statepath to the old statepath + + //Set in database + setSharedStateTxn(noTxn, i->first, i->second); + } + + } @@ -578,6 +606,7 @@ static void opInstall(Globals & globals, typedef enum { utLt, utLeq, utEq, utAlways } UpgradeType; +//TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! static void upgradeDerivations(Globals & globals, const Strings & args, UpgradeType upgradeType) { diff --git a/src/nix-env/profiles.cc b/src/nix-env/profiles.cc index df5ef4419..66b0edab2 100644 --- a/src/nix-env/profiles.cc +++ b/src/nix-env/profiles.cc @@ -93,8 +93,6 @@ Path createGeneration(Path profile, Path outPath) makeName(profile, num + 1, generation); addPermRoot(outPath, generation, false, true); - printMsg(lvlError, format("TEST3 '%1%' '%2%' --> '%3%'") % profile % outPath % generation); - return generation; }