Runtime state arguments added to nix-state.

This commit is contained in:
Wouter den Breejen 2007-10-23 14:02:25 +00:00
parent c0dceea9f0
commit 7e0dcc5dcb
15 changed files with 155 additions and 50 deletions

3
TODO Normal file
View file

@ -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
-

View file

@ -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"] = "";

View file

@ -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;

View file

@ -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<string, unsigned int> 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<Hash, std::pair<Path, ino_t> > HashToPath;

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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;

View file

@ -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;
};

View file

@ -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);
}
}

View file

@ -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);

View file

@ -52,6 +52,8 @@ typedef enum {
wopShareState,
wopUnShareState,
wopLookupStatePath,
wopSetStateOptions,
wopGetStateOptions,
wopSetOptions, //40
} WorkerOp;

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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);
}