1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-26 04:00:59 +01:00

Before adjusting queryReferences/Referrers to handle shared state paths

This commit is contained in:
Wouter den Breejen 2007-07-19 12:25:38 +00:00
parent b46db4dea7
commit 7f2140d17f
8 changed files with 115 additions and 39 deletions

View file

@ -417,11 +417,12 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args)
//state vars //state vars
bool enableState = false; //We dont do state by default, but if a user defines stateDirs for example, than this becomes true. bool enableState = false; //We dont do state by default, but if a user defines stateDirs for example, than this becomes true.
bool disableState = false; //Becomes true if the user explicitly says: no state bool disableState = false; //Becomes true if the user explicitly says: no state
string shareState = "none"; string shareType = "none";
string syncState = "none"; string syncState = "none";
string stateIdentifier = ""; string stateIdentifier = "";
bool createDirsBeforeInstall = false; bool createDirsBeforeInstall = false;
string runtimeStateParamters = ""; string runtimeStateParamters = "";
string sharedState = "";
vector<DerivationStateOutputDir> stateDirs; vector<DerivationStateOutputDir> stateDirs;
for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) { for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
@ -520,12 +521,13 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args)
drv.solidStateDeps.insert(s); drv.solidStateDeps.insert(s);
} }
} }
else if(key == "shareState") { shareState = coerceToString(state, value, context, true); } else if(key == "shareType") { shareType = coerceToString(state, value, context, true); }
else if(key == "synchronization") { syncState = coerceToString(state, value, context, true); } else if(key == "synchronization") { syncState = coerceToString(state, value, context, true); }
else if(key == "disableState") { disableState = evalBool(state, value); } else if(key == "disableState") { disableState = evalBool(state, value); }
else if(key == "identifier"){ stateIdentifier = coerceToString(state, value, context, true); } else if(key == "identifier"){ stateIdentifier = coerceToString(state, value, context, true); }
else if(key == "createDirsBeforeInstall"){ createDirsBeforeInstall = evalBool(state, value); } else if(key == "createDirsBeforeInstall"){ createDirsBeforeInstall = evalBool(state, value); }
else if(key == "runtimeStateParamters"){ runtimeStateParamters = coerceToString(state, value, context, true); } else if(key == "runtimeStateParamters"){ runtimeStateParamters = coerceToString(state, value, context, true); }
else if(key == "shareStateFrom"){ sharedState = coerceToString(state, value, context, true); }
/* All other attributes are passed to the builder through /* All other attributes are passed to the builder through
the environment. */ the environment. */
@ -614,7 +616,7 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args)
if(enableState && !disableState){ if(enableState && !disableState){
if(runtimeStateParamters == ""){ if(runtimeStateParamters == ""){
string enableStateS = bool2string("true"); string enableStateS = bool2string("true");
drv.stateOutputs["state"] = DerivationStateOutput("", "", "", "", stateIdentifier, enableStateS, "", "", "", runtimeStateParamters, getCallingUserName(), false); drv.stateOutputs["state"] = DerivationStateOutput("", "", "", "", stateIdentifier, enableStateS, "", "", "", runtimeStateParamters, getCallingUserName(), "", false);
} }
} }
@ -649,7 +651,8 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args)
string enableStateS = bool2string("true"); string enableStateS = bool2string("true");
string createDirsBeforeInstallS = bool2string(createDirsBeforeInstall); string createDirsBeforeInstallS = bool2string(createDirsBeforeInstall);
drv.stateOutputs["state"] = DerivationStateOutput(stateOutPath, printHash(componentHash), outputHashAlgo, outputHash, stateIdentifier, enableStateS, shareState, syncState, createDirsBeforeInstallS, runtimeStateParamters, getCallingUserName()); drv.stateOutputs["state"] = DerivationStateOutput(stateOutPath, printHash(componentHash), outputHashAlgo, outputHash, stateIdentifier, enableStateS,
shareType, syncState, createDirsBeforeInstallS, runtimeStateParamters, getCallingUserName(), sharedState);
for(vector<DerivationStateOutputDir>::iterator i = stateDirs.begin(); i != stateDirs.end(); ++i) for(vector<DerivationStateOutputDir>::iterator i = stateDirs.begin(); i != stateDirs.end(); ++i)
drv.stateOutputDirs[(*i).path] = *(i); drv.stateOutputDirs[(*i).path] = *(i);

