mirror of
https://github.com/NixOS/nix.git
synced 2025-11-26 20:20:58 +01:00
* Fixed very old transactional bug that caused a freeze sometimes
* State components that get their state at runtime can now be (un)installed with nix-env
This commit is contained in:
parent
05297240ea
commit
53a6b9aaa5
20 changed files with 186 additions and 87 deletions
|
|
@ -7,7 +7,7 @@ libstore_la_SOURCES = \
|
|||
pkginclude_HEADERS = \
|
||||
store-api.hh local-store.hh remote-store.hh derivations.hh misc.hh \
|
||||
globals.hh db.hh references.hh pathlocks.hh \
|
||||
worker-protocol.hh store-state.hh
|
||||
worker-protocol.hh store-state.hh build.hh
|
||||
|
||||
libstore_la_LIBADD = ../libutil/libutil.la \
|
||||
../libext3cow/libext3cow.la \
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "db.hh"
|
||||
#include "util.hh"
|
||||
#include "store-state.hh"
|
||||
#include "build.hh"
|
||||
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
|
@ -770,7 +771,7 @@ void DerivationGoal::haveDerivation()
|
|||
assert(store->isValidPath(drvPath));
|
||||
|
||||
/* Get the derivation. */
|
||||
drv = derivationFromPath(drvPath);
|
||||
drv = derivationFromPathTxn(noTxn, drvPath);
|
||||
|
||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||
i != drv.outputs.end(); ++i)
|
||||
|
|
@ -1319,7 +1320,7 @@ bool DerivationGoal::prepareBuild()
|
|||
`*i' as input paths. Only add the closures of output paths
|
||||
that are specified as inputs. */
|
||||
assert(store->isValidPath(i->first));
|
||||
Derivation inDrv = derivationFromPath(i->first);
|
||||
Derivation inDrv = derivationFromPathTxn(noTxn, i->first);
|
||||
for (StringSet::iterator j = i->second.begin(); j != i->second.end(); ++j)
|
||||
if (inDrv.outputs.find(*j) != inDrv.outputs.end()){
|
||||
computeFSClosure(inDrv.outputs[*j].path, inputPaths, true, false, -1); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO COPY STATE (done?)
|
||||
|
|
@ -2600,10 +2601,12 @@ void LocalStore::buildDerivations(const PathSet & drvPaths)
|
|||
}
|
||||
|
||||
|
||||
void LocalStore::ensurePath(const Path & path)
|
||||
void ensurePathTxn(const Transaction & txn, const Path & path)
|
||||
{
|
||||
/* If the path is already valid, we're done. */
|
||||
if (store->isValidPath(path)) return;
|
||||
|
||||
if (isValidPathTxn(txn, path))
|
||||
return;
|
||||
|
||||
Worker worker;
|
||||
GoalPtr goal = worker.makeSubstitutionGoal(path);
|
||||
|
|
@ -2615,5 +2618,10 @@ void LocalStore::ensurePath(const Path & path)
|
|||
throw Error(format("path `%1%' does not exist and cannot be created") % path);
|
||||
}
|
||||
|
||||
void LocalStore::ensurePath(const Path & path)
|
||||
{
|
||||
ensurePathTxn(noTxn, path);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
12
src/libstore/build.hh
Normal file
12
src/libstore/build.hh
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef BUILD_HH_
|
||||
#define BUILD_HH_
|
||||
|
||||
#include "db.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
void ensurePathTxn(const Transaction & txn, const Path & path);
|
||||
|
||||
}
|
||||
|
||||
#endif /*BUILD_HH_*/
|
||||
|
|
@ -701,7 +701,7 @@ bool Database::queryStateRevisions(const Transaction & txn, TableId revisions_ta
|
|||
|
||||
//query state versioined directorys/files
|
||||
vector<Path> sortedPaths;
|
||||
Derivation drv = derivationFromPath(queryStatePathDrvTxn(txn, getStatePath));
|
||||
Derivation drv = derivationFromPathTxn(txn, queryStatePathDrvTxn(txn, getStatePath));
|
||||
DerivationStateOutputs stateOutputs = drv.stateOutputs;
|
||||
DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs;
|
||||
for (DerivationStateOutputDirs::const_iterator j = stateOutputDirs.begin(); j != stateOutputDirs.end(); ++j){
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ void throwBadDrv(ATerm t)
|
|||
Derivation parseDerivation(ATerm t)
|
||||
{
|
||||
Derivation drv;
|
||||
ATermList outs, solidStateDeps, inDrvs, inSrcs, args, bnds;
|
||||
ATermList stateOuts = ATempty, stateOutDirs = ATempty;
|
||||
ATermList outs, inDrvs, inSrcs, args, bnds;
|
||||
ATermList stateOuts = ATempty, stateOutDirs = ATempty, solidStateDeps = ATempty;
|
||||
|
||||
ATerm builder, platform;
|
||||
|
||||
|
|
@ -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, shareType, synchronization, createDirsBeforeInstall, runtimeStateParamters, username, sharedState;
|
||||
if (!matchDerivationStateOutput(*i, id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shareType, synchronization, createDirsBeforeInstall, runtimeStateParamters, username, sharedState))
|
||||
ATerm id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shareType, synchronization, createDirsBeforeInstall, runtimeStateArgs, username, sharedState;
|
||||
if (!matchDerivationStateOutput(*i, id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shareType, synchronization, createDirsBeforeInstall, runtimeStateArgs, username, sharedState))
|
||||
throwBadDrv(t);
|
||||
DerivationStateOutput stateOut;
|
||||
stateOut.statepath = aterm2String(statepath);
|
||||
|
|
@ -107,7 +107,7 @@ Derivation parseDerivation(ATerm t)
|
|||
stateOut.shareType = aterm2String(shareType);
|
||||
stateOut.synchronization = aterm2String(synchronization);
|
||||
stateOut.createDirsBeforeInstall = aterm2String(createDirsBeforeInstall);
|
||||
stateOut.runtimeStateParamters = aterm2String(runtimeStateParamters);
|
||||
stateOut.runtimeStateArgs = aterm2String(runtimeStateArgs);
|
||||
stateOut.username = aterm2String(username);
|
||||
stateOut.sharedState = aterm2String(sharedState);
|
||||
drv.stateOutputs[aterm2String(id)] = stateOut;
|
||||
|
|
@ -199,7 +199,7 @@ ATerm unparseDerivation(const Derivation & drv)
|
|||
toATerm(i->second.shareType),
|
||||
toATerm(i->second.synchronization),
|
||||
toATerm(i->second.createDirsBeforeInstall),
|
||||
toATerm(i->second.runtimeStateParamters),
|
||||
toATerm(i->second.runtimeStateArgs),
|
||||
toATerm(i->second.username),
|
||||
toATerm(i->second.sharedState)
|
||||
));
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ struct DerivationStateOutput
|
|||
string commitBinaries; //TODO list of binaries that need (or not) to be committed when these binaries are called
|
||||
|
||||
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 runtimeStateArgs; //if not empty: these are the runtime parameters where state can be found (you can use $statepath here)
|
||||
|
||||
string username;
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ struct DerivationStateOutput
|
|||
}
|
||||
|
||||
//TODO add const ??
|
||||
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)
|
||||
DerivationStateOutput(Path statepath, string componentHash, string hashAlgo, string hash, string stateIdentifier, string enabled, string shareType, string synchronization, string createDirsBeforeInstall, string runtimeStateArgs, string username, string sharedState, bool check=true)
|
||||
{
|
||||
if(check){
|
||||
if(shareType != "none" && shareType != "full" && shareType != "group")
|
||||
|
|
@ -71,6 +71,10 @@ struct DerivationStateOutput
|
|||
throw Error(format("Username cannot be empty"));
|
||||
if(stateIdentifier == "__EMTPY__" || stateIdentifier == "__NOSTATE__")
|
||||
throw Error(format("the stateIdenfier cannot be this value '%1%'") % stateIdentifier);
|
||||
if(runtimeStateArgs == "__NOARGS__")
|
||||
throw Error(format("the runtimeStateArgs cannot be this value '%1%'") % runtimeStateArgs);
|
||||
|
||||
|
||||
}
|
||||
|
||||
//TODO
|
||||
|
|
@ -86,7 +90,7 @@ struct DerivationStateOutput
|
|||
this->shareType = shareType;
|
||||
this->synchronization = synchronization;
|
||||
this->createDirsBeforeInstall = createDirsBeforeInstall;
|
||||
this->runtimeStateParamters = runtimeStateParamters;
|
||||
this->runtimeStateArgs = runtimeStateArgs;
|
||||
this->username = username;
|
||||
this->sharedState = sharedState;
|
||||
}
|
||||
|
|
@ -112,7 +116,7 @@ struct DerivationStateOutput
|
|||
this->shareType = "";
|
||||
this->synchronization = "";
|
||||
this->createDirsBeforeInstall = "";
|
||||
this->runtimeStateParamters = "";
|
||||
this->runtimeStateArgs = "";
|
||||
//this->username; //Changes the statepath directly
|
||||
this->sharedState = "";
|
||||
|
||||
|
|
|
|||
|
|
@ -489,7 +489,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
|||
for (PathSet::iterator i = livePaths.begin();
|
||||
i != livePaths.end(); ++i)
|
||||
if (isDerivation(*i)) {
|
||||
Derivation drv = derivationFromPath(*i);
|
||||
Derivation drv = derivationFromPathTxn(noTxn, *i);
|
||||
for (DerivationOutputs::iterator j = drv.outputs.begin();
|
||||
j != drv.outputs.end(); ++j)
|
||||
if (store->isValidPath(j->second.path))
|
||||
|
|
|
|||
|
|
@ -453,7 +453,6 @@ void setReferences(const Transaction & txn, const Path & 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("Setting references for %1% (revision:%2%)") % store_or_statePath % int2String(revision));
|
||||
/*
|
||||
for (PathSet::iterator i = references.begin(); i != references.end(); ++i)
|
||||
printMsg(lvlError, format("'%2%' has references: %1%") % *i % store_or_statePath);
|
||||
|
|
@ -463,6 +462,8 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath,
|
|||
|
||||
if(isRealisablePath(txn, store_or_statePath))
|
||||
{
|
||||
printMsg(lvlError, format("Setting references for storepath '%1%'") % store_or_statePath);
|
||||
|
||||
//Just overwrite the old references, since there is oly 1 revision of a storePath
|
||||
|
||||
Paths oldReferences_c_c;
|
||||
|
|
@ -481,6 +482,8 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath,
|
|||
else if(isRealisableStatePath(txn, store_or_statePath))
|
||||
{
|
||||
|
||||
printMsg(lvlError, format("Setting references for statepath '%1%' (revision:%2%)") % store_or_statePath % int2String(revision));
|
||||
|
||||
//Write references to a special revision (since there are multiple revisions of a statePath)
|
||||
|
||||
//query the references of revision (-1 is query the latest references)
|
||||
|
|
@ -498,7 +501,7 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath,
|
|||
}
|
||||
else
|
||||
throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void queryXReferencesTxn(const Transaction & txn, const Path & store_or_statePath, PathSet & references, const bool component_or_state, const int revision, int timestamp)
|
||||
|
|
@ -693,9 +696,7 @@ void setDeriver(const Transaction & txn, const Path & storePath, const Path & de
|
|||
if (!isRealisablePath(txn, storePath))
|
||||
throw Error(format("path `%1%' is not valid") % storePath);
|
||||
|
||||
//printMsg(lvlError, format("Ttttttttttttttttttttttttt %1%") % deriver);
|
||||
|
||||
if (isStateDrvPathTxn(txn, deriver)){ //Redirect if its a state component //hanges somtimes !!!!!!!!!!!!!!!!!!!
|
||||
if (isStateDrvPathTxn(txn, deriver)){ //Redirect if its a state component
|
||||
addStateDeriver(txn, storePath, deriver);
|
||||
}
|
||||
else{
|
||||
|
|
@ -712,14 +713,14 @@ PathSet mergeNewDerivationIntoList(const Path & storepath, const Path & newdrv,
|
|||
{
|
||||
PathSet newdrvs;
|
||||
|
||||
Derivation drv = derivationFromPath(newdrv);
|
||||
Derivation drv = derivationFromPathTxn(noTxn, newdrv);
|
||||
string identifier = drv.stateOutputs.find("state")->second.stateIdentifier;
|
||||
string user = drv.stateOutputs.find("state")->second.username;
|
||||
|
||||
for (PathSet::iterator i = drvs.begin(); i != drvs.end(); ++i) //Check if we need to remove old drvs
|
||||
{
|
||||
Path drv = *i;
|
||||
Derivation getdrv = derivationFromPath(drv);
|
||||
Derivation getdrv = derivationFromPathTxn(noTxn, drv);
|
||||
string getIdentifier = getdrv.stateOutputs.find("state")->second.stateIdentifier;
|
||||
string getUser = getdrv.stateOutputs.find("state")->second.username;
|
||||
|
||||
|
|
@ -747,7 +748,7 @@ void addStateDeriver(const Transaction & txn, const Path & storePath, const Path
|
|||
if (!isRealisablePath(txn, storePath))
|
||||
throw Error(format("path `%1%' is not valid") % storePath);
|
||||
|
||||
Derivation drv = derivationFromPath(deriver);
|
||||
Derivation drv = derivationFromPathTxn(txn, deriver);
|
||||
string identifier = drv.stateOutputs.find("state")->second.stateIdentifier;
|
||||
string user = drv.stateOutputs.find("state")->second.username;
|
||||
|
||||
|
|
@ -786,8 +787,7 @@ bool LocalStore::isStateComponent(const Path & storePath)
|
|||
|
||||
bool isStateDrvPathTxn(const Transaction & txn, const Path & drvPath)
|
||||
{
|
||||
//printMsg(lvlError, format("Sssssssssssssssssss %1%") % drvPath);
|
||||
Derivation drv = derivationFromPath(drvPath);
|
||||
Derivation drv = derivationFromPathTxn(txn, drvPath);
|
||||
return isStateDrvTxn(txn, drv);
|
||||
}
|
||||
|
||||
|
|
@ -817,7 +817,7 @@ Path queryDeriver(const Transaction & txn, const Path & storePath)
|
|||
|
||||
bool b = nixDB.queryString(txn, dbDerivers, storePath, deriver);
|
||||
|
||||
Derivation drv = derivationFromPath(deriver);
|
||||
Derivation drv = derivationFromPathTxn(txn, deriver);
|
||||
if (isStateDrvTxn(txn, drv))
|
||||
throw Error(format("This deriver `%1%' is a state deriver, u should use queryDerivers instead of queryDeriver") % deriver);
|
||||
|
||||
|
|
@ -843,7 +843,7 @@ PathSet queryDerivers(const Transaction & txn, const Path & storePath, const str
|
|||
for (Strings::iterator i = alldata.begin(); i != alldata.end(); ++i) { //filter on username and identifier
|
||||
|
||||
string derivationpath = (*i);
|
||||
Derivation drv = derivationFromPath(derivationpath);
|
||||
Derivation drv = derivationFromPathTxn(txn, derivationpath);
|
||||
|
||||
if (drv.outputs.size() != 1)
|
||||
throw Error(format("The call queryDerivers with storepath %1% is not a statePath") % storePath);
|
||||
|
|
@ -1093,8 +1093,9 @@ void registerValidPaths(const Transaction & txn, const ValidPathInfos & infos)
|
|||
|
||||
//We cannot check the statePath since registerValidPath is called twice, first for the component path, and then for the state path....
|
||||
|
||||
if(isStorePath_b)
|
||||
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 ....
|
||||
}
|
||||
|
|
@ -1649,7 +1650,7 @@ void storePathRequisitesTxn(const Transaction & txn, const Path & storeOrstatePa
|
|||
for (PathSet::iterator i = paths.begin();
|
||||
i != paths.end(); ++i)
|
||||
if (isDerivation(*i)) {
|
||||
Derivation drv = derivationFromPath(*i);
|
||||
Derivation drv = derivationFromPathTxn(txn, *i);
|
||||
for (DerivationOutputs::iterator j = drv.outputs.begin();
|
||||
j != drv.outputs.end(); ++j)
|
||||
if (isValidPathTxn(txn, j->second.path))
|
||||
|
|
@ -1816,9 +1817,8 @@ PathSet getSharedWithPathSetRecTxn(const Transaction & txn, const Path & statePa
|
|||
Path statePath_ns = toNonSharedPathTxn(txn, statePath);
|
||||
PathSet empty;
|
||||
return getSharedWithPathSetRecTxn_private(txn, statePath_ns, empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Upgrade from schema 1 (Nix <= 0.7) to schema 2 (Nix >= 0.8). */
|
||||
static void upgradeStore07()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -244,6 +244,8 @@ PathSet toNonSharedPathSetTxn(const Transaction & txn, const PathSet & statePath
|
|||
Path toNonSharedPathTxn(const Transaction & txn, const Path & statePath);
|
||||
PathSet getSharedWithPathSetRecTxn(const Transaction & txn, const Path & statePath);
|
||||
|
||||
void ensurePathTxn(const Transaction & txn, const Path & path);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@
|
|||
namespace nix {
|
||||
|
||||
|
||||
Derivation derivationFromPath(const Path & drvPath)
|
||||
Derivation derivationFromPathTxn(const Transaction & txn, const Path & drvPath)
|
||||
{
|
||||
assertStorePath(drvPath);
|
||||
store->ensurePath(drvPath);
|
||||
//printMsg(lvlError, format("uuuuuuuuuuuuuuuuuu"));
|
||||
ensurePathTxn(txn, drvPath);
|
||||
ATerm t = ATreadFromNamedFile(drvPath.c_str());
|
||||
if (!t) throw Error(format("cannot read aterm from `%1%'") % drvPath);
|
||||
if (!t)
|
||||
throw Error(format("cannot read aterm from `%1%'") % drvPath);
|
||||
return parseDerivation(t);
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ void queryMissing(const PathSet & targets,
|
|||
|
||||
if (isDerivation(p)) {
|
||||
if (!store->isValidPath(p)) continue;
|
||||
Derivation drv = derivationFromPath(p);
|
||||
Derivation drv = derivationFromPathTxn(noTxn, p);
|
||||
|
||||
bool mustBuild = false;
|
||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace nix {
|
|||
|
||||
/* Read a derivation, after ensuring its existence through
|
||||
ensurePath(). */
|
||||
Derivation derivationFromPath(const Path & drvPath);
|
||||
Derivation derivationFromPathTxn(const Transaction & txn, const Path & drvPath);
|
||||
|
||||
/* Place in `paths' the set of all store paths in the file system
|
||||
closure of `storePath'; that is, all paths than can be directly or
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ Snapshots commitStatePathTxn(const Transaction & txn, const Path & statePath)
|
|||
throw Error(format("path `%1%' is not a valid state path") % statePath);
|
||||
|
||||
//queryDeriversStatePath??
|
||||
Derivation drv = derivationFromPath(queryStatePathDrvTxn(txn, statePath));
|
||||
Derivation drv = derivationFromPathTxn(txn, queryStatePathDrvTxn(txn, statePath));
|
||||
DerivationStateOutputs stateOutputs = drv.stateOutputs;
|
||||
DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue