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
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
string shareState = "none";
string shareType = "none";
string syncState = "none";
string stateIdentifier = "";
bool createDirsBeforeInstall = false;
string runtimeStateParamters = "";
string sharedState = "";
vector<DerivationStateOutputDir> stateDirs;
for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
@ -520,13 +521,14 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args)
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 == "disableState") { disableState = evalBool(state, value); }
else if(key == "identifier"){ stateIdentifier = coerceToString(state, value, context, true); }
else if(key == "createDirsBeforeInstall"){ createDirsBeforeInstall = evalBool(state, value); }
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
the environment. */
else {
@ -614,7 +616,7 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args)
if(enableState && !disableState){
if(runtimeStateParamters == ""){
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 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)
drv.stateOutputDirs[(*i).path] = *(i);

View file

@ -1754,11 +1754,22 @@ void DerivationGoal::computeClosure()
* [scan for and state references and component references in the state path] //3,4
*/
if(isStateDrvTxn(noTxn, drv)){ //TODO
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 = scanForStateReferences(statePath, allStatePaths);
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;
printMsg(lvlTalkative, format("scanning for component and state references inside `%1%'") % statePath);
state_references = scanForReferences(statePath, allPaths);
state_stateReferences = scanForStateReferences(statePath, allStatePaths);
}
}
/* Register each output path as valid, and register the sets of
@ -1789,7 +1800,6 @@ void DerivationGoal::computeClosure()
//Register the state path valid
if(isStateDrvTxn(txn, drv))
{
//TODO ONLY CALL THIS FUNCTION ON A NON-SHARED STATE PATH!!!!!!!!!!! (why?)
Path statePath = drv.stateOutputs.find("state")->second.statepath;
registerValidPath(txn,
@ -1797,14 +1807,31 @@ void DerivationGoal::computeClosure()
Hash(), //emtpy hash
state_references,
state_stateReferences,
drvPath, 0); //TODO !!!!!!!!!!!!
drvPath, 0);
//Commit state
commitStatePathTxn(txn, statePath);
//Set first revision (if we committed something)
if(readRevisionNumber(statePath) == 1)
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();

View file

@ -4,7 +4,7 @@ Derive | ATermList ATermList ATermList ATermList ATermList ATermList string stri
| string string | ATerm | EnvBinding |
| string ATermList | ATerm | DerivationInput |
| 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 |
#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
for (ATermIterator i(stateOuts); i; ++i) {
ATerm id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shared, synchronization, createDirsBeforeInstall, runtimeStateParamters, username;
if (!matchDerivationStateOutput(*i, 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, shareType, synchronization, createDirsBeforeInstall, runtimeStateParamters, username, sharedState))
throwBadDrv(t);
DerivationStateOutput stateOut;
stateOut.statepath = aterm2String(statepath);
@ -104,11 +104,12 @@ Derivation parseDerivation(ATerm t)
stateOut.hash = aterm2String(hash);
stateOut.stateIdentifier = aterm2String(stateIdentifier);
stateOut.enabled = aterm2String(enabled);
stateOut.shared = aterm2String(shared);
stateOut.shareType = aterm2String(shareType);
stateOut.synchronization = aterm2String(synchronization);
stateOut.createDirsBeforeInstall = aterm2String(createDirsBeforeInstall);
stateOut.runtimeStateParamters = aterm2String(runtimeStateParamters);
stateOut.username = aterm2String(username);
stateOut.sharedState = aterm2String(sharedState);
drv.stateOutputs[aterm2String(id)] = stateOut;
}
@ -195,11 +196,12 @@ ATerm unparseDerivation(const Derivation & drv)
toATerm(i->second.hash),
toATerm(i->second.stateIdentifier),
toATerm(i->second.enabled),
toATerm(i->second.shared),
toATerm(i->second.shareType),
toATerm(i->second.synchronization),
toATerm(i->second.createDirsBeforeInstall),
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 stateIdentifier; //the identifier
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 commitReferences; //TODO none, direct, recursive-all
@ -51,18 +51,20 @@ struct DerivationStateOutput
string createDirsBeforeInstall; //if true: creates state dirs before installation
string runtimeStateParamters; //if not empty: these are the runtime parameters where state can be found (you can use $statepath here)
string username;
string username;
string sharedState; //Path to share state From
DerivationStateOutput()
{
}
//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(shared != "none" && shared != "full" && shared != "group")
throw Error(format("shared '%1%' is not a correct type") % shared);
if(shareType != "none" && shareType != "full" && shareType != "group")
throw Error(format("shareType '%1%' is not a correct type") % shareType);
if(synchronization != "none" && synchronization != "exclusive-lock" && synchronization != "recursive-exclusive-lock")
throw Error(format("synchronization '%1%' is not a correct type") % synchronization);
if(username == "")
@ -79,11 +81,12 @@ struct DerivationStateOutput
this->hash = hash;
this->stateIdentifier = stateIdentifier;
this->enabled = enabled;
this->shared = shared;
this->shareType = shareType;
this->synchronization = synchronization;
this->createDirsBeforeInstall = createDirsBeforeInstall;
this->runtimeStateParamters = runtimeStateParamters;
this->username = username;
this->sharedState = sharedState;
}
bool getEnabled(){
@ -104,11 +107,13 @@ struct DerivationStateOutput
//this->hash; //Clear this one?
//this->stateIdentifier; //Changes the statepath directly
this->enabled = "";
this->shared = "";
this->shareType = "";
this->synchronization = "";
this->createDirsBeforeInstall = "";
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;
/* dbSharedState :: Path -> Path
*
* Lists all paths that are shared with other paths
*/
static TableId dbSharedState = 0;
bool Substitute::operator == (const Substitute & sub) const
{
return program == sub.program
@ -205,6 +211,7 @@ LocalStore::LocalStore(bool reserveSpace)
dbStateComponentReferrers = nixDB.openTable("referrers_s_c", true);
dbStateStateReferrers = nixDB.openTable("referrers_s_s", true);
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 */
@ -406,6 +413,7 @@ static string stripPrefix(const string & prefix, const string & s)
//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)
{
@ -631,6 +639,8 @@ void LocalStore::queryStateReferrers(const Path & storePath, PathSet & stateRefe
nix::queryStateReferrersTxn(noTxn, storePath, stateReferrers, revision);
}
/********************/
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;
}
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). */
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);
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;
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
for (RevisionNumbersSet::iterator i = getRivisions.begin(); i != getRivisions.end(); ++i){
Path statePath = (*i).first;
@ -413,6 +401,9 @@ static void opRunComponent(Strings opFlags, Strings opArgs)
store->storePathRequisites(root_componentPath, false, statePaths, false, true, -1);
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?
//program_args