View file

@ -1754,12 +1754,23 @@ void DerivationGoal::computeClosure()
* [scan for and state references and component references in the state path] //3,4 * [scan for and state references and component references in the state path] //3,4
*/ */
if(isStateDrvTxn(noTxn, drv)){ //TODO if(isStateDrvTxn(noTxn, drv)){ //TODO
Path sharedState = drv.stateOutputs.find("state")->second.sharedState;
if(sharedState != ""){
if (!store->isValidStatePath(sharedState))
throw BuildError(format("sharedState path `%1%', is not a valid state path") % sharedState);
//We dont need to scan for state references since at the query to the state path we give the results of the linked-to path
}
else
{
Path statePath = drv.stateOutputs.find("state")->second.statepath; Path statePath = drv.stateOutputs.find("state")->second.statepath;
printMsg(lvlTalkative, format("scanning for component and state references inside `%1%'") % statePath); printMsg(lvlTalkative, format("scanning for component and state references inside `%1%'") % statePath);
state_references = scanForReferences(statePath, allPaths); state_references = scanForReferences(statePath, allPaths);
state_stateReferences = scanForStateReferences(statePath, allStatePaths); state_stateReferences = scanForStateReferences(statePath, allStatePaths);
} }
}
/* Register each output path as valid, and register the sets of /* Register each output path as valid, and register the sets of
paths referenced by each of them. This is wrapped in one paths referenced by each of them. This is wrapped in one
@ -1789,7 +1800,6 @@ void DerivationGoal::computeClosure()
//Register the state path valid //Register the state path valid
if(isStateDrvTxn(txn, drv)) if(isStateDrvTxn(txn, drv))
{ {
//TODO ONLY CALL THIS FUNCTION ON A NON-SHARED STATE PATH!!!!!!!!!!! (why?)
Path statePath = drv.stateOutputs.find("state")->second.statepath; Path statePath = drv.stateOutputs.find("state")->second.statepath;
registerValidPath(txn, registerValidPath(txn,
@ -1797,7 +1807,7 @@ void DerivationGoal::computeClosure()
Hash(), //emtpy hash Hash(), //emtpy hash
state_references, state_references,
state_stateReferences, state_stateReferences,
drvPath, 0); //TODO !!!!!!!!!!!! drvPath, 0);
//Commit state //Commit state
commitStatePathTxn(txn, statePath); commitStatePathTxn(txn, statePath);
@ -1805,6 +1815,23 @@ void DerivationGoal::computeClosure()
//Set first revision (if we committed something) //Set first revision (if we committed something)
if(readRevisionNumber(statePath) == 1) if(readRevisionNumber(statePath) == 1)
updateRevisionsRecursivelyTxn(txn, statePath); updateRevisionsRecursivelyTxn(txn, statePath);
//Shared state
Path sharedState = drv.stateOutputs.find("state")->second.sharedState;
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
//Set in database
setSharedStateTxn(txn, statePath, sharedState);
}
} }
txn.commit(); txn.commit();

View file

@ -4,7 +4,7 @@ Derive | ATermList ATermList ATermList ATermList ATermList ATermList string stri
| string string | ATerm | EnvBinding | | string string | ATerm | EnvBinding |
| string ATermList | ATerm | DerivationInput | | string ATermList | ATerm | DerivationInput |
| string string string string | ATerm | DerivationOutput | | string string string string | ATerm | DerivationOutput |
| string string string string string string string string string string string string | ATerm | DerivationStateOutput | | string string string string string string string string string string string string string | ATerm | DerivationStateOutput |
| string string string | ATerm | DerivationStateOutputDir | | string string string | ATerm | DerivationStateOutputDir |
#We use DeriveWithOutState to create derivations that dont use state, and thus dont have the stateDerivationStateOutput and DerivationStateOutputDir in their derivation #We use DeriveWithOutState to create derivations that dont use state, and thus dont have the stateDerivationStateOutput and DerivationStateOutputDir in their derivation

View file

@ -93,8 +93,8 @@ Derivation parseDerivation(ATerm t)
{ {
//parse state part //parse state part
for (ATermIterator i(stateOuts); i; ++i) { for (ATermIterator i(stateOuts); i; ++i) {
ATerm id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shared, synchronization, createDirsBeforeInstall, runtimeStateParamters, username; ATerm id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shareType, synchronization, createDirsBeforeInstall, runtimeStateParamters, username, sharedState;
if (!matchDerivationStateOutput(*i, id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shared, synchronization, createDirsBeforeInstall, runtimeStateParamters, username)) if (!matchDerivationStateOutput(*i, id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shareType, synchronization, createDirsBeforeInstall, runtimeStateParamters, username, sharedState))
throwBadDrv(t); throwBadDrv(t);
DerivationStateOutput stateOut; DerivationStateOutput stateOut;
stateOut.statepath = aterm2String(statepath); stateOut.statepath = aterm2String(statepath);
@ -104,11 +104,12 @@ Derivation parseDerivation(ATerm t)
stateOut.hash = aterm2String(hash); stateOut.hash = aterm2String(hash);
stateOut.stateIdentifier = aterm2String(stateIdentifier); stateOut.stateIdentifier = aterm2String(stateIdentifier);
stateOut.enabled = aterm2String(enabled); stateOut.enabled = aterm2String(enabled);
stateOut.shared = aterm2String(shared); stateOut.shareType = aterm2String(shareType);
stateOut.synchronization = aterm2String(synchronization); stateOut.synchronization = aterm2String(synchronization);
stateOut.createDirsBeforeInstall = aterm2String(createDirsBeforeInstall); stateOut.createDirsBeforeInstall = aterm2String(createDirsBeforeInstall);
stateOut.runtimeStateParamters = aterm2String(runtimeStateParamters); stateOut.runtimeStateParamters = aterm2String(runtimeStateParamters);
stateOut.username = aterm2String(username); stateOut.username = aterm2String(username);
stateOut.sharedState = aterm2String(sharedState);
drv.stateOutputs[aterm2String(id)] = stateOut; drv.stateOutputs[aterm2String(id)] = stateOut;
} }
@ -195,11 +196,12 @@ ATerm unparseDerivation(const Derivation & drv)
toATerm(i->second.hash), toATerm(i->second.hash),
toATerm(i->second.stateIdentifier), toATerm(i->second.stateIdentifier),
toATerm(i->second.enabled), toATerm(i->second.enabled),
toATerm(i->second.shared), toATerm(i->second.shareType),
toATerm(i->second.synchronization), toATerm(i->second.synchronization),
toATerm(i->second.createDirsBeforeInstall), toATerm(i->second.createDirsBeforeInstall),
toATerm(i->second.runtimeStateParamters), toATerm(i->second.runtimeStateParamters),
toATerm(i->second.username) toATerm(i->second.username),
toATerm(i->second.sharedState)
)); ));
} }

View file

@ -42,7 +42,7 @@ struct DerivationStateOutput
string hash; string hash;
string stateIdentifier; //the identifier string stateIdentifier; //the identifier
string enabled; //enable or disable state string enabled; //enable or disable state
string shared; //none, full, group string shareType; //none, full, group
string synchronization; //none (no locks), exclusive-lock, recursive-exclusive-lock string synchronization; //none (no locks), exclusive-lock, recursive-exclusive-lock
string commitReferences; //TODO none, direct, recursive-all string commitReferences; //TODO none, direct, recursive-all
@ -53,16 +53,18 @@ struct DerivationStateOutput
string username; string username;
string sharedState; //Path to share state From
DerivationStateOutput() DerivationStateOutput()
{ {
} }
//TODO add const ?? //TODO add const ??
DerivationStateOutput(Path statepath, string componentHash, string hashAlgo, string hash, string stateIdentifier, string enabled, string shared, string synchronization, string createDirsBeforeInstall, string runtimeStateParamters, string username, bool check=true) 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)
{ {
if(check){ if(check){
if(shared != "none" && shared != "full" && shared != "group") if(shareType != "none" && shareType != "full" && shareType != "group")
throw Error(format("shared '%1%' is not a correct type") % shared); throw Error(format("shareType '%1%' is not a correct type") % shareType);
if(synchronization != "none" && synchronization != "exclusive-lock" && synchronization != "recursive-exclusive-lock") if(synchronization != "none" && synchronization != "exclusive-lock" && synchronization != "recursive-exclusive-lock")
throw Error(format("synchronization '%1%' is not a correct type") % synchronization); throw Error(format("synchronization '%1%' is not a correct type") % synchronization);
if(username == "") if(username == "")
@ -79,11 +81,12 @@ struct DerivationStateOutput
this->hash = hash; this->hash = hash;
this->stateIdentifier = stateIdentifier; this->stateIdentifier = stateIdentifier;
this->enabled = enabled; this->enabled = enabled;
this->shared = shared; this->shareType = shareType;
this->synchronization = synchronization; this->synchronization = synchronization;
this->createDirsBeforeInstall = createDirsBeforeInstall; this->createDirsBeforeInstall = createDirsBeforeInstall;
this->runtimeStateParamters = runtimeStateParamters; this->runtimeStateParamters = runtimeStateParamters;
this->username = username; this->username = username;
this->sharedState = sharedState;
} }
bool getEnabled(){ bool getEnabled(){
@ -104,11 +107,13 @@ struct DerivationStateOutput
//this->hash; //Clear this one? //this->hash; //Clear this one?
//this->stateIdentifier; //Changes the statepath directly //this->stateIdentifier; //Changes the statepath directly
this->enabled = ""; this->enabled = "";
this->shared = ""; this->shareType = "";
this->synchronization = ""; this->synchronization = "";
this->createDirsBeforeInstall = ""; this->createDirsBeforeInstall = "";
this->runtimeStateParamters = ""; this->runtimeStateParamters = "";
//this->username; //Changes the statepath directly //this->username; //Changes the statepath directly
this->sharedState = "";
} }
}; };

View file

@ -131,6 +131,12 @@ static TableId dbStateInfo = 0;
*/ */
static TableId dbStateRevisions = 0; static TableId dbStateRevisions = 0;
/* dbSharedState :: Path -> Path
*
* Lists all paths that are shared with other paths
*/
static TableId dbSharedState = 0;
bool Substitute::operator == (const Substitute & sub) const bool Substitute::operator == (const Substitute & sub) const
{ {
return program == sub.program return program == sub.program
@ -205,6 +211,7 @@ LocalStore::LocalStore(bool reserveSpace)
dbStateComponentReferrers = nixDB.openTable("referrers_s_c", true); dbStateComponentReferrers = nixDB.openTable("referrers_s_c", true);
dbStateStateReferrers = nixDB.openTable("referrers_s_s", true); dbStateStateReferrers = nixDB.openTable("referrers_s_s", true);
dbStateRevisions = nixDB.openTable("staterevisions"); dbStateRevisions = nixDB.openTable("staterevisions");
dbSharedState = nixDB.openTable("sharedState");
dbSolidStateReferences = nixDB.openTable("references_solid_c_s"); /* The contents of this table is included in references_c_s */ dbSolidStateReferences = nixDB.openTable("references_solid_c_s"); /* The contents of this table is included in references_c_s */
@ -406,6 +413,7 @@ static string stripPrefix(const string & prefix, const string & s)
//TODO move the code of get(State)Referrers into query variant ..... !!!!!!!!!!!!!!!!!!!!!!!!!!!!??? //TODO move the code of get(State)Referrers into query variant ..... !!!!!!!!!!!!!!!!!!!!!!!!!!!!???
/********************/
static PathSet getReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision) static PathSet getReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision)
{ {
@ -631,6 +639,8 @@ void LocalStore::queryStateReferrers(const Path & storePath, PathSet & stateRefe
nix::queryStateReferrersTxn(noTxn, storePath, stateReferrers, revision); nix::queryStateReferrersTxn(noTxn, storePath, stateReferrers, revision);
} }
/********************/
void setDeriver(const Transaction & txn, const Path & storePath, const Path & deriver) void setDeriver(const Transaction & txn, const Path & storePath, const Path & deriver)
{ {
@ -1731,6 +1741,41 @@ bool querySolidStateReferencesTxn(const Transaction & txn, const Path & statePat
return notempty; return notempty;
} }
void setSharedStateTxn(const Transaction & txn, const Path & statePath, const Path & shared_with)
{
//Remove earlier entries
nixDB.delPair(txn, dbSharedState, statePath);
//Set new entry
nixDB.setString(txn, dbSharedState, statePath, shared_with);
}
bool querySharedStateTxn(const Transaction & txn, const Path & statePath, Path & shared_with)
{
return nixDB.queryString(txn, dbSharedState, statePath, shared_with);
}
PathSet toNonSharedPathSetTxn(const Transaction & txn, const PathSet & statePaths)
{
PathSet real_statePaths;
//we loop over all paths in the list
for (PathSet::const_iterator i = statePaths.begin(); i != statePaths.end(); ++i){
Path sharedPath;
Path checkPath = *i;
real_statePaths.insert(checkPath);
//for each path we do querySharedStateTxn until there the current path is not a shared path anymore
while(querySharedStateTxn(txn, checkPath, sharedPath)){
real_statePaths.erase(checkPath);
real_statePaths.insert(sharedPath);
checkPath = sharedPath;
}
}
return real_statePaths;
}
/* Upgrade from schema 1 (Nix <= 0.7) to schema 2 (Nix >= 0.8). */ /* Upgrade from schema 1 (Nix <= 0.7) to schema 2 (Nix >= 0.8). */
static void upgradeStore07() static void upgradeStore07()
{ {

View file

@ -243,6 +243,9 @@ bool isValidStatePathTxn(const Transaction & txn, const Path & path);
void setSolidStateReferencesTxn(const Transaction & txn, const Path & statePath, const PathSet & paths); void setSolidStateReferencesTxn(const Transaction & txn, const Path & statePath, const PathSet & paths);
bool querySolidStateReferencesTxn(const Transaction & txn, const Path & statePath, PathSet & paths); bool querySolidStateReferencesTxn(const Transaction & txn, const Path & statePath, PathSet & paths);
void setSharedStateTxn(const Transaction & txn, const Path & statePath, const Path & shared_with);
PathSet toNonSharedPathSetTxn(const Transaction & txn, const PathSet & statePaths);
} }

View file

@ -249,18 +249,6 @@ static void revertToRevision(Strings opFlags, Strings opArgs)
RevisionNumbersSet getRivisions; RevisionNumbersSet getRivisions;
bool b = store->queryStateRevisions(statePath, getRivisions, revision_arg); bool b = store->queryStateRevisions(statePath, getRivisions, revision_arg);
//Sort the statePaths from all drvs
//map<Path, string> state_repos;
//vector<Path> sorted_paths;
//for (PathSet::iterator d = statePaths.begin(); d != statePaths.end(); ++d){
//state_repos[statePath] = repos;
// sorted_paths.push_back(statePath);
//}
//sort(sorted_paths.begin(), sorted_paths.end());
//string repos =
//Revert each statePath in the list //Revert each statePath in the list
for (RevisionNumbersSet::iterator i = getRivisions.begin(); i != getRivisions.end(); ++i){ for (RevisionNumbersSet::iterator i = getRivisions.begin(); i != getRivisions.end(); ++i){
Path statePath = (*i).first; Path statePath = (*i).first;
@ -413,6 +401,9 @@ static void opRunComponent(Strings opFlags, Strings opArgs)
store->storePathRequisites(root_componentPath, false, statePaths, false, true, -1); store->storePathRequisites(root_componentPath, false, statePaths, false, true, -1);
statePaths.insert(root_statePath); statePaths.insert(root_statePath);
//Replace all shared paths in the set for their real paths
statePaths = toNonSharedPathSetTxn(noTxn, statePaths);
//TODO maybe also scan the parameters for state or component hashes? //TODO maybe also scan the parameters for state or component hashes?
//program_args //program_args