* Garbage collector: option `--max-freed' to stop after at least N
bytes have been freed, `--max-links' to stop when the Nix store directory has fewer than N hard links (the latter being important for very large Nix stores on filesystems with a 32000 subdirectories limit).
This commit is contained in:
parent
a8f3b02092
commit
d3aa183beb
6 changed files with 47 additions and 12 deletions
|
@ -58,7 +58,7 @@ static void setLogType(string lt)
|
|||
}
|
||||
|
||||
|
||||
static unsigned int getIntArg(const string & opt,
|
||||
unsigned int getIntArg(const string & opt,
|
||||
Strings::iterator & i, const Strings::iterator & end)
|
||||
{
|
||||
++i;
|
||||
|
|
|
@ -26,6 +26,9 @@ namespace nix {
|
|||
Path makeRootName(const Path & gcRoot, int & counter);
|
||||
void printGCWarning();
|
||||
|
||||
unsigned int getIntArg(const string & opt,
|
||||
Strings::iterator & i, const Strings::iterator & end);
|
||||
|
||||
/* Whether we're running setuid. */
|
||||
extern bool setuidMode;
|
||||
|
||||
|
|
|
@ -439,6 +439,9 @@ Paths topoSortPaths(const PathSet & paths)
|
|||
}
|
||||
|
||||
|
||||
struct GCLimitReached { };
|
||||
|
||||
|
||||
void LocalStore::tryToDelete(const GCOptions & options, GCResults & results,
|
||||
const PathSet & livePaths, const PathSet & tempRootsClosed, PathSet & done,
|
||||
const Path & path)
|
||||
|
@ -512,6 +515,21 @@ void LocalStore::tryToDelete(const GCOptions & options, GCResults & results,
|
|||
results.bytesFreed += bytesFreed;
|
||||
results.blocksFreed += blocksFreed;
|
||||
|
||||
if (results.bytesFreed > options.maxFreed) {
|
||||
printMsg(lvlInfo, format("deleted more than %1% bytes; stopping") % options.maxFreed);
|
||||
throw GCLimitReached();
|
||||
}
|
||||
|
||||
if (options.maxLinks) {
|
||||
struct stat st;
|
||||
if (stat(nixStore.c_str(), &st) == -1)
|
||||
throw SysError(format("statting `%1%'") % nixStore);
|
||||
if (st.st_nlink < options.maxLinks) {
|
||||
printMsg(lvlInfo, format("link count on the store has dropped below %1%; stopping") % options.maxLinks);
|
||||
throw GCLimitReached();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
if (fdLock != -1)
|
||||
/* Write token to stale (deleted) lock file. */
|
||||
|
@ -650,8 +668,11 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
: format("deleting garbage..."));
|
||||
|
||||
PathSet done;
|
||||
foreach (PathSet::iterator, i, storePaths)
|
||||
tryToDelete(options, results, livePaths, tempRootsClosed, done, *i);
|
||||
try {
|
||||
foreach (PathSet::iterator, i, storePaths)
|
||||
tryToDelete(options, results, livePaths, tempRootsClosed, done, *i);
|
||||
} catch (GCLimitReached & e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,10 +2,21 @@
|
|||
#include "globals.hh"
|
||||
#include "util.hh"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
GCOptions::GCOptions()
|
||||
{
|
||||
action = gcDeleteDead;
|
||||
ignoreLiveness = false;
|
||||
maxFreed = ULLONG_MAX;
|
||||
maxLinks = 0;
|
||||
}
|
||||
|
||||
|
||||
bool StoreAPI::hasSubstitutes(const Path & path)
|
||||
{
|
||||
PathSet paths = querySubstitutablePaths();
|
||||
|
|
|
@ -60,16 +60,10 @@ struct GCOptions
|
|||
unsigned long long maxFreed;
|
||||
|
||||
/* Stop after the number of hard links to the Nix store directory
|
||||
has dropped to at least `maxLinks'. */
|
||||
has dropped below `maxLinks'. */
|
||||
unsigned int maxLinks;
|
||||
|
||||
GCOptions()
|
||||
{
|
||||
action = gcDeleteDead;
|
||||
ignoreLiveness = false;
|
||||
maxFreed = ULLONG_MAX;
|
||||
maxLinks = UINT_MAX;
|
||||
}
|
||||
GCOptions();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -528,6 +528,8 @@ static void opGC(Strings opFlags, Strings opArgs)
|
|||
else if (*i == "--print-live") options.action = GCOptions::gcReturnLive;
|
||||
else if (*i == "--print-dead") options.action = GCOptions::gcReturnDead;
|
||||
else if (*i == "--delete") options.action = GCOptions::gcDeleteDead;
|
||||
else if (*i == "--max-freed") options.maxFreed = getIntArg(*i, i, opFlags.end());
|
||||
else if (*i == "--max-links") options.maxLinks = getIntArg(*i, i, opFlags.end());
|
||||
else throw UsageError(format("bad sub-operation `%1%' in GC") % *i);
|
||||
|
||||
PrintFreed freed(
|
||||
|
@ -744,8 +746,12 @@ void run(Strings args)
|
|||
}
|
||||
else if (arg == "--indirect")
|
||||
indirectRoot = true;
|
||||
else if (arg[0] == '-')
|
||||
else if (arg[0] == '-') {
|
||||
opFlags.push_back(arg);
|
||||
if (arg == "--max-freed" || arg == "--max-links") { /* !!! hack */
|
||||
if (i != args.end()) opFlags.push_back(*i++);
|
||||
}
|
||||
}
|
||||
else
|
||||
opArgs.push_back(arg);
|
||||
|
||||
|
|
Loading…
Reference in a new issue