From 7e0dcc5dcb83c75e8366f48f247a6eae320dc508 Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Tue, 23 Oct 2007 14:02:25 +0000 Subject: [PATCH] Runtime state arguments added to nix-state. --- TODO | 3 +++ src/libexpr/primops.cc | 4 +-- src/libstore/build.cc | 5 +++- src/libstore/local-store.cc | 48 ++++++++++++++++++++------------- src/libstore/local-store.hh | 9 +++++-- src/libstore/remote-store.cc | 32 +++++++++++++++++++--- src/libstore/remote-store.hh | 4 +++ src/libstore/store-api.hh | 6 +++++ src/libstore/store-state.cc | 31 +++++++++++++++------ src/libstore/store-state.hh | 4 +-- src/libstore/worker-protocol.hh | 2 ++ src/nix-env/nix-env.cc | 8 +----- src/nix-state/nix-state.cc | 16 ++++++++++- src/nix-store/nix-store.cc | 2 -- src/nix-worker/nix-worker.cc | 31 +++++++++++++++++++-- 15 files changed, 155 insertions(+), 50 deletions(-) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 000000000..213375063 --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +- runtimeStateArgs now must be set to someting (or it will see it as a hardcoded path) +- import and export of state paths +- diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 0e1bd72af..b8608bf79 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -366,7 +366,7 @@ static Hash hashDerivationModulo(EvalState & state, Derivation drv) } } - /* If we have a state derivation, we clear state paramters because they (sometimes) dont affect to outPath: + /* If we have a state derivation, we clear state paramters because they (sometimes) can affect the outPath: * If this drv has runtime paramters: The state indentifier and thus statepath may change, but the componentPath (outPath) can stay the same * If this drv doesnt have runtime paramters: The state indentifier and thus statepath may change, and thus the componentPath changes since it is build with another identifier * In both cases: Other runtime state parameters like stateDirs, synchronisation and shareState never change the out or statepath so always need to be out of the hash @@ -378,7 +378,7 @@ static Hash hashDerivationModulo(EvalState & state, Derivation drv) DerivationStateOutput drvso = drv.stateOutputs["state"]; - if(drvso.runtimeStateArgs != ""){ //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"] = ""; diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 192583088..7e142add3 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1949,7 +1949,10 @@ void DerivationGoal::computeClosure() } setStatePathsIntervalTxn(txn, statePath, intervals); //Set intervals to zero setVersionedStateEntriesTxn(txn, statePath, infos); //register subdirs/files and their types of versioning - setStateUserGroupTxn(txn, statePath, queryCallingUsername(), "nixbld", 700); //register the user and group + + //register state options that may change + DerivationStateOutput drvso = drv.stateOutputs["state"]; + setStateOptionsTxn(txn, statePath, queryCallingUsername(), "nixbld", 700, drvso.runtimeStateArgs); //Shared state Path sharedState = drv.stateOutputs.find("state")->second.sharedState; diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 807be2c46..8e016fb0b 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -156,9 +156,9 @@ static TableId dbVersionItems = 0; /* * StatePath :: string - * the string contains the user,group and chmod + * the string contains the user,group,chmod,runtimestateargs */ -static TableId dbStateRights = 0; +static TableId dbStateOptions = 0; static void upgradeStore07(); @@ -231,7 +231,7 @@ LocalStore::LocalStore(bool reserveSpace) dbSharedState = nixDB.openTable("sharedState"); dbSolidStateReferences = nixDB.openTable("references_solid_c_s"); /* The contents of this table is included in references_c_s */ dbVersionItems = nixDB.openTable("stateItems"); - dbStateRights = nixDB.openTable("stateRights"); + dbStateOptions = nixDB.openTable("stateOptions"); int curSchema = 0; Path schemaFN = nixDBPath + "/schema"; @@ -559,16 +559,16 @@ static PathSet getXReferrers(const Transaction & txn, const Path & store_or_stat map latest; for (Strings::const_iterator i = keys.begin(); i != keys.end(); ++i){ Path getStatePath; - unsigned int getRevision; - splitDBRevKey(*i, getStatePath, getRevision); + unsigned int getTimestamp; + splitDBRevKey(*i, getStatePath, getTimestamp); if(latest[getStatePath] == 0) //either it is unset - latest[getStatePath] = getRevision; - else if(latest[getStatePath] < getRevision){ - if(revision != 0 && getRevision <= timestamp) //or it is greater, but not greater then the timestamp //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!! WERE COMPARING A REVISION TO A TIMESTAMP ??? - latest[getStatePath] = getRevision; + latest[getStatePath] = getTimestamp; + else if(latest[getStatePath] < getTimestamp){ + if(revision != 0 && getTimestamp <= timestamp) //or it is greater, but not greater then the timestamp + latest[getStatePath] = getTimestamp; else //we need the latest so greater is good - latest[getStatePath] = getRevision; + latest[getStatePath] = getTimestamp; } } @@ -1204,7 +1204,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source) PathSet references = readStorePaths(hashAndReadSource); - //TODO TODO also ..??!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + //TODO TODO also ?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PathSet stateReferences; Path deriver = readString(hashAndReadSource); @@ -1294,8 +1294,8 @@ void deleteXFromStore(const Path & _path, unsigned long long & bytesFreed, const Transaction txn(nixDB); if (isValidPathTxn(txn, path) || isValidStatePathTxn(txn, path)) { - PathSet storeReferrers = getStoreReferrersTxn(txn, path, 0); //TODO GET REFERRERS OF ALL REVISIONS !!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!! - PathSet stateReferrers = getStateReferrersTxn(txn, path, 0); + PathSet storeReferrers = getStoreReferrersTxn(txn, path, 0); //TODO GET REFERRERS OF ALL REVISIONS WHEN path IS A STATEPATH + PathSet stateReferrers = getStateReferrersTxn(txn, path, 0); //TODO GET REFERRERS OF ALL REVISIONS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! for (PathSet::iterator i = storeReferrers.begin(); i != storeReferrers.end(); ++i) if (*i != path && isValidPathTxn(txn, *i)) @@ -1626,9 +1626,9 @@ void unShareStateTxn(const Transaction & txn, const Path & statePath, const bool nixDB.delPair(txn, dbSharedState, statePath); //Touch dir with correct rights - string user, group; + string user, group, runtimeArgs; int chmod; - getStateUserGroupTxn(txn, statePath, user, group, chmod); + getStateOptionsTxn(txn, statePath, user, group, chmod, runtimeArgs); ensureStateDir(statePath, user, group, int2String(chmod)); if(branch && restoreOld) @@ -1839,14 +1839,24 @@ bool getVersionedStateEntriesTxn(const Transaction & txn, const Path & statePath statePath, infos, revision, timestamp); } -void setStateUserGroupTxn(const Transaction & txn, const Path & statePath, const string & user, const string & group, int chmod) +void setStateOptionsTxn(const Transaction & txn, const Path & statePath, const string & user, const string & group, int chmod, const string & runtimeArgs) { - setStateUserGroup(nixDB, txn, dbStateRights, statePath, user, group, chmod); + setStateOptions(nixDB, txn, dbStateOptions, statePath, user, group, chmod, runtimeArgs); } -void getStateUserGroupTxn(const Transaction & txn, const Path & statePath, string & user, string & group, int & chmod) +void getStateOptionsTxn(const Transaction & txn, const Path & statePath, string & user, string & group, int & chmod, string & runtimeArgs) { - getStateUserGroup(nixDB, txn, dbStateRights, statePath, user, group, chmod); + getStateOptions(nixDB, txn, dbStateOptions, statePath, user, group, chmod, runtimeArgs); +} + +void LocalStore::setStateOptions(const Path & statePath, const string & user, const string & group, int chmod, const string & runtimeArgs) +{ + setStateOptionsTxn(noTxn, statePath, user, group, chmod, runtimeArgs); +} + +void LocalStore::getStateOptions(const Path & statePath, string & user, string & group, int & chmod, string & runtimeArgs) +{ + getStateOptionsTxn(noTxn, statePath, user, group, chmod, runtimeArgs); } typedef std::map > HashToPath; diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index ae06c92d4..8ebea8f10 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -142,6 +142,11 @@ public: Path lookupStatePath(const Path & storePath, const string & identifier, const string & user); + void setStateOptions(const Path & statePath, const string & user, const string & group, int chmod, const string & runtimeArgs); + + void getStateOptions(const Path & statePath, string & user, string & group, int & chmod, string & runtimeArgs); + + /* Optimise the disk space usage of the Nix store by hard-linking files with the same contents. */ void optimiseStore(bool dryRun, OptimiseStats & stats); @@ -281,8 +286,8 @@ void setStateComponentTxn(const Transaction & txn, const Path & storePath, const void setVersionedStateEntriesTxn(const Transaction & txn, const Path & statePath, const StateInfos & infos, const unsigned int revision = 0, const unsigned int timestamp = 0); bool getVersionedStateEntriesTxn(const Transaction & txn, const Path & statePath, StateInfos & infos, const unsigned int revision = 0, const unsigned int timestamp = 0); -void setStateUserGroupTxn(const Transaction & txn, const Path & statePath, const string & user, const string & group, int chmod); -void getStateUserGroupTxn(const Transaction & txn, const Path & statePath, string & user, string & group, int & chmod); +void setStateOptionsTxn(const Transaction & txn, const Path & statePath, const string & user, const string & group, int chmod, const string & runtimeArgs); +void getStateOptionsTxn(const Transaction & txn, const Path & statePath, string & user, string & group, int & chmod, string & runtimeArgs); } diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 00c734472..c0c56222e 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -516,8 +516,8 @@ bool RemoteStore::queryStateRevisions(const Path & statePath, RevisionClosure & processStderr(); RevisionClosure revisions2 = readRevisionClosure(from); RevisionClosureTS timestamps2 = readRevisionClosureTS(from); - revisions = revisions2; //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - timestamps = timestamps2; //TODO !!!!!!!!!!!!!!!!!!!! COPY BY VALUE I THINK + revisions = revisions2; + timestamps = timestamps2; //TODO Is this ok?? Maybe COPY BY VALUE ?? unsigned int reply = readInt(from); return reply != 0; } @@ -528,7 +528,7 @@ bool RemoteStore::queryAvailableStateRevisions(const Path & statePath, RevisionI writeString(statePath, to); processStderr(); RevisionInfos revisions2 = readRevisionInfos(from); - revisions = revisions2; //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + revisions = revisions2; unsigned int reply = readInt(from); return reply != 0; } @@ -565,7 +565,7 @@ PathSet RemoteStore::toNonSharedPathSet(const PathSet & statePaths) writeInt(wopToNonSharedPathSet, to); writeStringSet(statePaths, to); processStderr(); - return readStringSet(from); //TODO !!!!!!!!!!!!!!! create a readStatePaths just like readStorePaths + return readStatePaths(from); } void RemoteStore::revertToRevision(const Path & statePath, const unsigned int revision_arg, const bool recursive) @@ -608,6 +608,30 @@ Path RemoteStore::lookupStatePath(const Path & storePath, const string & identif return readStatePath(from); } +void RemoteStore::setStateOptions(const Path & statePath, const string & user, const string & group, int chmod, const string & runtimeArgs) +{ + writeInt(wopSetStateOptions, to); + writeString(statePath, to); + writeString(user, to); + writeString(group, to); + writeInt(chmod, to); + writeString(runtimeArgs, to); + processStderr(); + readInt(from); +} + +void RemoteStore::getStateOptions(const Path & statePath, string & user, string & group, int & chmod, string & runtimeArgs) +{ + writeInt(wopGetStateOptions, to); + writeString(statePath, to); + processStderr(); + user = readString(from); + group = readString(from); + chmod = readInt(from); + runtimeArgs = readString(from); + readInt(from); +} + void RemoteStore::processStderr(Sink * sink, Source * source) { diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 9b82cab39..9290d00bd 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -108,6 +108,10 @@ public: Path lookupStatePath(const Path & storePath, const string & identifier, const string & user); + void setStateOptions(const Path & statePath, const string & user, const string & group, int chmod, const string & runtimeArgs); + + void getStateOptions(const Path & statePath, string & user, string & group, int & chmod, string & runtimeArgs); + private: AutoCloseFD fdSocket; FdSink to; diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index b8ec9dd4b..0998a22ab 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -234,6 +234,12 @@ public: /* TODO */ virtual Path lookupStatePath(const Path & storePath, const string & identifier, const string & user) = 0; + /* TODO */ + virtual void setStateOptions(const Path & statePath, const string & user, const string & group, int chmod, const string & runtimeArgs) = 0; + + /* TODO */ + virtual void getStateOptions(const Path & statePath, string & user, string & group, int & chmod, string & runtimeArgs) = 0; + }; diff --git a/src/libstore/store-state.cc b/src/libstore/store-state.cc index c448b557d..6c52e443e 100644 --- a/src/libstore/store-state.cc +++ b/src/libstore/store-state.cc @@ -147,11 +147,20 @@ void revertToRevisionTxn(const Transaction & txn, const Path & statePath, const queryXReferencesTxn(txn, statePath, state_references, true, 0, timestamp); PathSet state_stateReferences; queryXReferencesTxn(txn, statePath, state_stateReferences, false, 0, timestamp); - //Now set these old references as the new references at the new (just created) Timestamp setStateComponentReferencesTxn(txn, statePath, Strings(state_references.begin(), state_references.end()), 0, newTimestamp); setStateStateReferencesTxn(txn, statePath, Strings(state_stateReferences.begin(), state_stateReferences.end()), 0, newTimestamp); + //Now set these old state-items as the new state-items at the new (just created) Timestamp + StateInfos infos; + getVersionedStateEntriesTxn(txn, statePath, infos, 0, timestamp); + setVersionedStateEntriesTxn(txn, statePath, infos, 0, newTimestamp); + + //Now set these old staterights as the new staterights at the new (just created) Timestamp + //void getStateOptionsTxn(const Transaction & txn, const Path & statePath, string & user, string & group, int & chmod); + //void setStateOptionsTxn(const Transaction & txn, const Path & statePath, const string & user, const string & group, int chmod); + //TODO !!!!!!!!!?? + if(revision_arg == 0) printMsg(lvlError, format("Reverted state of '%1%' to the latest revision") % statePath); //TODO lookup the number else @@ -804,27 +813,33 @@ bool getVersionedStateEntries(Database & nixDB, const Transaction & txn, TableId return true; } -void setStateUserGroup(Database & nixDB, const Transaction & txn, TableId stateRights, const Path & statePath, const string & user, const string & group, int chmod) +void setStateOptions(Database & nixDB, const Transaction & txn, TableId stateOptions, const Path & statePath, + const string & user, const string & group, int chmod, const string & runtimeArgs) { - string value = mergeToDBKey(user,mergeToDBKey(group, int2String(chmod))); - nixDB.setString(txn, stateRights, statePath, value); + string value = mergeToDBKey(user,mergeToDBKey(group, mergeToDBKey(int2String(chmod), runtimeArgs))); + nixDB.setString(txn, stateOptions, statePath, value); } -void getStateUserGroup(Database & nixDB, const Transaction & txn, TableId stateRights, const Path & statePath, string & user, string & group, int & chmod) +void getStateOptions(Database & nixDB, const Transaction & txn, TableId stateOptions, const Path & statePath, + string & user, string & group, int & chmod, string & runtimeArgs) { string value; - bool notEmpty = nixDB.queryString(txn, stateRights, statePath, value); + bool notEmpty = nixDB.queryString(txn, stateOptions, statePath, value); if(!notEmpty) throw Error(format("No rights found for path '%1%'") % statePath); string s1; + splitDBKey(value, s1, runtimeArgs); + + string s2; string chmod_s; - splitDBKey(value, s1, chmod_s); + splitDBKey(s1, s2, chmod_s); + bool succeed = string2Int(chmod_s, chmod); if(!succeed) throw Error(format("Malformed chmod value of path '%1%'") % statePath); - splitDBKey(s1, user, group); + splitDBKey(s2, user, group); } } diff --git a/src/libstore/store-state.hh b/src/libstore/store-state.hh index 7ad6cf128..1c02b406d 100644 --- a/src/libstore/store-state.hh +++ b/src/libstore/store-state.hh @@ -90,10 +90,10 @@ namespace nix { const Path & statePath, StateInfos & infos, const unsigned int revision = 0, const unsigned int timestamp = 0); /**/ - void setStateUserGroup(Database & nixDB, const Transaction & txn, TableId stateRights, const Path & statePath, const string & user, const string & group, int chmod); + void setStateOptions(Database & nixDB, const Transaction & txn, TableId stateOptions, const Path & statePath, const string & user, const string & group, int chmod, const string & runtimeArgs); /**/ - void getStateUserGroup(Database & nixDB, const Transaction & txn, TableId stateRights, const Path & statePath, string & user, string & group, int & chmod); + void getStateOptions(Database & nixDB, const Transaction & txn, TableId stateOptions, const Path & statePath, string & user, string & group, int & chmod, string & runtimeArgs); diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index e292cd002..31d56bb54 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -52,6 +52,8 @@ typedef enum { wopShareState, wopUnShareState, wopLookupStatePath, + wopSetStateOptions, + wopGetStateOptions, wopSetOptions, //40 } WorkerOp; diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index c9544d190..b2b627cc6 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -660,15 +660,9 @@ static void installDerivations(Globals & globals, //if it doesnt need to share state with some other component //&& the identifiers are equal - - //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - //TODO && (the users are equal || OR SHARED BETWEEN USERS) isnt this already user specific? - //TODO if( newSharedState == "" && - (oldStateIdentifier == newStateIdentifier - || (oldStateIdentifier == "__EMTPY__" && newStateIdentifier == "")) - + (oldStateIdentifier == newStateIdentifier || (oldStateIdentifier == "__EMTPY__" && newStateIdentifier == "")) ){ //query old state path diff --git a/src/nix-state/nix-state.cc b/src/nix-state/nix-state.cc index 407ed478d..476c59d4a 100644 --- a/src/nix-state/nix-state.cc +++ b/src/nix-state/nix-state.cc @@ -347,6 +347,20 @@ static void opRunComponent(Strings opFlags, Strings opArgs) //program_args } + //Lookup runtimeState args + int chmod; + string user, group, runtimeArgs; + store->getStateOptions(root_statePath, user, group, chmod, runtimeArgs); + Strings addedRuntimeArgs = tokenizeString(runtimeArgs, " "); + for (Strings::iterator i = addedRuntimeArgs.begin(); i != addedRuntimeArgs.end(); ++i){ + string arg = *i; + size_t pos; + string keyword = "@statePath@"; + while((pos=arg.find(keyword)) != string::npos) + arg.replace(pos,keyword.length(),root_statePath); + root_args += " " + arg; + } + printMsg(lvlError, format("Command: '%1%'") % (root_componentPath + root_binary + root_args)); executeShellCommand(root_componentPath + root_binary + root_args); } @@ -560,7 +574,7 @@ void run(Strings args) printMsg(lvlError, format("Rsync: '%1%'") % nixRsync); - copyContents("/nix/state/fwir6jlqygy90zadnx95zryfa8918qac-hellohardcodedstateworld-1.0-test/", "/home/wouterdb/tmp/aa/"); //TODO !!!!!!!!!!!!!!!!!!! + copyContents("/nix/state/fwir6jlqygy90zadnx95zryfa8918qac-hellohardcodedstateworld-1.0-test/", "/home/wouterdb/tmp/aa/"); Hash hash; PathSet references; diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 1bf67a9d5..41fa00a2d 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -430,8 +430,6 @@ static void opRegisterValidity(Strings opFlags, Strings opArgs) ValidPathInfos infos; - printMsg(lvlError, format("opRegisterValidity!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")); - while (1) { ValidPathInfo info = decodeValidPathInfo(cin); if (info.path == "") break; diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc index c23b3bb44..ace8d8a9b 100644 --- a/src/nix-worker/nix-worker.cc +++ b/src/nix-worker/nix-worker.cc @@ -524,7 +524,6 @@ static void performOp(Source & from, Sink & to, unsigned int op) } case wopQueryStateRevisions: { - printMsg(lvlError, format("queryStateRevisions nix-worker")); Path statePath = readStatePath(from); unsigned int revision = readBigUnsignedInt(from); RevisionClosure revisions; @@ -632,6 +631,34 @@ static void performOp(Source & from, Sink & to, unsigned int op) break; } + case wopSetStateOptions: { + Path statePath = readStatePath(from); + string user = readString(from); + string group = readString(from); + int chmod = readInt(from); + string runtimeArgs = readString(from); + startWork(); + store->setStateOptions(statePath, user, group, chmod, runtimeArgs); + stopWork(); + writeInt(1, to); + break; + } + + case wopGetStateOptions: { + Path statePath = readString(from); + string user, group, runtimeArgs; + int chmod; + startWork(); + store->getStateOptions(statePath, user, group, chmod, runtimeArgs); + stopWork(); + writeString(user, to); + writeString(group, to); + writeInt(chmod, to); + writeString(runtimeArgs, to); + writeInt(1, to); + break; + } + case wopSetOptions: { keepFailed = readInt(from) != 0; keepGoing = readInt(from) != 0; @@ -643,7 +670,7 @@ static void performOp(Source & from, Sink & to, unsigned int op) stopWork(); break; } - + default: throw Error(format("invalid operation %1%") % op); }