* 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)
|
Strings::iterator & i, const Strings::iterator & end)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
|
|
|
@ -26,6 +26,9 @@ namespace nix {
|
||||||
Path makeRootName(const Path & gcRoot, int & counter);
|
Path makeRootName(const Path & gcRoot, int & counter);
|
||||||
void printGCWarning();
|
void printGCWarning();
|
||||||
|
|
||||||
|
unsigned int getIntArg(const string & opt,
|
||||||
|
Strings::iterator & i, const Strings::iterator & end);
|
||||||
|
|
||||||
/* Whether we're running setuid. */
|
/* Whether we're running setuid. */
|
||||||
extern bool setuidMode;
|
extern bool setuidMode;
|
||||||
|
|
||||||
|
|
|
@ -439,6 +439,9 @@ Paths topoSortPaths(const PathSet & paths)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct GCLimitReached { };
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::tryToDelete(const GCOptions & options, GCResults & results,
|
void LocalStore::tryToDelete(const GCOptions & options, GCResults & results,
|
||||||
const PathSet & livePaths, const PathSet & tempRootsClosed, PathSet & done,
|
const PathSet & livePaths, const PathSet & tempRootsClosed, PathSet & done,
|
||||||
const Path & path)
|
const Path & path)
|
||||||
|
@ -512,6 +515,21 @@ void LocalStore::tryToDelete(const GCOptions & options, GCResults & results,
|
||||||
results.bytesFreed += bytesFreed;
|
results.bytesFreed += bytesFreed;
|
||||||
results.blocksFreed += blocksFreed;
|
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__
|
#ifndef __CYGWIN__
|
||||||
if (fdLock != -1)
|
if (fdLock != -1)
|
||||||
/* Write token to stale (deleted) lock file. */
|
/* Write token to stale (deleted) lock file. */
|
||||||
|
@ -650,8 +668,11 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
||||||
: format("deleting garbage..."));
|
: format("deleting garbage..."));
|
||||||
|
|
||||||
PathSet done;
|
PathSet done;
|
||||||
foreach (PathSet::iterator, i, storePaths)
|
try {
|
||||||
tryToDelete(options, results, livePaths, tempRootsClosed, done, *i);
|
foreach (PathSet::iterator, i, storePaths)
|
||||||
|
tryToDelete(options, results, livePaths, tempRootsClosed, done, *i);
|
||||||
|
} catch (GCLimitReached & e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,21 @@
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
|
GCOptions::GCOptions()
|
||||||
|
{
|
||||||
|
action = gcDeleteDead;
|
||||||
|
ignoreLiveness = false;
|
||||||
|
maxFreed = ULLONG_MAX;
|
||||||
|
maxLinks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool StoreAPI::hasSubstitutes(const Path & path)
|
bool StoreAPI::hasSubstitutes(const Path & path)
|
||||||
{
|
{
|
||||||
PathSet paths = querySubstitutablePaths();
|
PathSet paths = querySubstitutablePaths();
|
||||||
|
|
|
@ -60,16 +60,10 @@ struct GCOptions
|
||||||
unsigned long long maxFreed;
|
unsigned long long maxFreed;
|
||||||
|
|
||||||
/* Stop after the number of hard links to the Nix store directory
|
/* 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;
|
unsigned int maxLinks;
|
||||||
|
|
||||||
GCOptions()
|
GCOptions();
|
||||||
{
|
|
||||||
action = gcDeleteDead;
|
|
||||||
ignoreLiveness = false;
|
|
||||||
maxFreed = ULLONG_MAX;
|
|
||||||
maxLinks = UINT_MAX;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -528,6 +528,8 @@ static void opGC(Strings opFlags, Strings opArgs)
|
||||||
else if (*i == "--print-live") options.action = GCOptions::gcReturnLive;
|
else if (*i == "--print-live") options.action = GCOptions::gcReturnLive;
|
||||||
else if (*i == "--print-dead") options.action = GCOptions::gcReturnDead;
|
else if (*i == "--print-dead") options.action = GCOptions::gcReturnDead;
|
||||||
else if (*i == "--delete") options.action = GCOptions::gcDeleteDead;
|
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);
|
else throw UsageError(format("bad sub-operation `%1%' in GC") % *i);
|
||||||
|
|
||||||
PrintFreed freed(
|
PrintFreed freed(
|
||||||
|
@ -744,8 +746,12 @@ void run(Strings args)
|
||||||
}
|
}
|
||||||
else if (arg == "--indirect")
|
else if (arg == "--indirect")
|
||||||
indirectRoot = true;
|
indirectRoot = true;
|
||||||
else if (arg[0] == '-')
|
else if (arg[0] == '-') {
|
||||||
opFlags.push_back(arg);
|
opFlags.push_back(arg);
|
||||||
|
if (arg == "--max-freed" || arg == "--max-links") { /* !!! hack */
|
||||||
|
if (i != args.end()) opFlags.push_back(*i++);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
opArgs.push_back(arg);
|
opArgs.push_back(arg);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue