From b32691da2b274720a3a67bba051aa88765cfabe0 Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Thu, 28 Jun 2007 18:59:07 +0000 Subject: [PATCH] registerValidPath can now also take state paths as arguments, nix-store still cannot --- src/libstore/build.cc | 100 ++++++++++++++++++++---------------- src/libstore/local-store.cc | 91 +++++++++++++++++++------------- src/libstore/local-store.hh | 5 +- src/libstore/store-api.cc | 20 +++++++- src/libstore/store-api.hh | 5 ++ src/nix-state/nix-state.cc | 13 +++-- src/nix-store/nix-store.cc | 2 +- 7 files changed, 149 insertions(+), 87 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 9d724cf9b..6587e144f 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1618,9 +1618,10 @@ PathSet parseReferenceSpecifiers(const Derivation & drv, string attr) void DerivationGoal::computeClosure() { - map allReferences; - map allStateReferences; - map statePaths; + map allReferences; //all component references in componentpath (one drv can have multiple output paths) + map allStateReferences; //all state references in componentpath + PathSet state_references; //all component references in statepath (one drv can have only one state path) + PathSet state_stateReferences; //all state references in statepath map contentHashes; //TODO MOVE THIS TO A PLACE THAT ALSO GETS CALLED WHEN WE DONT NEED TO BUILD ANYTHING @@ -1741,7 +1742,6 @@ void DerivationGoal::computeClosure() //printMsg(lvlError, format("SetValidPath: %1%") % i->second.path); registerValidPath(txn, i->second.path, - "", //dummy statePath contentHashes[i->second.path], allReferences[i->second.path], PathSet(), //dummy stateReferences @@ -1759,67 +1759,81 @@ void DerivationGoal::computeClosure() * [scan for and state references and component references in the state path] //3,4 */ - //TODO we scan for each output-path, be then we do multiple scans on the state path if there are more ouputs paths then 1..... - - //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // WE NOW ONLY REGISTER COMPONETS PATHS WITH registerValidPath BUT WE SHOULD ALSO REGISTER STATE PAHTS AS VALID AND SET THEIR REFERENCES !!!!!!!!!!!!!!!!!!!!!!! - + PathSet allStatePaths; + for (PathSet::const_iterator i = allPaths.begin(); i != allPaths.end(); i++){ + Path componentPath = *i; + + if(isStateComponentTxn(txn, componentPath)){ + //printMsg(lvlError, format("Scanning for state path: %1%") % componentPath); + + //TODO A HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + //We should only get the state paths of the derivers in the build closure from drv. + //The we can dismiss the call to queryDeriversStatePath(...), and we only have to do registerValidPath once + + PathSet stateRefs = queryDeriversStatePath(txn, componentPath ,"*",getCallingUserName()); + allStatePaths = mergePathSets(stateRefs, allStatePaths); + } + } + + //Scan all output paths ... comment TODO for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i) { Path path = i->second.path; - - /* For this state-output path, find the references to other paths contained in it. - * Get the state paths (instead of out paths) from all components, and then call - * scanForReferences(). - */ - PathSet allStatePaths; - for (PathSet::const_iterator i = allPaths.begin(); i != allPaths.end(); i++){ - Path componentPath = *i; - if(isStateComponentTxn(txn, componentPath)){ - //printMsg(lvlError, format("Scanning for state path: %1%") % componentPath); - PathSet stateRefs = queryDeriversStatePath(txn, componentPath ,"*",getCallingUserName()); - allStatePaths = mergePathSets(stateRefs, allStatePaths); - } - } - //We scan for state references in the component path - PathSet all_state_references = scanForReferences(path, allStatePaths); + PathSet output_state_references = scanForReferences(path, allStatePaths); - //If state is enabled: Seaches for state and component references in the state path - if(isStateDrvTxn(txn, drv)){ - Path statePath = drv.stateOutputs.find("state")->second.statepath; - printMsg(lvlTalkative, format("scanning for component and state references inside `%1%'") % statePath); - - PathSet state_references = scanForReferences(statePath, allPaths); - PathSet state_stateReferences = scanForReferences(statePath, allStatePaths); - all_state_references = mergePathSets(all_state_references, mergePathSets(state_references, state_stateReferences)); - - statePaths[path] = statePath; - } - else - statePaths[path] = ""; - //debugging for (PathSet::const_iterator i = allStatePaths.begin(); i != allStatePaths.end(); i++) debug(format("all possible StatePaths: %1%") % (*i)); - for (PathSet::const_iterator i = all_state_references.begin(); i != all_state_references.end(); i++) + for (PathSet::const_iterator i = output_state_references.begin(); i != output_state_references.end(); i++) debug(format("state References scanned: %1%") % (*i)); - allStateReferences[path] = all_state_references; + allStateReferences[path] = output_state_references; } + //Scan the state Path + /* For this state-output path, find the references to other paths contained in it. + * Get the state paths (instead of out paths) from all components, and then call + * scanForReferences(). + */ + //If state is enabled: Seaches for state and component references in the state path + if(isStateDrvTxn(txn, drv)){ + Path statePath = drv.stateOutputs.find("state")->second.statepath; + printMsg(lvlTalkative, format("scanning for component and state references inside `%1%'") % statePath); + + state_references = scanForReferences(statePath, allPaths); + state_stateReferences = scanForReferences(statePath, allStatePaths); + } + + //Register all outputs now valid for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i) { registerValidPath(txn, i->second.path, //component path - statePaths[i->second.path], //state path contentHashes[i->second.path], allReferences[i->second.path], //set of component-references allStateReferences[i->second.path], //set of state-references drvPath); } + //Register the state path valid + if(isStateDrvTxn(txn, drv)) + { + Path statePath = drv.stateOutputs.find("state")->second.statepath; + + registerValidPath(txn, + statePath, + Hash(), //emtpy hash + state_references, + state_stateReferences, + drvPath); + + //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // WE NOW ONLY REGISTER COMPONETS PATHS WITH registerValidPath BUT WE SHOULD ALSO REGISTER STATE PAHTS AS VALID AND SET THEIR REFERENCES !!!!!!!!!!!!!!!!!!!!!!! + } + txn.commit(); /* It is now safe to delete the lock files, since all future @@ -2220,7 +2234,7 @@ void SubstitutionGoal::finished() Transaction txn; createStoreTransaction(txn); - registerValidPath(txn, storePath, "", contentHash, //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! replace "" with a substitued state path !!!!!!!! + registerValidPath(txn, storePath, contentHash, //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! how about substituing a state path ????? references, stateReferences, sub.deriver); txn.commit(); diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index eb5927d73..f985b76d4 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -381,7 +381,7 @@ static PathSet getReferrers(const Transaction & txn, const Path & storePath) return referrers; } -static PathSet getStateReferrers(const Transaction & txn, const Path & storePath) //TODO this is just a copy of getReferrers, maybe make the function more generic? +static PathSet getStateReferrers(const Transaction & txn, const Path & storePath) //TODO this is just a copy of getReferrers with a change to dbStateReferrers, maybe make the function more generic? { PathSet referrers; Strings keys; @@ -391,50 +391,52 @@ static PathSet getStateReferrers(const Transaction & txn, const Path & storePath return referrers; } -void setReferences(const Transaction & txn, const Path & storePath, +void setReferences(const Transaction & txn, const Path & store_or_statePath, const PathSet & references, const PathSet & stateReferences) { /* For unrealisable paths, we can only clear the references. */ - if (references.size() > 0 && !isRealisablePath(txn, storePath)) - throw Error( - format("cannot set references for path `%1%' which is invalid and has no substitutes") - % storePath); + if (references.size() > 0 && !isRealisableComponentOrStatePath(txn, 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("REGISTER: %1%") % store_or_statePath); Paths oldReferences; - nixDB.queryStrings(txn, dbReferences, storePath, oldReferences); + nixDB.queryStrings(txn, dbReferences, store_or_statePath, oldReferences); PathSet oldReferences2(oldReferences.begin(), oldReferences.end()); Paths oldStateReferences; - nixDB.queryStrings(txn, dbStateReferences, storePath, oldStateReferences); + nixDB.queryStrings(txn, dbStateReferences, store_or_statePath, oldStateReferences); PathSet oldStateReferences2(oldStateReferences.begin(), oldStateReferences.end()); if (oldReferences2 == references && oldStateReferences2 == stateReferences) return; - nixDB.setStrings(txn, dbReferences, storePath, + printMsg(lvlError, format("REGISTER2: %1%") % store_or_statePath); + + nixDB.setStrings(txn, dbReferences, store_or_statePath, Paths(references.begin(), references.end())); - nixDB.setStrings(txn, dbStateReferences, storePath, + nixDB.setStrings(txn, dbStateReferences, store_or_statePath, Paths(stateReferences.begin(), stateReferences.end())); /* Update the referrers mappings of all new referenced paths. */ for (PathSet::const_iterator i = references.begin(); i != references.end(); ++i) if (oldReferences2.find(*i) == oldReferences2.end()) - nixDB.setString(txn, dbReferrers, addPrefix(*i, storePath), ""); + nixDB.setString(txn, dbReferrers, addPrefix(*i, store_or_statePath), ""); /* Update the state referrers mappings of all new referenced paths. */ for (PathSet::const_iterator i = stateReferences.begin(); i != stateReferences.end(); ++i) if (oldStateReferences2.find(*i) == oldStateReferences2.end()) - nixDB.setString(txn, dbStateReferrers, addPrefix(*i, storePath), ""); + nixDB.setString(txn, dbStateReferrers, addPrefix(*i, store_or_statePath), ""); /* Remove referrer mappings from paths that are no longer references. */ for (Paths::iterator i = oldReferences.begin(); i != oldReferences.end(); ++i) if (references.find(*i) == references.end()) - nixDB.delPair(txn, dbReferrers, addPrefix(*i, storePath)); + nixDB.delPair(txn, dbReferrers, addPrefix(*i, store_or_statePath)); /* Remove referrer mappings from paths that are no longer state references. */ for (Paths::iterator i = oldStateReferences.begin(); i != oldStateReferences.end(); ++i) if (stateReferences.find(*i) == stateReferences.end()) - nixDB.delPair(txn, dbStateReferrers, addPrefix(*i, storePath)); + nixDB.delPair(txn, dbStateReferrers, addPrefix(*i, store_or_statePath)); } @@ -643,7 +645,7 @@ PathSet queryDerivers(const Transaction & txn, const Path & storePath, const str return filtereddata; } -//TODO Wrapper around converting the drvPath to the statePath +//Wrapper around converting the drvPath to the statePath PathSet queryDeriversStatePath(const Transaction & txn, const Path & storePath, const string & identifier, const string & user) { PathSet drvs = queryDerivers(txn, storePath, identifier, user); @@ -823,13 +825,12 @@ Path LocalStore::queryStatePathDrv(const Path & statePath) void registerValidPath(const Transaction & txn, - const Path & path, const Path & statePath, const Hash & hash, + const Path & component_or_state_path, const Hash & hash, const PathSet & references, const PathSet & stateReferences, const Path & deriver) { ValidPathInfo info; - info.path = path; - info.statePath = statePath; + info.path = component_or_state_path; info.hash = hash; info.references = references; info.stateReferences = stateReferences; @@ -848,25 +849,37 @@ void registerValidPaths(const Transaction & txn, const ValidPathInfos & infos) for (ValidPathInfos::const_iterator i = infos.begin(); i != infos.end(); ++i) { - assertStorePath(i->path); + //Check the type of path: component or state + bool isStorePath_b; + if(isStorePath(i->path)){ + assertStorePath(i->path); + isStorePath_b = true; + } + else{ + assertStatePath(i->path); + isStorePath_b = false; + } debug(format("registering path `%1%'") % i->path); - setHash(txn, i->path, i->hash); //set path valid - - if (i->statePath != "") - setStateValid(txn, i->statePath, i->deriver); //set state path valid + + if(isStorePath_b) + setHash(txn, i->path, i->hash); //set compont path valid + else + setStateValid(txn, i->path, i->deriver); //or set state path valid setReferences(txn, i->path, i->references, i->stateReferences); /* Check that all referenced paths are also valid (or about to) become valid). */ - //TODO Maybe also check this for stateReferences???? - for (PathSet::iterator j = i->references.begin(); - j != i->references.end(); ++j) + for (PathSet::iterator j = i->references.begin(); j != i->references.end(); ++j) if (!isValidPathTxn(txn, *j) && newPaths.find(*j) == newPaths.end()) - throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid") - % i->path % *j); + throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid") % i->path % *j); + //TODO Maybe also check this for stateReferences???? with isValidStatePathTxn .... + //for (.... - setDeriver(txn, i->path, i->deriver); + 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 .... } } @@ -924,7 +937,7 @@ Path LocalStore::addToStore(const Path & _srcPath, bool fixed, canonicalisePathMetaData(dstPath); Transaction txn(nixDB); - registerValidPath(txn, dstPath, "", h, PathSet(), PathSet(), ""); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!! CHECK if the first "" (statepath) is needed here + registerValidPath(txn, dstPath, h, PathSet(), PathSet(), ""); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!! CHECK (probabyly ok?) txn.commit(); } @@ -958,8 +971,8 @@ Path LocalStore::addTextToStore(const string & suffix, const string & s, canonicalisePathMetaData(dstPath); Transaction txn(nixDB); - registerValidPath(txn, dstPath, "", hashPath(htSHA256, dstPath), references, PathSet(), ""); //There are no stateReferences in drvs..... so we dont need to register them (I think) - //A drvs has also no statepath, so that is ok... + registerValidPath(txn, dstPath, hashPath(htSHA256, dstPath), references, PathSet(), ""); //There are no stateReferences in drvs..... so we dont need to register them (I think) + //A drvs has also no statepath, so that is ok... txn.commit(); } @@ -1164,7 +1177,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source) /* !!! if we were clever, we could prevent the hashPath() here. */ if (!isValidPath(deriver)) deriver = ""; - registerValidPath(txn, dstPath, "", //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!! replace "" for a state path ?????? + registerValidPath(txn, dstPath, //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!! replace how about state paths ?????? hashPath(htSHA256, dstPath), references, stateReferences, deriver); txn.commit(); } @@ -1589,8 +1602,16 @@ void scanForAllReferences(const Transaction & txn, const Path & statePath) nixDB.enumTable(txn, dbReferences, referencesKeys); nixDB.enumTable(txn, dbStateReferences, stateReferencesKeys); - for (Paths::iterator i = stateReferencesKeys.begin(); i != stateReferencesKeys.end(); ++i) - printMsg(lvlError, format("STATE: %1%") % *i); + for (Paths::iterator i = referencesKeys.begin(); i != referencesKeys.end(); ++i){ + string s = *i; + if (s.substr(0,10) == "/nix/state") + printMsg(lvlError, format("referencesKeys: %1%") % s); + } + for (Paths::iterator i = stateReferencesKeys.begin(); i != stateReferencesKeys.end(); ++i){ + string s = *i; + if (s.substr(0,10) == "/nix/state") + printMsg(lvlError, format("stateReferencesKeys: %1%") % s); + } //Remove derivation paths ..... for (Paths::iterator i = referencesKeys.begin(); i != referencesKeys.end(); ++i){ diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index ec42470f0..d307339a0 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -127,14 +127,13 @@ void clearSubstitutes(); of the file system contents of the path. The hash must be a SHA-256 hash. */ void registerValidPath(const Transaction & txn, - const Path & path, const Path & statepath, const Hash & hash, + const Path & component_or_state_path, const Hash & hash, const PathSet & references, const PathSet & stateReferences, const Path & deriver); struct ValidPathInfo { Path path; - Path statePath; Path deriver; Hash hash; PathSet references; @@ -161,7 +160,7 @@ bool isValidPathTxn(const Transaction & txn, const Path & path); /* Sets the set of outgoing FS (also state) references for a store path. Use with care! */ -void setReferences(const Transaction & txn, const Path & path, +void setReferences(const Transaction & txn, const Path & store_or_statePath, const PathSet & references, const PathSet & stateReferences); /* Sets the deriver of a store path. Use with care! */ diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index a9ba851d1..fa2b1201b 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -20,6 +20,13 @@ bool isInStore(const Path & path) && path[nixStore.size()] == '/'; } +bool isInStateStore(const Path & path) +{ + return path[0] == '/' + && string(path, 0, nixStoreState.size()) == nixStoreState + && path.size() >= nixStoreState.size() + 2 + && path[nixStoreState.size()] == '/'; +} bool isStorePath(const Path & path) { @@ -27,11 +34,22 @@ bool isStorePath(const Path & path) && path.find('/', nixStore.size() + 1) == Path::npos; } +bool isStatePath(const Path & path) +{ + return isInStateStore(path) + && path.find('/', nixStoreState.size() + 1) == Path::npos; +} void assertStorePath(const Path & path) { if (!isStorePath(path)) - throw Error(format("path `%1%' is not in the Nix store (1)") % path); //TODO bug: this prints an empty path ... + throw Error(format("component path `%1%' is not in the Nix store (1)") % path); //TODO bug: this prints an empty path ... +} + +void assertStatePath(const Path & path) +{ + if (!isStatePath(path)) + throw Error(format("state path `%1%' is not in the Nix state-store (1)") % path); //TODO bug: this prints an empty path ... } diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index f24d1ad6e..4c4ef5c9a 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -232,10 +232,15 @@ public: /* Throw an exception if `path' is not directly in the Nix store. */ void assertStorePath(const Path & path); +void assertStatePath(const Path & path); bool isInStore(const Path & path); bool isStorePath(const Path & path); +bool isInStateStore(const Path & path); +bool isStatePath(const Path & path); + + void checkStoreName(const string & name); /* Chop off the parts after the top-level store name, e.g., diff --git a/src/nix-state/nix-state.cc b/src/nix-state/nix-state.cc index 3f3de6b89..d01c60629 100644 --- a/src/nix-state/nix-state.cc +++ b/src/nix-state/nix-state.cc @@ -10,6 +10,7 @@ #include "help.txt.hh" #include "local-store.hh" #include "derivations.hh" +#include "store-api.hh" //TODO REMOVE using namespace nix; using std::cin; @@ -375,12 +376,16 @@ void run(Strings args) printMsg(lvlError, format("Result: %1%") % p); return; - - */ - string path = "afddsafsdafsdaf.drv"; printMsg(lvlError, format("Result: %1%") % path.substr(path.length() - 4,path.length())); - + + printMsg(lvlError, format("AA: %1%") % isStorePath("/nix/store/hbxqq4d67j2y21xzp7yp01qjfkcjjbc7-hellohardcodedstateworld-1.0")); + printMsg(lvlError, format("AA: %1%") % isStorePath("/nix/state/0qhlpz1ji4gvg3j6nk5vkcddmi3m5x1r-hellohardcodedstateworld-1.0-test2")); + printMsg(lvlError, format("AA: %1%") % isStatePath("/nix/store/hbxqq4d67j2y21xzp7yp01qjfkcjjbc7-hellohardcodedstateworld-1.0")); + printMsg(lvlError, format("AA: %1%") % isStatePath("/nix/state/0qhlpz1ji4gvg3j6nk5vkcddmi3m5x1r-hellohardcodedstateworld-1.0-test2")); + + */ + store = openStore(); store->scanForAllReferences("/nix/state/0qhlpz1ji4gvg3j6nk5vkcddmi3m5x1r-hellohardcodedstateworld-1.0-test2"); return; diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index c6db9e3a5..b3d6d3c48 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -286,7 +286,7 @@ static void opQuery(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { - Path path = maybeUseOutput(fixPath(*i), useOutput, forceRealise); + Path path = maybeUseOutput(fixPath(*i), useOutput, forceRealise); //TODO This hangs on state paths ... if (query == qRequisites) store->storePathRequisites(path, includeOutputs, paths, false); else if (query == qRequisitesState) store->storePathStateRequisitesOnly(path, includeOutputs, paths); else if (query == qRequisitesFull) store->storePathRequisites(path, includeOutputs, paths, true);