mirror of
https://github.com/NixOS/nix.git
synced 2025-11-26 12:10:59 +01:00
Added more state garbage collection code
This commit is contained in:
parent
60a32fcbf3
commit
ef37776094
4 changed files with 81 additions and 50 deletions
|
|
@ -412,7 +412,7 @@ static void dfsVisit(const PathSet & paths, const Path & path,
|
||||||
|
|
||||||
PathSet references;
|
PathSet references;
|
||||||
if (store->isValidPath(path))
|
if (store->isValidPath(path))
|
||||||
store->queryStoreReferences(path, references, 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
store->queryStoreReferences(path, references, 0);
|
||||||
|
|
||||||
for (PathSet::iterator i = references.begin();
|
for (PathSet::iterator i = references.begin();
|
||||||
i != references.end(); ++i)
|
i != references.end(); ++i)
|
||||||
|
|
@ -424,6 +424,8 @@ static void dfsVisit(const PathSet & paths, const Path & path,
|
||||||
sorted.push_front(path);
|
sorted.push_front(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO maybe? stateTopoSortPaths(const PathSet & paths)
|
||||||
|
|
||||||
|
|
||||||
Paths topoSortPaths(const PathSet & paths)
|
Paths topoSortPaths(const PathSet & paths)
|
||||||
{
|
{
|
||||||
|
|
@ -446,9 +448,6 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
bool gcKeepDerivations =
|
bool gcKeepDerivations =
|
||||||
queryBoolSetting("gc-keep-derivations", true);
|
queryBoolSetting("gc-keep-derivations", true);
|
||||||
|
|
||||||
gcKeepDerivations = true; //TODO for now. we always keep drvs in the state branch since we
|
|
||||||
//need some of them to lookup info
|
|
||||||
|
|
||||||
/* Acquire the global GC root. This prevents
|
/* Acquire the global GC root. This prevents
|
||||||
a) New roots from being added.
|
a) New roots from being added.
|
||||||
b) Processes from creating new temporary root files. */
|
b) Processes from creating new temporary root files. */
|
||||||
|
|
@ -479,7 +478,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
roots under the `references' relation. */
|
roots under the `references' relation. */
|
||||||
PathSet livePaths;
|
PathSet livePaths;
|
||||||
for (PathSet::const_iterator i = roots.begin(); i != roots.end(); ++i){
|
for (PathSet::const_iterator i = roots.begin(); i != roots.end(); ++i){
|
||||||
printMsg(lvlError, format("CHECK '%1%'") % *i);
|
//printMsg(lvlError, format("CHECK '%1%'") % *i);
|
||||||
computeFSClosure(canonPath(*i), livePaths, true, true, 0);
|
computeFSClosure(canonPath(*i), livePaths, true, true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -490,7 +489,8 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
i != livePaths.end(); ++i)
|
i != livePaths.end(); ++i)
|
||||||
{
|
{
|
||||||
if (store->isStateComponent(*i)){
|
if (store->isStateComponent(*i)){
|
||||||
printMsg(lvlError, format("CHECK-STATE-STORE '%1%'") % *i);
|
//printMsg(lvlError, format("Live state store '%1%'") % *i);
|
||||||
|
|
||||||
//we select ALL state Derivations here
|
//we select ALL state Derivations here
|
||||||
PathSet derivers = store->queryDerivers(*i, "*", "*");
|
PathSet derivers = store->queryDerivers(*i, "*", "*");
|
||||||
|
|
||||||
|
|
@ -500,22 +500,27 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
computeFSClosure(*j, livePaths, true, true, 0);
|
computeFSClosure(*j, livePaths, true, true, 0);
|
||||||
}
|
}
|
||||||
else if (store->isValidPath(*i)){
|
else if (store->isValidPath(*i)){
|
||||||
printMsg(lvlError, format("CHECK-STORE '%1%'") % *i);
|
//printMsg(lvlError, format("Live Store '%1%'") % *i);
|
||||||
Path deriver = store->queryDeriver(*i);
|
Path deriver = store->queryDeriver(*i);
|
||||||
//printMsg(lvlError, format("CHECK-STORE DRV '%1%'") % deriver);
|
|
||||||
|
|
||||||
/* Note that the deriver need not be valid (e.g., if we
|
/* Note that the deriver need not be valid (e.g., if we
|
||||||
previously ran the collector with `gcKeepDerivations'
|
previously ran the collector with `gcKeepDerivations'
|
||||||
turned off). */
|
turned off). */
|
||||||
if (deriver != "" && store->isValidPath(deriver))
|
if (deriver != "" && store->isValidPath(deriver))
|
||||||
computeFSClosure(deriver, livePaths, true, true, 0);
|
computeFSClosure(deriver, livePaths, true, true, 0);
|
||||||
|
}
|
||||||
|
else if (store->isValidStatePath(*i)){
|
||||||
|
//printMsg(lvlError, format("Live State '%1%'") % *i);
|
||||||
|
Path deriver = queryStatePathDrvTxn(noTxn, *i);
|
||||||
|
|
||||||
|
if(!store->isValidPath(deriver))
|
||||||
|
throw Error(format("deriver `%1%' of state-store component `%2%' in GC is not valid") % deriver % *i);
|
||||||
|
|
||||||
|
computeFSClosure(deriver, livePaths, true, true, 0);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
printMsg(lvlError, format("CHECK-STATE '%1%'") % *i);
|
// //throw error? ( check trunk?
|
||||||
|
}
|
||||||
//TODO also get its deriver???? for if its component is gone !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -526,12 +531,14 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
for (PathSet::iterator i = livePaths.begin();
|
for (PathSet::iterator i = livePaths.begin();
|
||||||
i != livePaths.end(); ++i)
|
i != livePaths.end(); ++i)
|
||||||
if (isDerivation(*i)) {
|
if (isDerivation(*i)) {
|
||||||
printMsg(lvlError, format("CHECK3 '%1%'") % *i);
|
//printMsg(lvlError, format("CHECK3 '%1%'") % *i);
|
||||||
Derivation drv = derivationFromPathTxn(noTxn, *i);
|
Derivation drv = derivationFromPathTxn(noTxn, *i);
|
||||||
for (DerivationOutputs::iterator j = drv.outputs.begin();
|
for (DerivationOutputs::iterator j = drv.outputs.begin();
|
||||||
j != drv.outputs.end(); ++j)
|
j != drv.outputs.end(); ++j)
|
||||||
if (store->isValidPath(j->second.path))
|
if (store->isValidPath(j->second.path))
|
||||||
computeFSClosure(j->second.path, livePaths, true, true, 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WHAT ARE (STATE) OUTPUTS ????????????
|
computeFSClosure(j->second.path, livePaths, true, true, 0); //TODO Check?
|
||||||
|
else if (store->isValidStatePath(j->second.path))
|
||||||
|
computeFSClosure(j->second.path, livePaths, true, true, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -556,7 +563,9 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
PathSet tempRootsClosed;
|
PathSet tempRootsClosed;
|
||||||
for (PathSet::iterator i = tempRoots.begin(); i != tempRoots.end(); ++i)
|
for (PathSet::iterator i = tempRoots.begin(); i != tempRoots.end(); ++i)
|
||||||
if (store->isValidPath(*i))
|
if (store->isValidPath(*i))
|
||||||
computeFSClosure(*i, tempRootsClosed, true, false, 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO .... STATE
|
computeFSClosure(*i, tempRootsClosed, true, true, 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO .... STATE
|
||||||
|
else if(store->isValidStatePath(*i))
|
||||||
|
computeFSClosure(*i, tempRootsClosed, true, true, 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO .... STATE
|
||||||
else
|
else
|
||||||
tempRootsClosed.insert(*i);
|
tempRootsClosed.insert(*i);
|
||||||
|
|
||||||
|
|
@ -569,9 +578,38 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
that is not currently in in `livePaths' or `tempRootsClosed'
|
that is not currently in in `livePaths' or `tempRootsClosed'
|
||||||
can be deleted. */
|
can be deleted. */
|
||||||
|
|
||||||
///TODO Calc get shared paths //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
/*
|
||||||
//for: livePaths, tempRootsClosed
|
* We lookup all shared paths for: livePaths, tempRootsClosed
|
||||||
PathSet sharedWith_livePaths_tempRootsClosed;
|
*/
|
||||||
|
PathSet allLiveStatePaths;
|
||||||
|
|
||||||
|
for (PathSet::iterator i = livePaths.begin(); i != livePaths.end(); ++i)
|
||||||
|
if(store->isValidStatePath(*i)){
|
||||||
|
allLiveStatePaths.insert(*i);
|
||||||
|
allLiveStatePaths = pathSets_union(getSharedWithPathSetRecTxn(noTxn, *i), allLiveStatePaths);
|
||||||
|
}
|
||||||
|
for (PathSet::iterator i = tempRootsClosed.begin(); i != tempRootsClosed.end(); ++i)
|
||||||
|
if(store->isValidStatePath(*i)){
|
||||||
|
allLiveStatePaths.insert(*i);
|
||||||
|
allLiveStatePaths = pathSets_union(getSharedWithPathSetRecTxn(noTxn, *i), allLiveStatePaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup all derivations, of all state paths, because they need to be kept for comitting
|
||||||
|
*/
|
||||||
|
PathSet allStatePathDerivations;
|
||||||
|
for (PathSet::iterator i = allLiveStatePaths.begin(); i != allLiveStatePaths.end(); ++i){
|
||||||
|
printMsg(lvlError, format("Live state path `%1%'") % *i);
|
||||||
|
|
||||||
|
//allStatePathDerivations
|
||||||
|
|
||||||
|
//GET DERIVER AND COMPUTE CLOSURE HERE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
//if (deriver != "" && store->isValidPath(deriver))
|
||||||
|
// computeFSClosure(deriver, livePaths, true, true, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Read the Nix store and state directory's to find all currently existing
|
/* Read the Nix store and state directory's to find all currently existing
|
||||||
paths. */
|
paths. */
|
||||||
|
|
@ -651,7 +689,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
|
|
||||||
if (!pathExists(*i)) continue;
|
if (!pathExists(*i)) continue;
|
||||||
|
|
||||||
printMsg(lvlInfo, format("deleting `%1%'") % *i);
|
//printMsg(lvlInfo, format("deleting `%1%'") % *i); //TODO
|
||||||
|
|
||||||
/* Okay, it's safe to delete. */
|
/* Okay, it's safe to delete. */
|
||||||
try {
|
try {
|
||||||
|
|
@ -686,21 +724,9 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
for (Paths::iterator i = statePaths.begin(); i != statePaths.end(); ++i) {
|
for (Paths::iterator i = statePaths.begin(); i != statePaths.end(); ++i) {
|
||||||
|
|
||||||
debug(format("considering deletion of state path `%1%'") % *i);
|
debug(format("considering deletion of state path `%1%'") % *i);
|
||||||
|
|
||||||
if (livePaths.find(*i) != livePaths.end()) {
|
|
||||||
if (action == gcDeleteSpecific)
|
|
||||||
throw Error(format("cannot delete state path `%1%' since it is still alive") % *i);
|
|
||||||
debug(format("live state path `%1%'") % *i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tempRootsClosed.find(*i) != tempRootsClosed.end()) {
|
if (allLiveStatePaths.find(*i) != allLiveStatePaths.end()) {
|
||||||
debug(format("temporary root `%1%'") % *i);
|
debug(format("State path `%1%' is alive (possibyly shared with another live path)") % *i);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sharedWith_livePaths_tempRootsClosed.find(*i) != sharedWith_livePaths_tempRootsClosed.end()) {
|
|
||||||
debug(format("State path `%1%' is shared with another live path") % *i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -237,11 +237,11 @@ LocalStore::LocalStore(bool reserveSpace)
|
||||||
throw Error(format("`%1%' is corrupt") % schemaFN);
|
throw Error(format("`%1%' is corrupt") % schemaFN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curSchema > nixSchemaVersion && curSchema != 4) //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MAJOR HACK, I SHOULD MERGE WITH THE TRUNK
|
if (curSchema > nixSchemaVersion)
|
||||||
throw Error(format("current Nix store schema is version %1%, but I only support %2%")
|
throw Error(format("current Nix store schema is version %1%, but I only support %2%")
|
||||||
% curSchema % nixSchemaVersion);
|
% curSchema % nixSchemaVersion);
|
||||||
|
|
||||||
if (curSchema < nixSchemaVersion && curSchema != 4) { //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MAJOR HACK, I SHOULD MERGE WITH THE TRUNK
|
if (curSchema < nixSchemaVersion) {
|
||||||
if (curSchema <= 1)
|
if (curSchema <= 1)
|
||||||
upgradeStore07();
|
upgradeStore07();
|
||||||
if (curSchema == 2)
|
if (curSchema == 2)
|
||||||
|
|
@ -756,14 +756,12 @@ static Path queryDeriver(const Transaction & txn, const Path & storePath)
|
||||||
previously ran the garbage collector with `gcKeepDerivations'
|
previously ran the garbage collector with `gcKeepDerivations'
|
||||||
turned off). */
|
turned off). */
|
||||||
if(deriver == ""){
|
if(deriver == ""){
|
||||||
printMsg(lvlTalkative, format("WARNING: Path '%1%' has no deriver anymore") % storePath);
|
//printMsg(lvlTalkative, format("WARNING: Path '%1%' has no deriver anymore") % storePath);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
if (isStateComponentTxn(txn, storePath))
|
||||||
//Derivation drv = derivationFromPathTxn(txn, deriver); //We cant do this (at this point) since the drv might not exist ....
|
throw Error(format("This path `%1%' is a store-state path, u should use queryDerivers instead of queryDeriver") % storePath);
|
||||||
//if (isStateDrv(drv))
|
|
||||||
// throw Error(format("This deriver `%1%' is a state deriver, u should use queryDerivers instead of queryDeriver") % deriver);
|
|
||||||
|
|
||||||
if (b)
|
if (b)
|
||||||
return deriver;
|
return deriver;
|
||||||
|
|
@ -892,9 +890,9 @@ Hash LocalStore::queryPathHash(const Path & path)
|
||||||
return queryHash(noTxn, path);
|
return queryHash(noTxn, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Path queryStatePathDrvTxn(const Transaction & txn, const Path & statePath) //TODO !!!!!!!!!!!!!!!!!!!!!! A STATEPATH CAN HAVE MORE THEN JUST ONE DRV!!!!!!!!!!!!!!!!!!!!!!!
|
Path queryStatePathDrvTxn(const Transaction & txn, const Path & statePath)
|
||||||
{ //SOLUTION: make dbValidStatePaths :: statepath --> storepath
|
{
|
||||||
string s; //query includes username and identifier ....??
|
string s;
|
||||||
nixDB.queryString(txn, dbValidStatePaths, statePath, s);
|
nixDB.queryString(txn, dbValidStatePaths, statePath, s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -964,7 +962,7 @@ void registerValidPaths(const Transaction & txn, const ValidPathInfos & infos)
|
||||||
setDeriver(txn, i->path, i->deriver);
|
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 ....
|
//State is already linked to a drvpath in dbValidStatePaths
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1038,7 +1036,7 @@ Path LocalStore::addToStore(const Path & _srcPath, bool fixed,
|
||||||
canonicalisePathMetaData(dstPath);
|
canonicalisePathMetaData(dstPath);
|
||||||
|
|
||||||
Transaction txn(nixDB);
|
Transaction txn(nixDB);
|
||||||
registerValidPath(txn, dstPath, h, PathSet(), PathSet(), "", -1); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!! CHECK (probabyly ok?)
|
registerValidPath(txn, dstPath, h, PathSet(), PathSet(), "", 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!! CHECK (probabyly ok?)
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1214,7 +1212,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
|
||||||
|
|
||||||
PathSet references = readStorePaths(hashAndReadSource);
|
PathSet references = readStorePaths(hashAndReadSource);
|
||||||
|
|
||||||
//TODO TODO also ..??!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
//TODO TODO also ..??!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
PathSet stateReferences;
|
PathSet stateReferences;
|
||||||
|
|
||||||
Path deriver = readString(hashAndReadSource);
|
Path deriver = readString(hashAndReadSource);
|
||||||
|
|
@ -1635,7 +1633,7 @@ bool querySolidStateReferencesTxn(const Transaction & txn, const Path & statePat
|
||||||
return notempty;
|
return notempty;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unShareStateTxn(const Transaction & txn, const Path & path, const bool branch, const bool restoreOld) //TODO ADD BOOL YES/NO TO RESTORE OLD STATE (LAST REV.)
|
void unShareStateTxn(const Transaction & txn, const Path & path, const bool branch, const bool restoreOld)
|
||||||
{
|
{
|
||||||
//Check if is statePath
|
//Check if is statePath
|
||||||
if(!isValidStatePathTxn(txn, path))
|
if(!isValidStatePathTxn(txn, path))
|
||||||
|
|
@ -1785,7 +1783,7 @@ void setStateStateReferencesTxn(const Transaction & txn, const Path & statePath,
|
||||||
setStateReferences(nixDB, txn, dbStateStateReferences, dbStateRevisions, statePath, references, revision, timestamp);
|
setStateReferences(nixDB, txn, dbStateStateReferences, dbStateRevisions, statePath, references, revision, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Lookups which statePaths directy share (point to) statePath
|
//Lookup which statePaths directy share (point to) statePath
|
||||||
PathSet getDirectlySharedWithPathSetTxn(const Transaction & txn, const Path & statePath)
|
PathSet getDirectlySharedWithPathSetTxn(const Transaction & txn, const Path & statePath)
|
||||||
{
|
{
|
||||||
PathSet statePaths;
|
PathSet statePaths;
|
||||||
|
|
@ -1822,6 +1820,7 @@ PathSet getSharedWithPathSetRecTxn_private(const Transaction & txn, const Path &
|
||||||
return statePaths;
|
return statePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Lookup recursively which statePaths (in)directy share (point to) statePath
|
||||||
PathSet getSharedWithPathSetRecTxn(const Transaction & txn, const Path & statePath)
|
PathSet getSharedWithPathSetRecTxn(const Transaction & txn, const Path & statePath)
|
||||||
{
|
{
|
||||||
//To no shared state path
|
//To no shared state path
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,7 @@ public:
|
||||||
|
|
||||||
/* TODO */
|
/* TODO */
|
||||||
virtual void unShareState(const Path & path, const bool branch, const bool restoreOld) = 0;
|
virtual void unShareState(const Path & path, const bool branch, const bool restoreOld) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -704,10 +704,15 @@ static void processConnection()
|
||||||
try {
|
try {
|
||||||
int oppp = readInt(from);
|
int oppp = readInt(from);
|
||||||
op = (WorkerOp) oppp;
|
op = (WorkerOp) oppp;
|
||||||
|
|
||||||
|
/* Use for debugging*/
|
||||||
|
/*
|
||||||
if(oppp == 14){
|
if(oppp == 14){
|
||||||
printMsg(lvlError, format("Sleeping 10"));
|
printMsg(lvlError, format("Sleeping 10"));
|
||||||
sleep(10);
|
sleep(10);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
} catch (EndOfFile & e) {
|
} catch (EndOfFile & e) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue