* Simplify deleting .lock files in /nix/store: just don't delete them

if they belong a path that's currently being built.  This gets rid
  of some Cygwin-specific code.
This commit is contained in:
Eelco Dolstra 2008-12-12 17:03:18 +00:00
parent ac36c6cd44
commit 0008b0006d
4 changed files with 38 additions and 34 deletions

View file

@ -476,23 +476,6 @@ void LocalStore::gcPath(const GCOptions & options, GCResults & results,
if (!pathExists(path)) return;
#ifndef __CYGWIN__
AutoCloseFD fdLock;
/* Only delete a lock file if we can acquire a write lock on it.
That means that it's either stale, or the process that created
it hasn't locked it yet. In the latter case the other process
will detect that we deleted the lock, and retry (see
pathlocks.cc). */
if (path.size() >= 5 && string(path, path.size() - 5) == ".lock") {
fdLock = openLockFile(path, false);
if (fdLock != -1 && !lockFile(fdLock, ltWrite, false)) {
debug(format("skipping active lock `%1%'") % path);
return;
}
}
#endif
/* Okay, it's safe to delete. */
unsigned long long bytesFreed, blocksFreed;
deleteFromStore(path, bytesFreed, blocksFreed);
@ -513,12 +496,6 @@ void LocalStore::gcPath(const GCOptions & options, GCResults & results,
throw GCLimitReached();
}
}
#ifndef __CYGWIN__
if (fdLock != -1)
/* Write token to stale (deleted) lock file. */
writeFull(fdLock, (const unsigned char *) "d", 1);
#endif
}
@ -569,7 +546,7 @@ struct CachingAtimeComparator : public std::binary_function<Path, Path, bool>
};
string showTime(const string & format, time_t t)
static string showTime(const string & format, time_t t)
{
char s[128];
strftime(s, sizeof s, format.c_str(), localtime(&t));
@ -577,6 +554,21 @@ string showTime(const string & format, time_t t)
}
static bool isLive(const Path & path, const PathSet & livePaths,
const PathSet & tempRoots, const PathSet & tempRootsClosed)
{
if (livePaths.find(path) != livePaths.end() ||
tempRootsClosed.find(path) != tempRootsClosed.end()) return true;
/* A lock file belonging to a path that we're building right
now isn't garbage. */
if (hasSuffix(path, ".lock") && tempRoots.find(string(path, 0, path.size() - 5)) != tempRoots.end())
return true;
return false;
}
void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
{
bool gcKeepOutputs =
@ -691,9 +683,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
Paths entries = readDirectory(nixStore);
foreach (Paths::iterator, i, entries) {
Path path = canonPath(nixStore + "/" + *i);
if (livePaths.find(path) == livePaths.end() &&
tempRootsClosed.find(path) == tempRootsClosed.end())
storePaths.insert(path);
if (!isLive(path, livePaths, tempRoots, tempRootsClosed)) storePaths.insert(path);
}
}
@ -701,10 +691,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
foreach (PathSet::iterator, i, options.pathsToDelete) {
assertStorePath(*i);
storePaths.insert(*i);
if (livePaths.find(*i) != livePaths.end())
if (isLive(*i, livePaths, tempRoots, tempRootsClosed))
throw Error(format("cannot delete path `%1%' since it is still alive") % *i);
if (tempRootsClosed.find(*i) != tempRootsClosed.end())
throw Error(format("cannot delete path `%1%' since it is temporarily in use") % *i);
}
}

View file

@ -96,7 +96,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
if (isDerivation(*i)) drvPaths.insert(*i);
store->buildDerivations(drvPaths);
foreach (Strings::iterator, i,opArgs)
foreach (Strings::iterator, i, opArgs)
cout << format("%1%\n") % realisePath(*i);
}

View file

@ -7,7 +7,7 @@ dependencies.sh gc.sh nix-push.sh nix-pull.in logging.sh nix-build.sh install-pa
locking.sh: locking.nix
parallel.sh: parallel.nix
build-hook.sh: build-hook.nix
gc-concurrent.sh: gc-concurrent.nix gc-concurrent2.nix
gc-concurrent.sh: gc-concurrent.nix gc-concurrent2.nix simple.nix
user-envs.sh: user-envs.nix
fixed.sh: fixed.nix
gc-runtime.sh: gc-runtime.nix

View file

@ -8,8 +8,15 @@ outPath1=$($nixstore -q $drvPath1)
drvPath2=$($nixinstantiate gc-concurrent2.nix)
outPath2=$($nixstore -q $drvPath2)
rm -f "$NIX_STATE_DIR"/gcroots/foo
drvPath3=$($nixinstantiate simple.nix)
outPath3=$($nixstore -r $drvPath3)
! test -e $outPath3.lock
touch $outPath3.lock
rm -f "$NIX_STATE_DIR"/gcroots/foo*
ln -s $drvPath2 "$NIX_STATE_DIR"/gcroots/foo
ln -s $outPath3 "$NIX_STATE_DIR"/gcroots/foo2
# Start build #1 in the background. It starts immediately.
$nixstore -rvv "$drvPath1" &
@ -39,4 +46,13 @@ cat $outPath1/input-2/bar
# derivation is a GC root.
cat $outPath2/foobar
rm "$NIX_STATE_DIR"/gcroots/foo
rm -f "$NIX_STATE_DIR"/gcroots/foo*
# The collector should have deleted lock files for paths that have
# been built previously.
! test -e $outPath3.lock
# If we run the collector now, it should delete outPath1/2.
$NIX_BIN_DIR/nix-collect-garbage -vvvvv
! test -e $outPath1
! test -e $outPath2