mirror of
https://github.com/NixOS/nix.git
synced 2025-11-26 04:00:59 +01:00
Garbage collection - gcKeepDerivations bug
This commit is contained in:
parent
ef37776094
commit
d8e9dc2775
4 changed files with 73 additions and 44 deletions
|
|
@ -2396,10 +2396,8 @@ static bool working = false;
|
||||||
Worker::Worker()
|
Worker::Worker()
|
||||||
{
|
{
|
||||||
/* Debugging: prevent recursive workers. */
|
/* Debugging: prevent recursive workers. */
|
||||||
printMsg(lvlError, format("Before abort '%1%'") % working);
|
|
||||||
if (working)
|
if (working)
|
||||||
abort();
|
abort();
|
||||||
printMsg(lvlError, format("After abort"));
|
|
||||||
working = true;
|
working = true;
|
||||||
nrChildren = 0;
|
nrChildren = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -437,7 +437,7 @@ Paths topoSortPaths(const PathSet & paths)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete, //TODO ? statePathsToDelete
|
||||||
bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed)
|
bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed)
|
||||||
{
|
{
|
||||||
result.clear();
|
result.clear();
|
||||||
|
|
@ -448,6 +448,8 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
bool gcKeepDerivations =
|
bool gcKeepDerivations =
|
||||||
queryBoolSetting("gc-keep-derivations", true);
|
queryBoolSetting("gc-keep-derivations", true);
|
||||||
|
|
||||||
|
printMsg(lvlError, format("gcKeepOutputs %1% gcKeepDerivations: %2%") % gcKeepOutputs % gcKeepDerivations);
|
||||||
|
|
||||||
/* 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. */
|
||||||
|
|
@ -485,8 +487,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
printMsg(lvlError, format("STAGE X"));
|
printMsg(lvlError, format("STAGE X"));
|
||||||
|
|
||||||
if (gcKeepDerivations) {
|
if (gcKeepDerivations) {
|
||||||
for (PathSet::iterator i = livePaths.begin();
|
for (PathSet::iterator i = livePaths.begin(); i != livePaths.end(); ++i)
|
||||||
i != livePaths.end(); ++i)
|
|
||||||
{
|
{
|
||||||
if (store->isStateComponent(*i)){
|
if (store->isStateComponent(*i)){
|
||||||
//printMsg(lvlError, format("Live state store '%1%'") % *i);
|
//printMsg(lvlError, format("Live state store '%1%'") % *i);
|
||||||
|
|
@ -513,14 +514,12 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
//printMsg(lvlError, format("Live State '%1%'") % *i);
|
//printMsg(lvlError, format("Live State '%1%'") % *i);
|
||||||
Path deriver = queryStatePathDrvTxn(noTxn, *i);
|
Path deriver = queryStatePathDrvTxn(noTxn, *i);
|
||||||
|
|
||||||
|
//TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TODO put back on
|
||||||
if(!store->isValidPath(deriver))
|
if(!store->isValidPath(deriver))
|
||||||
throw Error(format("deriver `%1%' of state-store component `%2%' in GC is not valid") % deriver % *i);
|
{} // throw Error(format("deriver `%1%' of state-store component `%2%' in GC is not valid") % deriver % *i);
|
||||||
|
else //TODO !!!!!!!!!!!!!! REMOVE ELSE
|
||||||
computeFSClosure(deriver, livePaths, true, true, 0);
|
computeFSClosure(deriver, livePaths, true, true, 0);
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
// //throw error? ( check trunk?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -528,15 +527,14 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
|
|
||||||
if (gcKeepOutputs) {
|
if (gcKeepOutputs) {
|
||||||
/* Hmz, identical to storePathRequisites in nix-store. */
|
/* Hmz, identical to storePathRequisites in nix-store. */
|
||||||
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 Check?
|
computeFSClosure(j->second.path, livePaths, true, true, 0);
|
||||||
else if (store->isValidStatePath(j->second.path))
|
else if (store->isValidStatePath(j->second.path))
|
||||||
computeFSClosure(j->second.path, livePaths, true, true, 0);
|
computeFSClosure(j->second.path, livePaths, true, true, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -563,9 +561,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, true, 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO .... STATE
|
computeFSClosure(*i, tempRootsClosed, true, true, 0);
|
||||||
else if(store->isValidStatePath(*i))
|
else if(store->isValidStatePath(*i))
|
||||||
computeFSClosure(*i, tempRootsClosed, true, true, 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO .... STATE
|
computeFSClosure(*i, tempRootsClosed, true, true, 0);
|
||||||
else
|
else
|
||||||
tempRootsClosed.insert(*i);
|
tempRootsClosed.insert(*i);
|
||||||
|
|
||||||
|
|
@ -600,17 +598,17 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
PathSet allStatePathDerivations;
|
PathSet allStatePathDerivations;
|
||||||
for (PathSet::iterator i = allLiveStatePaths.begin(); i != allLiveStatePaths.end(); ++i){
|
for (PathSet::iterator i = allLiveStatePaths.begin(); i != allLiveStatePaths.end(); ++i){
|
||||||
printMsg(lvlError, format("Live state path `%1%'") % *i);
|
printMsg(lvlError, format("Live state path `%1%'") % *i);
|
||||||
|
Path stateDrv = queryStatePathDrvTxn(noTxn, *i);
|
||||||
|
allStatePathDerivations.insert(stateDrv);
|
||||||
|
//printMsg(lvlError, format("Live state path drv `%1%'") % stateDrv);
|
||||||
|
|
||||||
//allStatePathDerivations
|
//TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TODO put back on
|
||||||
|
if(!store->isValidPath(stateDrv))
|
||||||
|
{} // throw Error(format("deriver `%1%' of state component `%2%' in GC is not valid") % stateDrv % *i);
|
||||||
|
|
||||||
//GET DERIVER AND COMPUTE CLOSURE HERE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
// computeFSClosure(stateDrv, livePaths, true, true, 0); //TODO .................. should we do this ?????????????
|
||||||
//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. */
|
||||||
PathSet storePathSet;
|
PathSet storePathSet;
|
||||||
|
|
@ -631,7 +629,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
for (PathSet::iterator i = pathsToDelete.begin();
|
for (PathSet::iterator i = pathsToDelete.begin();
|
||||||
i != pathsToDelete.end(); ++i)
|
i != pathsToDelete.end(); ++i)
|
||||||
{
|
{
|
||||||
assertStorePath(*i); //TODO ASSERTSTATEPATH !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
assertStorePath(*i); //TODO ASSERTSTATEPATH, we for now we have no arg statePathsToDelete
|
||||||
storePathSet.insert(*i);
|
storePathSet.insert(*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -660,6 +658,11 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allStatePathDerivations.find(*i) != allStatePathDerivations.end()) {
|
||||||
|
debug(format("Keeping statePath derivation `%1%'") % *i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
debug(format("dead path `%1%'") % *i);
|
debug(format("dead path `%1%'") % *i);
|
||||||
result.insert(*i);
|
result.insert(*i);
|
||||||
|
|
||||||
|
|
@ -689,12 +692,12 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
|
|
||||||
if (!pathExists(*i)) continue;
|
if (!pathExists(*i)) continue;
|
||||||
|
|
||||||
//printMsg(lvlInfo, format("deleting `%1%'") % *i); //TODO
|
printMsg(lvlInfo, format("deleting store path `%1%'") % *i);
|
||||||
|
|
||||||
/* Okay, it's safe to delete. */
|
/* Okay, it's safe to delete. */
|
||||||
try {
|
try {
|
||||||
unsigned long long freed;
|
unsigned long long freed;
|
||||||
//deleteFromStore(*i, freed); //TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PUT BACK ON
|
deleteFromStore(*i, freed);
|
||||||
bytesFreed += freed;
|
bytesFreed += freed;
|
||||||
} catch (PathInUse & e) {
|
} catch (PathInUse & e) {
|
||||||
printMsg(lvlError, format("warning: %1%") % e.msg());
|
printMsg(lvlError, format("warning: %1%") % e.msg());
|
||||||
|
|
@ -718,9 +721,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
for (PathSet::iterator i = statePathSet.begin(); i != statePathSet.end(); ++i)
|
for (PathSet::iterator i = statePathSet.begin(); i != statePathSet.end(); ++i)
|
||||||
statePaths.push_back(*i);
|
statePaths.push_back(*i);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -740,7 +741,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
|
|
||||||
if (action == gcDeleteDead || action == gcDeleteSpecific) {
|
if (action == gcDeleteDead || action == gcDeleteSpecific) {
|
||||||
|
|
||||||
//TODO !!!!!!!!!!!!!!!!!!!!!! state locks
|
//TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! state locks
|
||||||
/*
|
/*
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
AutoCloseFD fdLock;
|
AutoCloseFD fdLock;
|
||||||
|
|
@ -767,7 +768,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
/* Okay, it's safe to delete. */
|
/* Okay, it's safe to delete. */
|
||||||
try {
|
try {
|
||||||
unsigned long long freed;
|
unsigned long long freed;
|
||||||
//deleteFromState(*i, freed); //TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PUT BACK ON
|
deleteFromState(*i, freed);
|
||||||
bytesFreed += freed;
|
bytesFreed += freed;
|
||||||
} catch (PathInUse & e) {
|
} catch (PathInUse & e) {
|
||||||
printMsg(lvlError, format("warning: %1%") % e.msg());
|
printMsg(lvlError, format("warning: %1%") % e.msg());
|
||||||
|
|
|
||||||
|
|
@ -972,21 +972,49 @@ static void invalidatexPath(Transaction & txn, const Path & path, const bool com
|
||||||
|
|
||||||
/* Clear the `references' entry for this path, as well as the
|
/* Clear the `references' entry for this path, as well as the
|
||||||
inverse `referrers' entries, and the `derivers' entry. */
|
inverse `referrers' entries, and the `derivers' entry. */
|
||||||
|
if(component_or_state){
|
||||||
if(component_or_state)
|
|
||||||
setReferences(txn, path, PathSet(), PathSet(), 0); //This is a store path so the revision doenst matter
|
setReferences(txn, path, PathSet(), PathSet(), 0); //This is a store path so the revision doenst matter
|
||||||
else
|
nixDB.delPair(txn, dbDerivers, path);
|
||||||
setReferences(txn, path, PathSet(), PathSet(), 0); //For now.... we only delete clear references for the new revision (TODO !!!!!!!!!!!!!!!! CHECK IF WE REALLY SET IT FOR A NEW OR LAST REVISION)
|
|
||||||
|
|
||||||
nixDB.delPair(txn, dbDerivers, path);
|
|
||||||
|
|
||||||
if(component_or_state)
|
|
||||||
nixDB.delPair(txn, dbValidPaths, path);
|
nixDB.delPair(txn, dbValidPaths, path);
|
||||||
else
|
|
||||||
|
//if is store-state
|
||||||
|
if(isStateComponentTxn(txn, path)){
|
||||||
|
|
||||||
|
//delete all references
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nixDB.delPair(txn, dbStateInfo, path); //We (may) need to delete if this key if path is a state-store path
|
||||||
|
|
||||||
|
|
||||||
|
//TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
//For now.... we only delete clear references for the new revision (TODO !!!!!!!!!!!!!!!! CHECK IF WE REALLY SET IT FOR A NEW OR LAST REVISION)
|
||||||
|
setReferences(txn, path, PathSet(), PathSet(), 0);
|
||||||
|
nixDB.delPair(txn, dbDerivers, path);
|
||||||
nixDB.delPair(txn, dbValidStatePaths, path);
|
nixDB.delPair(txn, dbValidStatePaths, path);
|
||||||
|
|
||||||
if(component_or_state)
|
//TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! also clear
|
||||||
nixDB.delPair(txn, dbStateInfo, path); //We (may) need to delete if this key if path is a state-store path
|
|
||||||
|
//state-counters
|
||||||
|
///nix/state/pspj0srf5vh6qhwa1i11swqai9lnk581-hellohardcodedstateworld-1.0-test/log/
|
||||||
|
//0
|
||||||
|
|
||||||
|
//revisions
|
||||||
|
///nix/state/4ngfrqhfj7n28p334ajcji9zrdrbdgaw-hellohardcodedstateworld-1.0-test
|
||||||
|
//1
|
||||||
|
///nix/state/aacs4qpi9jzg4vmhj09d0ichframh22x-hellohardcodedstateworld-1.0-test-KEY-16
|
||||||
|
|
||||||
|
//comments
|
||||||
|
// /nix/state/ryxrs01hkxyk4x96i58pc7n54y1gyhmb-hellostateworld-1.0-test-KEY-1
|
||||||
|
// \0a\00\00\001187346592\17\00\00\00Initial build revision.
|
||||||
|
|
||||||
|
//stateSnapshots
|
||||||
|
//nix/state/54crxisppkqy7929dysqyjdiladahrw7-hellohardcodedstateworld-1.0-test-KEY-1189076361
|
||||||
|
//\01\00\00\000\0a\00\00\001189076361\01\00\00\000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1312,7 +1340,6 @@ void deleteXFromStore(const Path & _path, unsigned long long & bytesFreed, const
|
||||||
if (*i != path && isValidPathTxn(txn, *i))
|
if (*i != path && isValidPathTxn(txn, *i))
|
||||||
throw PathInUse(format("cannot delete %3% path `%1%' because it is in use by state path `%2%'") % path % *i % (component_or_state ? "store" : "state"));
|
throw PathInUse(format("cannot delete %3% path `%1%' because it is in use by state path `%2%'") % path % *i % (component_or_state ? "store" : "state"));
|
||||||
|
|
||||||
|
|
||||||
if(component_or_state)
|
if(component_or_state)
|
||||||
invalidateStorePath(txn, path);
|
invalidateStorePath(txn, path);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -761,6 +761,9 @@ static void installDerivations(Globals & globals,
|
||||||
|
|
||||||
//**********************
|
//**********************
|
||||||
|
|
||||||
|
|
||||||
|
//TODO !!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
//Remove the external links when a user uninstalls
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue