* 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:
Eelco Dolstra 2008-06-18 14:20:16 +00:00
parent a8f3b02092
commit d3aa183beb
6 changed files with 47 additions and 12 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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) {
}
}

View file

@ -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();

View file

@ -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();
};

View file

@ -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);