mirror of
https://github.com/NixOS/nix.git
synced 2025-11-25 19:51:00 +01:00
* Down to 1 test failure...
This commit is contained in:
parent
07da660396
commit
95fa444587
9 changed files with 156 additions and 219 deletions
|
|
@ -206,7 +206,9 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Worker();
|
LocalStore & store;
|
||||||
|
|
||||||
|
Worker(LocalStore & store);
|
||||||
~Worker();
|
~Worker();
|
||||||
|
|
||||||
/* Make a goal (with caching). */
|
/* Make a goal (with caching). */
|
||||||
|
|
@ -896,14 +898,14 @@ void DerivationGoal::haveDerivation()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(store->isValidPath(drvPath));
|
assert(worker.store.isValidPath(drvPath));
|
||||||
|
|
||||||
/* Get the derivation. */
|
/* Get the derivation. */
|
||||||
drv = derivationFromPath(drvPath);
|
drv = derivationFromPath(drvPath);
|
||||||
|
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
store->addTempRoot(i->second.path);
|
worker.store.addTempRoot(i->second.path);
|
||||||
|
|
||||||
/* Check what outputs paths are not already valid. */
|
/* Check what outputs paths are not already valid. */
|
||||||
PathSet invalidOutputs = checkPathValidity(false);
|
PathSet invalidOutputs = checkPathValidity(false);
|
||||||
|
|
@ -937,7 +939,7 @@ void DerivationGoal::haveDerivation()
|
||||||
i != invalidOutputs.end(); ++i)
|
i != invalidOutputs.end(); ++i)
|
||||||
/* Don't bother creating a substitution goal if there are no
|
/* Don't bother creating a substitution goal if there are no
|
||||||
substitutes. */
|
substitutes. */
|
||||||
if (store->hasSubstitutes(*i))
|
if (worker.store.hasSubstitutes(*i))
|
||||||
addWaitee(worker.makeSubstitutionGoal(*i));
|
addWaitee(worker.makeSubstitutionGoal(*i));
|
||||||
|
|
||||||
if (waitees.empty()) /* to prevent hang (no wake-up event) */
|
if (waitees.empty()) /* to prevent hang (no wake-up event) */
|
||||||
|
|
@ -992,7 +994,7 @@ void DerivationGoal::outputsSubstituted()
|
||||||
throw BuildError(format("`exportBuildReferencesGraph' contains a non-store path `%1%'")
|
throw BuildError(format("`exportBuildReferencesGraph' contains a non-store path `%1%'")
|
||||||
% storePath);
|
% storePath);
|
||||||
storePath = toStorePath(storePath);
|
storePath = toStorePath(storePath);
|
||||||
if (!store->isValidPath(storePath))
|
if (!worker.store.isValidPath(storePath))
|
||||||
throw BuildError(format("`exportBuildReferencesGraph' contains an invalid path `%1%'")
|
throw BuildError(format("`exportBuildReferencesGraph' contains an invalid path `%1%'")
|
||||||
% storePath);
|
% storePath);
|
||||||
|
|
||||||
|
|
@ -1249,19 +1251,6 @@ PathSet outputPaths(const DerivationOutputs & outputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string showPaths(const PathSet & paths)
|
|
||||||
{
|
|
||||||
string s;
|
|
||||||
for (PathSet::const_iterator i = paths.begin();
|
|
||||||
i != paths.end(); ++i)
|
|
||||||
{
|
|
||||||
if (s.size() != 0) s += ", ";
|
|
||||||
s += "`" + *i + "'";
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
||||||
{
|
{
|
||||||
if (!useBuildHook) return rpDecline;
|
if (!useBuildHook) return rpDecline;
|
||||||
|
|
@ -1473,7 +1462,7 @@ DerivationGoal::PrepareBuildReply DerivationGoal::prepareBuild()
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
{
|
{
|
||||||
Path path = i->second.path;
|
Path path = i->second.path;
|
||||||
if (store->isValidPath(path))
|
if (worker.store.isValidPath(path))
|
||||||
throw BuildError(format("obstructed build: path `%1%' exists") % path);
|
throw BuildError(format("obstructed build: path `%1%' exists") % path);
|
||||||
if (pathExists(path)) {
|
if (pathExists(path)) {
|
||||||
debug(format("removing unregistered path `%1%'") % path);
|
debug(format("removing unregistered path `%1%'") % path);
|
||||||
|
|
@ -1501,7 +1490,7 @@ DerivationGoal::PrepareBuildReply DerivationGoal::prepareBuild()
|
||||||
/* Add the relevant output closures of the input derivation
|
/* Add the relevant output closures of the input derivation
|
||||||
`*i' as input paths. Only add the closures of output paths
|
`*i' as input paths. Only add the closures of output paths
|
||||||
that are specified as inputs. */
|
that are specified as inputs. */
|
||||||
assert(store->isValidPath(i->first));
|
assert(worker.store.isValidPath(i->first));
|
||||||
Derivation inDrv = derivationFromPath(i->first);
|
Derivation inDrv = derivationFromPath(i->first);
|
||||||
for (StringSet::iterator j = i->second.begin();
|
for (StringSet::iterator j = i->second.begin();
|
||||||
j != i->second.end(); ++j)
|
j != i->second.end(); ++j)
|
||||||
|
|
@ -1623,7 +1612,7 @@ void DerivationGoal::startBuilder()
|
||||||
throw BuildError(format("`exportReferencesGraph' contains a non-store path `%1%'")
|
throw BuildError(format("`exportReferencesGraph' contains a non-store path `%1%'")
|
||||||
% storePath);
|
% storePath);
|
||||||
storePath = toStorePath(storePath);
|
storePath = toStorePath(storePath);
|
||||||
if (!store->isValidPath(storePath))
|
if (!worker.store.isValidPath(storePath))
|
||||||
throw BuildError(format("`exportReferencesGraph' contains an invalid path `%1%'")
|
throw BuildError(format("`exportReferencesGraph' contains an invalid path `%1%'")
|
||||||
% storePath);
|
% storePath);
|
||||||
|
|
||||||
|
|
@ -1651,7 +1640,7 @@ void DerivationGoal::startBuilder()
|
||||||
throw BuildError(format("`exportBuildReferencesGraph' contains a non-store path `%1%'")
|
throw BuildError(format("`exportBuildReferencesGraph' contains a non-store path `%1%'")
|
||||||
% storePath);
|
% storePath);
|
||||||
storePath = toStorePath(storePath);
|
storePath = toStorePath(storePath);
|
||||||
if (!store->isValidPath(storePath))
|
if (!worker.store.isValidPath(storePath))
|
||||||
throw BuildError(format("`exportBuildReferencesGraph' contains an invalid path `%1%'")
|
throw BuildError(format("`exportBuildReferencesGraph' contains an invalid path `%1%'")
|
||||||
% storePath);
|
% storePath);
|
||||||
|
|
||||||
|
|
@ -1999,7 +1988,7 @@ void DerivationGoal::computeClosure()
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
{
|
{
|
||||||
registerValidPath(i->second.path,
|
worker.store.registerValidPath(i->second.path,
|
||||||
contentHashes[i->second.path],
|
contentHashes[i->second.path],
|
||||||
allReferences[i->second.path],
|
allReferences[i->second.path],
|
||||||
drvPath);
|
drvPath);
|
||||||
|
|
@ -2102,7 +2091,7 @@ PathSet DerivationGoal::checkPathValidity(bool returnValid)
|
||||||
PathSet result;
|
PathSet result;
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
if (store->isValidPath(i->second.path)) {
|
if (worker.store.isValidPath(i->second.path)) {
|
||||||
if (returnValid) result.insert(i->second.path);
|
if (returnValid) result.insert(i->second.path);
|
||||||
} else {
|
} else {
|
||||||
if (!returnValid) result.insert(i->second.path);
|
if (!returnValid) result.insert(i->second.path);
|
||||||
|
|
@ -2208,10 +2197,10 @@ void SubstitutionGoal::init()
|
||||||
{
|
{
|
||||||
trace("init");
|
trace("init");
|
||||||
|
|
||||||
store->addTempRoot(storePath);
|
worker.store.addTempRoot(storePath);
|
||||||
|
|
||||||
/* If the path already exists we're done. */
|
/* If the path already exists we're done. */
|
||||||
if (store->isValidPath(storePath)) {
|
if (worker.store.isValidPath(storePath)) {
|
||||||
amDone(ecSuccess);
|
amDone(ecSuccess);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2282,7 +2271,7 @@ void SubstitutionGoal::referencesValid()
|
||||||
for (PathSet::iterator i = references.begin();
|
for (PathSet::iterator i = references.begin();
|
||||||
i != references.end(); ++i)
|
i != references.end(); ++i)
|
||||||
if (*i != storePath) /* ignore self-references */
|
if (*i != storePath) /* ignore self-references */
|
||||||
assert(store->isValidPath(*i));
|
assert(worker.store.isValidPath(*i));
|
||||||
|
|
||||||
state = &SubstitutionGoal::tryToRun;
|
state = &SubstitutionGoal::tryToRun;
|
||||||
worker.waitForBuildSlot(shared_from_this());
|
worker.waitForBuildSlot(shared_from_this());
|
||||||
|
|
@ -2316,7 +2305,7 @@ void SubstitutionGoal::tryToRun()
|
||||||
(format("waiting for lock on `%1%'") % storePath).str());
|
(format("waiting for lock on `%1%'") % storePath).str());
|
||||||
|
|
||||||
/* Check again whether the path is invalid. */
|
/* Check again whether the path is invalid. */
|
||||||
if (store->isValidPath(storePath)) {
|
if (worker.store.isValidPath(storePath)) {
|
||||||
debug(format("store path `%1%' has become valid") % storePath);
|
debug(format("store path `%1%' has become valid") % storePath);
|
||||||
outputLock->setDeletion(true);
|
outputLock->setDeletion(true);
|
||||||
amDone(ecSuccess);
|
amDone(ecSuccess);
|
||||||
|
|
@ -2423,7 +2412,7 @@ void SubstitutionGoal::finished()
|
||||||
|
|
||||||
Hash contentHash = hashPath(htSHA256, storePath);
|
Hash contentHash = hashPath(htSHA256, storePath);
|
||||||
|
|
||||||
registerValidPath(storePath, contentHash,
|
worker.store.registerValidPath(storePath, contentHash,
|
||||||
references, deriver);
|
references, deriver);
|
||||||
|
|
||||||
outputLock->setDeletion(true);
|
outputLock->setDeletion(true);
|
||||||
|
|
@ -2458,7 +2447,8 @@ void SubstitutionGoal::handleEOF(int fd)
|
||||||
static bool working = false;
|
static bool working = false;
|
||||||
|
|
||||||
|
|
||||||
Worker::Worker()
|
Worker::Worker(LocalStore & store)
|
||||||
|
: store(store)
|
||||||
{
|
{
|
||||||
/* Debugging: prevent recursive workers. */
|
/* Debugging: prevent recursive workers. */
|
||||||
if (working) abort();
|
if (working) abort();
|
||||||
|
|
@ -2856,7 +2846,7 @@ void LocalStore::buildDerivations(const PathSet & drvPaths)
|
||||||
startNest(nest, lvlDebug,
|
startNest(nest, lvlDebug,
|
||||||
format("building %1%") % showPaths(drvPaths));
|
format("building %1%") % showPaths(drvPaths));
|
||||||
|
|
||||||
Worker worker;
|
Worker worker(*this);
|
||||||
|
|
||||||
Goals goals;
|
Goals goals;
|
||||||
for (PathSet::const_iterator i = drvPaths.begin();
|
for (PathSet::const_iterator i = drvPaths.begin();
|
||||||
|
|
@ -2881,9 +2871,9 @@ void LocalStore::buildDerivations(const PathSet & drvPaths)
|
||||||
void LocalStore::ensurePath(const Path & path)
|
void LocalStore::ensurePath(const Path & path)
|
||||||
{
|
{
|
||||||
/* If the path is already valid, we're done. */
|
/* If the path is already valid, we're done. */
|
||||||
if (store->isValidPath(path)) return;
|
if (isValidPath(path)) return;
|
||||||
|
|
||||||
Worker worker;
|
Worker worker(*this);
|
||||||
GoalPtr goal = worker.makeSubstitutionGoal(path);
|
GoalPtr goal = worker.makeSubstitutionGoal(path);
|
||||||
Goals goals = singleton<Goals>(goal);
|
Goals goals = singleton<Goals>(goal);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
void upgradeStore12();
|
|
||||||
|
|
||||||
|
|
||||||
void checkStoreNotSymlink()
|
void checkStoreNotSymlink()
|
||||||
{
|
{
|
||||||
if (getEnv("NIX_IGNORE_SYMLINK_STORE") == "1") return;
|
if (getEnv("NIX_IGNORE_SYMLINK_STORE") == "1") return;
|
||||||
|
|
@ -211,17 +208,41 @@ static void appendReferrer(const Path & from, const Path & to)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void registerValidPath(const Path & path,
|
/* Atomically update the referrers file. */
|
||||||
|
static void rewriteReferrers(const Path & path, const PathSet & referrers)
|
||||||
|
{
|
||||||
|
string s;
|
||||||
|
for (PathSet::const_iterator i = referrers.begin(); i != referrers.end(); ++i) {
|
||||||
|
s += " "; s += *i;
|
||||||
|
}
|
||||||
|
writeFile(referrersFileFor(path), s); /* !!! atomicity, locking */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LocalStore::registerValidPath(const Path & path,
|
||||||
const Hash & hash, const PathSet & references,
|
const Hash & hash, const PathSet & references,
|
||||||
const Path & deriver)
|
const Path & deriver)
|
||||||
{
|
{
|
||||||
Path infoFile = infoFileFor(path);
|
ValidPathInfo info;
|
||||||
|
info.path = path;
|
||||||
|
info.hash = hash;
|
||||||
|
info.references = references;
|
||||||
|
info.deriver = deriver;
|
||||||
|
registerValidPath(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LocalStore::registerValidPath(const ValidPathInfo & info)
|
||||||
|
{
|
||||||
|
Path infoFile = infoFileFor(info.path);
|
||||||
if (pathExists(infoFile)) return;
|
if (pathExists(infoFile)) return;
|
||||||
|
|
||||||
// !!! acquire PathLock on infoFile here
|
// !!! acquire PathLock on infoFile here?
|
||||||
|
|
||||||
string refs;
|
string refs;
|
||||||
for (PathSet::const_iterator i = references.begin(); i != references.end(); ++i) {
|
for (PathSet::const_iterator i = info.references.begin();
|
||||||
|
i != info.references.end(); ++i)
|
||||||
|
{
|
||||||
if (!refs.empty()) refs += " ";
|
if (!refs.empty()) refs += " ";
|
||||||
refs += *i;
|
refs += *i;
|
||||||
|
|
||||||
|
|
@ -231,21 +252,20 @@ void registerValidPath(const Path & path,
|
||||||
have referrer mappings back to `path'. A " " is prefixed
|
have referrer mappings back to `path'. A " " is prefixed
|
||||||
to separate it from the previous entry. It's not suffixed
|
to separate it from the previous entry. It's not suffixed
|
||||||
to deal with interrupted partial writes to this file. */
|
to deal with interrupted partial writes to this file. */
|
||||||
appendReferrer(*i, path);
|
appendReferrer(*i, info.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
string info = (format(
|
string s = (format(
|
||||||
"Hash: sha256:%1%\n"
|
"Hash: sha256:%1%\n"
|
||||||
"References: %2%\n"
|
"References: %2%\n"
|
||||||
"Deriver: %3%\n"
|
"Deriver: %3%\n"
|
||||||
"Registered-At: %4%\n")
|
"Registered-At: %4%\n")
|
||||||
% printHash(hash) % refs % deriver % time(0)).str();
|
% printHash(info.hash) % refs % info.deriver % time(0)).str();
|
||||||
|
|
||||||
// !!! atomicity
|
// !!! atomicity
|
||||||
writeFile(infoFile, info);
|
writeFile(infoFile, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Hash parseHashField(const Path & path, const string & s)
|
Hash parseHashField(const Path & path, const string & s)
|
||||||
{
|
{
|
||||||
string::size_type colon = s.find(':');
|
string::size_type colon = s.find(':');
|
||||||
|
|
@ -260,12 +280,16 @@ Hash parseHashField(const Path & path, const string & s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ValidPathInfo queryPathInfo(const Path & path)
|
ValidPathInfo LocalStore::queryPathInfo(const Path & path)
|
||||||
{
|
{
|
||||||
ValidPathInfo res;
|
ValidPathInfo res;
|
||||||
|
|
||||||
assertStorePath(path);
|
assertStorePath(path);
|
||||||
// !!! printMsg(lvlError, "queryPathInfo: " + path);
|
|
||||||
|
std::map<Path, ValidPathInfo>::iterator lookup = pathInfoCache.find(path);
|
||||||
|
if (lookup != pathInfoCache.end()) return lookup->second;
|
||||||
|
|
||||||
|
//printMsg(lvlError, "queryPathInfo: " + path);
|
||||||
|
|
||||||
/* Read the info file. */
|
/* Read the info file. */
|
||||||
Path infoFile = infoFileFor(path);
|
Path infoFile = infoFileFor(path);
|
||||||
|
|
@ -291,7 +315,7 @@ ValidPathInfo queryPathInfo(const Path & path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return pathInfoCache[path] = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -311,54 +335,6 @@ PathSet LocalStore::queryValidPaths()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static PathSet getReferrers(const Transaction & txn, const Path & storePath)
|
|
||||||
{
|
|
||||||
throw Error("!!! getReferrers");
|
|
||||||
PathSet referrers;
|
|
||||||
Strings keys;
|
|
||||||
nixDB.enumTable(txn, dbReferrers, keys, storePath + string(1, (char) 0));
|
|
||||||
for (Strings::iterator i = keys.begin(); i != keys.end(); ++i)
|
|
||||||
referrers.insert(stripPrefix(storePath, *i));
|
|
||||||
return referrers;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void setReferences(const Transaction & txn, const Path & storePath,
|
|
||||||
const PathSet & references)
|
|
||||||
{
|
|
||||||
/* For invalid paths, we can only clear the references. */
|
|
||||||
if (references.size() > 0 && !isValidPathTxn(txn, storePath))
|
|
||||||
throw Error(
|
|
||||||
format("cannot set references for invalid path `%1%'") % storePath);
|
|
||||||
|
|
||||||
Paths oldReferences;
|
|
||||||
nixDB.queryStrings(txn, dbReferences, storePath, oldReferences);
|
|
||||||
|
|
||||||
PathSet oldReferences2(oldReferences.begin(), oldReferences.end());
|
|
||||||
if (oldReferences2 == references) return;
|
|
||||||
|
|
||||||
nixDB.setStrings(txn, dbReferences, storePath,
|
|
||||||
Paths(references.begin(), references.end()));
|
|
||||||
|
|
||||||
/* Update the referrers mappings of all new referenced paths. */
|
|
||||||
for (PathSet::const_iterator i = references.begin();
|
|
||||||
i != references.end(); ++i)
|
|
||||||
if (oldReferences2.find(*i) == oldReferences2.end())
|
|
||||||
nixDB.setString(txn, dbReferrers, addPrefix(*i, storePath), "");
|
|
||||||
|
|
||||||
/* Remove referrer mappings from paths that are no longer
|
|
||||||
references. */
|
|
||||||
for (Paths::iterator i = oldReferences.begin();
|
|
||||||
i != oldReferences.end(); ++i)
|
|
||||||
if (references.find(*i) == references.end())
|
|
||||||
nixDB.delPair(txn, dbReferrers, addPrefix(*i, storePath));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::queryReferences(const Path & path,
|
void LocalStore::queryReferences(const Path & path,
|
||||||
PathSet & references)
|
PathSet & references)
|
||||||
{
|
{
|
||||||
|
|
@ -393,20 +369,6 @@ void LocalStore::queryReferrers(const Path & path, PathSet & referrers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void setDeriver(const Transaction & txn, const Path & storePath,
|
|
||||||
const Path & deriver)
|
|
||||||
{
|
|
||||||
assertStorePath(storePath);
|
|
||||||
if (deriver == "") return;
|
|
||||||
assertStorePath(deriver);
|
|
||||||
if (!isValidPathTxn(txn, storePath))
|
|
||||||
throw Error(format("path `%1%' is not valid") % storePath);
|
|
||||||
nixDB.setString(txn, dbDerivers, storePath, deriver);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
Path LocalStore::queryDeriver(const Path & path)
|
Path LocalStore::queryDeriver(const Path & path)
|
||||||
{
|
{
|
||||||
return queryPathInfo(path).deriver;
|
return queryPathInfo(path).deriver;
|
||||||
|
|
@ -449,24 +411,7 @@ Hash LocalStore::queryPathHash(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
void LocalStore::registerValidPaths(const ValidPathInfos & infos)
|
||||||
void registerValidPath(const Transaction & txn,
|
|
||||||
const Path & path, const Hash & hash, const PathSet & references,
|
|
||||||
const Path & deriver)
|
|
||||||
{
|
|
||||||
ValidPathInfo info;
|
|
||||||
info.path = path;
|
|
||||||
info.hash = hash;
|
|
||||||
info.references = references;
|
|
||||||
info.deriver = deriver;
|
|
||||||
ValidPathInfos infos;
|
|
||||||
infos.push_back(info);
|
|
||||||
registerValidPaths(txn, infos);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void registerValidPaths(const ValidPathInfos & infos)
|
|
||||||
{
|
{
|
||||||
throw Error("!!! registerValidPaths");
|
throw Error("!!! registerValidPaths");
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -505,14 +450,16 @@ static void invalidatePath(const Path & path)
|
||||||
{
|
{
|
||||||
debug(format("invalidating path `%1%'") % path);
|
debug(format("invalidating path `%1%'") % path);
|
||||||
|
|
||||||
throw Error("!!! invalidatePath");
|
/* Remove the info file. */
|
||||||
#if 0
|
Path p = infoFileFor(path);
|
||||||
/* Clear the `references' entry for this path, as well as the
|
if (unlink(p.c_str()) == -1)
|
||||||
inverse `referrers' entries, and the `derivers' entry. */
|
throw SysError(format("unlinking `%1%'") % p);
|
||||||
setReferences(txn, path, PathSet());
|
|
||||||
nixDB.delPair(txn, dbDerivers, path);
|
/* Remove the corresponding referrer entries for each path
|
||||||
nixDB.delPair(txn, dbValidPaths, path);
|
referenced by this one. This has to happen after removing the
|
||||||
#endif
|
info file to preserve the invariant (see
|
||||||
|
registerValidPath()). */
|
||||||
|
/* !!! */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -785,28 +732,24 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void deleteFromStore(const Path & _path, unsigned long long & bytesFreed)
|
void LocalStore::deleteFromStore(const Path & _path, unsigned long long & bytesFreed)
|
||||||
{
|
{
|
||||||
throw Error("!!! deleteFromStore");
|
|
||||||
#if 0
|
|
||||||
bytesFreed = 0;
|
bytesFreed = 0;
|
||||||
Path path(canonPath(_path));
|
Path path(canonPath(_path));
|
||||||
|
|
||||||
assertStorePath(path);
|
assertStorePath(path);
|
||||||
|
|
||||||
Transaction txn(nixDB);
|
if (isValidPath(path)) {
|
||||||
if (isValidPathTxn(txn, path)) {
|
PathSet referrers; queryReferrers(path, referrers);
|
||||||
PathSet referrers = getReferrers(txn, path);
|
referrers.erase(path); /* ignore self-references */
|
||||||
for (PathSet::iterator i = referrers.begin();
|
/* !!! check: can a new referrer appear now? */
|
||||||
i != referrers.end(); ++i)
|
if (!referrers.empty())
|
||||||
if (*i != path && isValidPathTxn(txn, *i))
|
throw PathInUse(format("cannot delete path `%1%' because it is in use by `%2%'")
|
||||||
throw PathInUse(format("cannot delete path `%1%' because it is in use by path `%2%'") % path % *i);
|
% path % showPaths(referrers));
|
||||||
invalidatePath(txn, path);
|
invalidatePath(path);
|
||||||
}
|
}
|
||||||
txn.commit();
|
|
||||||
|
|
||||||
deletePathWrapped(path, bytesFreed);
|
deletePathWrapped(path, bytesFreed);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -889,6 +832,8 @@ void LocalStore::verifyStore(bool checkContents)
|
||||||
/* Check the referrers. */
|
/* Check the referrers. */
|
||||||
printMsg(lvlInfo, "checking referrers");
|
printMsg(lvlInfo, "checking referrers");
|
||||||
|
|
||||||
|
std::map<Path, PathSet> referencesCache;
|
||||||
|
|
||||||
Strings entries = readDirectory(nixDBPath + "/referrer");
|
Strings entries = readDirectory(nixDBPath + "/referrer");
|
||||||
for (Strings::iterator i = entries.begin(); i != entries.end(); ++i) {
|
for (Strings::iterator i = entries.begin(); i != entries.end(); ++i) {
|
||||||
Path from = nixStore + "/" + *i;
|
Path from = nixStore + "/" + *i;
|
||||||
|
|
@ -906,54 +851,24 @@ void LocalStore::verifyStore(bool checkContents)
|
||||||
bool update = false;
|
bool update = false;
|
||||||
|
|
||||||
if (!allValid) {
|
if (!allValid) {
|
||||||
printMsg(lvlError, format("removing some stale paths from referrers of `%1%'") % from);
|
printMsg(lvlError, format("removing some stale referrers for `%1%'") % from);
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update)
|
/* Each referrer should have a matching reference. */
|
||||||
/* !!! */;
|
PathSet referrersNew;
|
||||||
|
for (PathSet::iterator j = referrers.begin(); j != referrers.end(); ++j) {
|
||||||
|
if (referencesCache.find(*j) == referencesCache.end())
|
||||||
|
queryReferences(*j, referencesCache[*j]);
|
||||||
|
if (referencesCache[*j].find(from) == referencesCache[*j].end()) {
|
||||||
|
printMsg(lvlError, format("removing unexpected referrer mapping from `%1%' to `%2%'")
|
||||||
|
% from % *j);
|
||||||
|
update = true;
|
||||||
|
} else referrersNew.insert(*j);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update) rewriteReferrers(from, referrersNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
Strings referrers;
|
|
||||||
nixDB.enumTable(txn, dbReferrers, referrers);
|
|
||||||
for (Strings::iterator i = referrers.begin(); i != referrers.end(); ++i) {
|
|
||||||
|
|
||||||
/* Decode the entry (it's a tuple of paths). */
|
|
||||||
string::size_type nul = i->find((char) 0);
|
|
||||||
if (nul == string::npos) {
|
|
||||||
printMsg(lvlError, format("removing bad referrer table entry `%1%'") % *i);
|
|
||||||
nixDB.delPair(txn, dbReferrers, *i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Path to(*i, 0, nul);
|
|
||||||
Path from(*i, nul + 1);
|
|
||||||
|
|
||||||
if (validPaths.find(to) == validPaths.end()) {
|
|
||||||
printMsg(lvlError, format("removing referrer entry from `%1%' to invalid `%2%'")
|
|
||||||
% from % to);
|
|
||||||
nixDB.delPair(txn, dbReferrers, *i);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (validPaths.find(from) == validPaths.end()) {
|
|
||||||
printMsg(lvlError, format("removing referrer entry from invalid `%1%' to `%2%'")
|
|
||||||
% from % to);
|
|
||||||
nixDB.delPair(txn, dbReferrers, *i);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
PathSet references;
|
|
||||||
oldQueryReferences(txn, from, references);
|
|
||||||
if (find(references.begin(), references.end(), to) == references.end()) {
|
|
||||||
printMsg(lvlError, format("adding missing referrer mapping from `%1%' to `%2%'")
|
|
||||||
% from % to);
|
|
||||||
references.insert(to);
|
|
||||||
setReferences(txn, from, references);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,9 @@ public:
|
||||||
void collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
void collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed);
|
bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed);
|
||||||
|
|
||||||
|
/* Delete a path from the Nix store. */
|
||||||
|
void deleteFromStore(const Path & path, unsigned long long & bytesFreed);
|
||||||
|
|
||||||
/* Optimise the disk space usage of the Nix store by hard-linking
|
/* Optimise the disk space usage of the Nix store by hard-linking
|
||||||
files with the same contents. */
|
files with the same contents. */
|
||||||
void optimiseStore(bool dryRun, OptimiseStats & stats);
|
void optimiseStore(bool dryRun, OptimiseStats & stats);
|
||||||
|
|
@ -98,28 +101,37 @@ public:
|
||||||
/* Check the integrity of the Nix store. */
|
/* Check the integrity of the Nix store. */
|
||||||
void verifyStore(bool checkContents);
|
void verifyStore(bool checkContents);
|
||||||
|
|
||||||
|
/* Register the validity of a path, i.e., that `path' exists, that
|
||||||
|
the paths referenced by it exists, and in the case of an output
|
||||||
|
path of a derivation, that it has been produced by a succesful
|
||||||
|
execution of the derivation (or something equivalent). Also
|
||||||
|
register the hash of the file system contents of the path. The
|
||||||
|
hash must be a SHA-256 hash. */
|
||||||
|
void registerValidPath(const Path & path,
|
||||||
|
const Hash & hash, const PathSet & references, const Path & deriver);
|
||||||
|
|
||||||
|
void registerValidPaths(const ValidPathInfos & infos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/* !!! The cache can grow very big. Maybe it should be pruned
|
||||||
|
every once in a while. */
|
||||||
|
std::map<Path, ValidPathInfo> pathInfoCache;
|
||||||
|
|
||||||
|
void registerValidPath(const ValidPathInfo & info);
|
||||||
|
|
||||||
|
ValidPathInfo queryPathInfo(const Path & path);
|
||||||
|
|
||||||
bool queryReferrersInternal(const Path & path, PathSet & referrers);
|
bool queryReferrersInternal(const Path & path, PathSet & referrers);
|
||||||
|
|
||||||
|
void upgradeStore12();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Copy a path recursively. */
|
/* Copy a path recursively. */
|
||||||
void copyPath(const Path & src, const Path & dst);
|
void copyPath(const Path & src, const Path & dst);
|
||||||
|
|
||||||
/* Register the validity of a path, i.e., that `path' exists, that the
|
|
||||||
paths referenced by it exists, and in the case of an output path of
|
|
||||||
a derivation, that it has been produced by a succesful execution of
|
|
||||||
the derivation (or something equivalent). Also register the hash
|
|
||||||
of the file system contents of the path. The hash must be a
|
|
||||||
SHA-256 hash. */
|
|
||||||
void registerValidPath(const Path & path,
|
|
||||||
const Hash & hash, const PathSet & references, const Path & deriver);
|
|
||||||
|
|
||||||
typedef list<ValidPathInfo> ValidPathInfos;
|
|
||||||
|
|
||||||
void registerValidPaths(const ValidPathInfos & infos);
|
|
||||||
|
|
||||||
/* "Fix", or canonicalise, the meta-data of the files in a store path
|
/* "Fix", or canonicalise, the meta-data of the files in a store path
|
||||||
after it has been built. In particular:
|
after it has been built. In particular:
|
||||||
- the last modification date on each file is set to 0 (i.e.,
|
- the last modification date on each file is set to 0 (i.e.,
|
||||||
|
|
@ -130,9 +142,6 @@ void registerValidPaths(const ValidPathInfos & infos);
|
||||||
in a setuid Nix installation. */
|
in a setuid Nix installation. */
|
||||||
void canonicalisePathMetaData(const Path & path);
|
void canonicalisePathMetaData(const Path & path);
|
||||||
|
|
||||||
/* Delete a value from the nixStore directory. */
|
|
||||||
void deleteFromStore(const Path & path, unsigned long long & bytesFreed);
|
|
||||||
|
|
||||||
MakeError(PathInUse, Error);
|
MakeError(PathInUse, Error);
|
||||||
|
|
||||||
/* Whether we are in build users mode. */
|
/* Whether we are in build users mode. */
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,19 @@ ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string showPaths(const PathSet & paths)
|
||||||
|
{
|
||||||
|
string s;
|
||||||
|
for (PathSet::const_iterator i = paths.begin();
|
||||||
|
i != paths.end(); ++i)
|
||||||
|
{
|
||||||
|
if (s.size() != 0) s += ", ";
|
||||||
|
s += "`" + *i + "'";
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -252,6 +252,11 @@ extern boost::shared_ptr<StoreAPI> store;
|
||||||
boost::shared_ptr<StoreAPI> openStore();
|
boost::shared_ptr<StoreAPI> openStore();
|
||||||
|
|
||||||
|
|
||||||
|
/* Display a set of paths in human-readable form (i.e., between quotes
|
||||||
|
and separated by commas). */
|
||||||
|
string showPaths(const PathSet & paths);
|
||||||
|
|
||||||
|
|
||||||
string makeValidityRegistration(const PathSet & paths,
|
string makeValidityRegistration(const PathSet & paths,
|
||||||
bool showDerivers, bool showHash);
|
bool showDerivers, bool showHash);
|
||||||
|
|
||||||
|
|
@ -263,6 +268,8 @@ struct ValidPathInfo
|
||||||
PathSet references;
|
PathSet references;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef list<ValidPathInfo> ValidPathInfos;
|
||||||
|
|
||||||
ValidPathInfo decodeValidPathInfo(std::istream & str,
|
ValidPathInfo decodeValidPathInfo(std::istream & str,
|
||||||
bool hashGiven = false);
|
bool hashGiven = false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ Hash parseHashField(const Path & path, const string & s);
|
||||||
/* Upgrade from schema 4 (Nix 0.11) to schema 5 (Nix >= 0.12). The
|
/* Upgrade from schema 4 (Nix 0.11) to schema 5 (Nix >= 0.12). The
|
||||||
old schema uses Berkeley DB, the new one stores store path
|
old schema uses Berkeley DB, the new one stores store path
|
||||||
meta-information in files. */
|
meta-information in files. */
|
||||||
void upgradeStore12()
|
void LocalStore::upgradeStore12()
|
||||||
{
|
{
|
||||||
printMsg(lvlError, "upgrading Nix store to new schema (this may take a while)...");
|
printMsg(lvlError, "upgrading Nix store to new schema (this may take a while)...");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,14 @@ static int rootNr = 0;
|
||||||
static bool indirectRoot = false;
|
static bool indirectRoot = false;
|
||||||
|
|
||||||
|
|
||||||
|
LocalStore & ensureLocalStore()
|
||||||
|
{
|
||||||
|
LocalStore * store2(dynamic_cast<LocalStore *>(store.get()));
|
||||||
|
if (!store2) throw Error("you don't have sufficient rights to use --verify");
|
||||||
|
return *store2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static Path useDeriver(Path path)
|
static Path useDeriver(Path path)
|
||||||
{
|
{
|
||||||
if (!isDerivation(path)) {
|
if (!isDerivation(path)) {
|
||||||
|
|
@ -430,7 +438,7 @@ static void registerValidity(bool reregister, bool hashGiven, bool canonicalise)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registerValidPaths(infos);
|
ensureLocalStore().registerValidPaths(infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -638,10 +646,7 @@ static void opVerify(Strings opFlags, Strings opArgs)
|
||||||
if (*i == "--check-contents") checkContents = true;
|
if (*i == "--check-contents") checkContents = true;
|
||||||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||||
|
|
||||||
LocalStore * store2(dynamic_cast<LocalStore *>(store.get()));
|
ensureLocalStore().verifyStore(checkContents);
|
||||||
if (!store2) throw Error("you don't have sufficient rights to use --verify");
|
|
||||||
|
|
||||||
store2->verifyStore(checkContents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -670,12 +675,9 @@ static void opOptimise(Strings opFlags, Strings opArgs)
|
||||||
if (*i == "--dry-run") dryRun = true;
|
if (*i == "--dry-run") dryRun = true;
|
||||||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||||
|
|
||||||
LocalStore * store2(dynamic_cast<LocalStore *>(store.get()));
|
|
||||||
if (!store2) throw Error("you don't have sufficient rights to use --optimise");
|
|
||||||
|
|
||||||
OptimiseStats stats;
|
OptimiseStats stats;
|
||||||
try {
|
try {
|
||||||
store2->optimiseStore(dryRun, stats);
|
ensureLocalStore().optimiseStore(dryRun, stats);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
showOptimiseStats(stats);
|
showOptimiseStats(stats);
|
||||||
throw;
|
throw;
|
||||||
|
|
|
||||||
|
|
@ -472,7 +472,7 @@ static void processConnection()
|
||||||
throw Error("if you run `nix-worker' as root, then you MUST set `build-users-group'!");
|
throw Error("if you run `nix-worker' as root, then you MUST set `build-users-group'!");
|
||||||
|
|
||||||
/* Open the store. */
|
/* Open the store. */
|
||||||
store = boost::shared_ptr<StoreAPI>(new LocalStore(true));
|
store = boost::shared_ptr<StoreAPI>(new LocalStore());
|
||||||
|
|
||||||
stopWork();
|
stopWork();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,4 +95,5 @@ chmod +x $NIX_BIN_DIR/nix/download-using-manifests.pl
|
||||||
$nixstore --init
|
$nixstore --init
|
||||||
|
|
||||||
# Did anything happen?
|
# Did anything happen?
|
||||||
test -e "$NIX_DB_DIR"/validpaths
|
test -e "$NIX_DB_DIR"/info
|
||||||
|
test -e "$NIX_DB_DIR"/referrer
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue