* GC option `--max-atime' that specifies an upper limit to the last

accessed time of paths that may be deleted.  Anything more recently
  used won't be deleted.  The time is specified in time_t,
  e.g. seconds since 1970-01-01 00:00:00 UTC; use `date +%s' to
  convert to time_t from the command line. 

  Example: to delete everything that hasn't been used in the last two
  months:

  $ nix-store --gc -v --max-atime $(date +%s -d "2 months ago")
This commit is contained in:
Eelco Dolstra 2008-09-17 14:52:35 +00:00
parent 4af2fdba6d
commit f32fef1b07
4 changed files with 24 additions and 7 deletions

View file

@ -531,10 +531,11 @@ void LocalStore::gcPathRecursive(const GCOptions & options,
startNest(nest, lvlDebug, format("looking at `%1%'") % path);
/* Delete all the referrers first. They must be garbage too,
since if they were in the closure of some live path, then this
path would also be in the closure. Note that
deleteFromStore() below still makes sure that the referrer set
has become empty, just in case. */
since if they were live, then the current path would also be
live. Note that deleteFromStore() below still makes sure that
the referrer set has become empty, just in case. (However that
doesn't guard against deleting top-level paths that are only
reachable from GC roots.) */
PathSet referrers;
if (isValidPath(path))
queryReferrers(path, referrers);
@ -571,7 +572,7 @@ struct CachingAtimeComparator : public std::binary_function<Path, Path, bool>
string showTime(const string & format, time_t t)
{
char s[128];
strftime(s, sizeof s, format.c_str(), gmtime(&t));
strftime(s, sizeof s, format.c_str(), localtime(&t));
return string(s);
}
@ -766,7 +767,12 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
while (!prioQueue.empty()) {
checkInterrupt();
Path path = prioQueue.top(); prioQueue.pop();
printMsg(lvlInfo, format("deleting `%1%' (last accessed %2%)") % path % showTime("%F %H:%M:%S", atimeComp.cache[path]));
if (options.maxAtime != (time_t) -1 &&
atimeComp.lookup(path) > options.maxAtime)
continue;
printMsg(lvlInfo, format("deleting `%1%' (last accessed %2%)") % path % showTime("%F %H:%M:%S", atimeComp.lookup(path)));
PathSet references;
if (isValidPath(path)) references = queryReferencesNoSelf(path);

View file

@ -15,6 +15,7 @@ GCOptions::GCOptions()
maxFreed = ULLONG_MAX;
maxLinks = 0;
useAtime = false;
maxAtime = (time_t) -1;
}

View file

@ -75,6 +75,10 @@ struct GCOptions
atime. */
bool useAtime;
/* Do not delete paths newer than `maxAtime'. -1 means no age
limit. */
time_t maxAtime;
GCOptions();
};

View file

@ -531,8 +531,14 @@ static void opGC(Strings opFlags, Strings opArgs)
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 if (*i == "--use-atime") options.useAtime = true;
else if (*i == "--max-atime") {
options.useAtime = true;
options.maxAtime = getIntArg(*i, i, opFlags.end());
}
else throw UsageError(format("bad sub-operation `%1%' in GC") % *i);
if (!opArgs.empty()) throw UsageError("no arguments expected");
PrintFreed freed(options.action == GCOptions::gcDeleteDead, results);
store->collectGarbage(options, results);
@ -745,7 +751,7 @@ void run(Strings args)
indirectRoot = true;
else if (arg[0] == '-') {
opFlags.push_back(arg);
if (arg == "--max-freed" || arg == "--max-links") { /* !!! hack */
if (arg == "--max-freed" || arg == "--max-links" || arg == "--max-atime") { /* !!! hack */
if (i != args.end()) opFlags.push_back(*i++);
}
}