mirror of
https://github.com/NixOS/nix.git
synced 2025-11-26 12:10:59 +01:00
added dbValidStatePaths, StatePaths are now also registered as valid and can be query'd on validity
This commit is contained in:
parent
51fad07fbd
commit
6351b7e728
8 changed files with 126 additions and 24 deletions
|
|
@ -1620,6 +1620,7 @@ void DerivationGoal::computeClosure()
|
||||||
{
|
{
|
||||||
map<Path, PathSet> allReferences;
|
map<Path, PathSet> allReferences;
|
||||||
map<Path, PathSet> allStateReferences;
|
map<Path, PathSet> allStateReferences;
|
||||||
|
map<Path, Path> statePaths;
|
||||||
map<Path, Hash> contentHashes;
|
map<Path, Hash> contentHashes;
|
||||||
|
|
||||||
//TODO MOVE THIS TO A PLACE THAT ALSO GETS CALLED WHEN WE DONT NEED TO BUILD ANYTHING
|
//TODO MOVE THIS TO A PLACE THAT ALSO GETS CALLED WHEN WE DONT NEED TO BUILD ANYTHING
|
||||||
|
|
@ -1737,9 +1738,10 @@ void DerivationGoal::computeClosure()
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
{
|
{
|
||||||
registerValidPath(txn, i->second.path,
|
registerValidPath(txn, i->second.path,
|
||||||
|
"", //dummy statePath
|
||||||
contentHashes[i->second.path],
|
contentHashes[i->second.path],
|
||||||
allReferences[i->second.path],
|
allReferences[i->second.path],
|
||||||
PathSet(),
|
PathSet(), //dummy stateReferences
|
||||||
drvPath);
|
drvPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1785,7 +1787,11 @@ void DerivationGoal::computeClosure()
|
||||||
PathSet state_references = scanForReferences(statePath, allPaths);
|
PathSet state_references = scanForReferences(statePath, allPaths);
|
||||||
PathSet state_stateReferences = scanForStateReferences(statePath, allStatePaths);
|
PathSet state_stateReferences = scanForStateReferences(statePath, allStatePaths);
|
||||||
all_state_references = mergePathSets(all_state_references, mergePathSets(state_references, state_stateReferences));
|
all_state_references = mergePathSets(all_state_references, mergePathSets(state_references, state_stateReferences));
|
||||||
|
|
||||||
|
statePaths[path] = statePath;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
statePaths[path] = "";
|
||||||
|
|
||||||
for (PathSet::const_iterator i = allStatePaths.begin(); i != allStatePaths.end(); i++){
|
for (PathSet::const_iterator i = allStatePaths.begin(); i != allStatePaths.end(); i++){
|
||||||
debug(format("all possible StatePaths: %1%") % (*i));
|
debug(format("all possible StatePaths: %1%") % (*i));
|
||||||
|
|
@ -1795,14 +1801,17 @@ void DerivationGoal::computeClosure()
|
||||||
}
|
}
|
||||||
|
|
||||||
allStateReferences[path] = all_state_references;
|
allStateReferences[path] = all_state_references;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i)
|
for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i)
|
||||||
{
|
{
|
||||||
registerValidPath(txn, i->second.path,
|
registerValidPath(txn,
|
||||||
|
i->second.path, //component path
|
||||||
|
statePaths[i->second.path], //state path
|
||||||
contentHashes[i->second.path],
|
contentHashes[i->second.path],
|
||||||
allReferences[i->second.path],
|
allReferences[i->second.path], //set of component-references
|
||||||
allStateReferences[i->second.path],
|
allStateReferences[i->second.path], //set of state-references
|
||||||
drvPath);
|
drvPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2206,7 +2215,7 @@ void SubstitutionGoal::finished()
|
||||||
|
|
||||||
Transaction txn;
|
Transaction txn;
|
||||||
createStoreTransaction(txn);
|
createStoreTransaction(txn);
|
||||||
registerValidPath(txn, storePath, contentHash,
|
registerValidPath(txn, storePath, "", contentHash, //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! replace "" with a substitued state path !!!!!!!!
|
||||||
references, stateReferences, sub.deriver);
|
references, stateReferences, sub.deriver);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,12 @@ static Database nixDB;
|
||||||
is, produced by a succesful build). */
|
is, produced by a succesful build). */
|
||||||
static TableId dbValidPaths = 0;
|
static TableId dbValidPaths = 0;
|
||||||
|
|
||||||
|
/* dbValidStatePaths :: Path -> ()
|
||||||
|
|
||||||
|
The existence of a key $p$ indicates that state path $p$ is valid (that
|
||||||
|
is, produced by a succesful build). */
|
||||||
|
static TableId dbValidStatePaths = 0;
|
||||||
|
|
||||||
/* dbReferences :: Path -> [Path]
|
/* dbReferences :: Path -> [Path]
|
||||||
|
|
||||||
This table lists the outgoing file system references for each
|
This table lists the outgoing file system references for each
|
||||||
|
|
@ -165,6 +171,7 @@ LocalStore::LocalStore(bool reserveSpace)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dbValidPaths = nixDB.openTable("validpaths");
|
dbValidPaths = nixDB.openTable("validpaths");
|
||||||
|
dbValidStatePaths = nixDB.openTable("validpaths_state");
|
||||||
dbReferences = nixDB.openTable("references");
|
dbReferences = nixDB.openTable("references");
|
||||||
dbReferrers = nixDB.openTable("referrers", true); /* must be sorted */
|
dbReferrers = nixDB.openTable("referrers", true); /* must be sorted */
|
||||||
dbSubstitutes = nixDB.openTable("substitutes");
|
dbSubstitutes = nixDB.openTable("substitutes");
|
||||||
|
|
@ -307,12 +314,32 @@ bool isValidPathTxn(const Transaction & txn, const Path & path)
|
||||||
return nixDB.queryString(txn, dbValidPaths, path, s);
|
return nixDB.queryString(txn, dbValidPaths, path, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LocalStore::isValidPath(const Path & path)
|
bool LocalStore::isValidPath(const Path & path)
|
||||||
{
|
{
|
||||||
return isValidPathTxn(noTxn, path);
|
return isValidPathTxn(noTxn, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isValidStatePathTxn(const Transaction & txn, const Path & path)
|
||||||
|
{
|
||||||
|
string s;
|
||||||
|
return nixDB.queryString(txn, dbValidStatePaths, path, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocalStore::isValidStatePath(const Path & path)
|
||||||
|
{
|
||||||
|
return isValidStatePathTxn(noTxn, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValidComponentOrStatePathTxn(const Transaction & txn, const Path & path)
|
||||||
|
{
|
||||||
|
return (isValidPathTxn(txn, path) || isValidStatePathTxn(txn, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocalStore::isValidComponentOrStatePath(const Path & path)
|
||||||
|
{
|
||||||
|
return isValidComponentOrStatePathTxn(noTxn, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static Substitutes readSubstitutes(const Transaction & txn,
|
static Substitutes readSubstitutes(const Transaction & txn,
|
||||||
const Path & srcPath);
|
const Path & srcPath);
|
||||||
|
|
@ -736,13 +763,20 @@ void clearSubstitutes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void setHash(const Transaction & txn, const Path & storePath,
|
static void setHash(const Transaction & txn, const Path & storePath, const Hash & hash, bool stateHash = false)
|
||||||
const Hash & hash)
|
|
||||||
{
|
{
|
||||||
assert(hash.type == htSHA256);
|
assert(hash.type == htSHA256);
|
||||||
nixDB.setString(txn, dbValidPaths, storePath, "sha256:" + printHash(hash));
|
|
||||||
|
if(stateHash)
|
||||||
|
nixDB.setString(txn, dbValidStatePaths, storePath, "sha256:" + printHash(hash));
|
||||||
|
else
|
||||||
|
nixDB.setString(txn, dbValidPaths, storePath, "sha256:" + printHash(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setStateHash(const Transaction & txn, const Path & storePath, const Hash & hash)
|
||||||
|
{
|
||||||
|
setHash(txn, storePath, hash, true);
|
||||||
|
}
|
||||||
|
|
||||||
static Hash queryHash(const Transaction & txn, const Path & storePath)
|
static Hash queryHash(const Transaction & txn, const Path & storePath)
|
||||||
{
|
{
|
||||||
|
|
@ -769,12 +803,13 @@ Hash LocalStore::queryPathHash(const Path & path)
|
||||||
|
|
||||||
|
|
||||||
void registerValidPath(const Transaction & txn,
|
void registerValidPath(const Transaction & txn,
|
||||||
const Path & path, const Hash & hash,
|
const Path & path, const Path & statePath, const Hash & hash,
|
||||||
const PathSet & references, const PathSet & stateReferences,
|
const PathSet & references, const PathSet & stateReferences,
|
||||||
const Path & deriver)
|
const Path & deriver)
|
||||||
{
|
{
|
||||||
ValidPathInfo info;
|
ValidPathInfo info;
|
||||||
info.path = path;
|
info.path = path;
|
||||||
|
info.statePath = statePath;
|
||||||
info.hash = hash;
|
info.hash = hash;
|
||||||
info.references = references;
|
info.references = references;
|
||||||
info.stateReferences = stateReferences;
|
info.stateReferences = stateReferences;
|
||||||
|
|
@ -788,28 +823,30 @@ void registerValidPath(const Transaction & txn,
|
||||||
void registerValidPaths(const Transaction & txn, const ValidPathInfos & infos)
|
void registerValidPaths(const Transaction & txn, const ValidPathInfos & infos)
|
||||||
{
|
{
|
||||||
PathSet newPaths;
|
PathSet newPaths;
|
||||||
for (ValidPathInfos::const_iterator i = infos.begin();
|
for (ValidPathInfos::const_iterator i = infos.begin(); i != infos.end(); ++i)
|
||||||
i != infos.end(); ++i)
|
|
||||||
newPaths.insert(i->path);
|
newPaths.insert(i->path);
|
||||||
|
|
||||||
for (ValidPathInfos::const_iterator i = infos.begin();
|
for (ValidPathInfos::const_iterator i = infos.begin(); i != infos.end(); ++i)
|
||||||
i != infos.end(); ++i)
|
|
||||||
{
|
{
|
||||||
assertStorePath(i->path);
|
assertStorePath(i->path);
|
||||||
|
|
||||||
debug(format("registering path `%1%'") % i->path);
|
debug(format("registering path `%1%'") % i->path);
|
||||||
setHash(txn, i->path, i->hash);
|
setHash(txn, i->path, i->hash);
|
||||||
|
|
||||||
|
if (i->statePath != "")
|
||||||
|
setStateHash(txn, i->statePath, Hash()); //the hash value in the db now becomes empty, but if the key exists, we know that the state path is valid
|
||||||
|
|
||||||
setReferences(txn, i->path, i->references, i->stateReferences);
|
setReferences(txn, i->path, i->references, i->stateReferences);
|
||||||
|
|
||||||
/* Check that all referenced paths are also valid (or about to
|
/* Check that all referenced paths are also valid (or about to) become valid). */
|
||||||
become valid). */
|
|
||||||
for (PathSet::iterator j = i->references.begin();
|
for (PathSet::iterator j = i->references.begin();
|
||||||
j != i->references.end(); ++j)
|
j != i->references.end(); ++j)
|
||||||
if (!isValidPathTxn(txn, *j) && newPaths.find(*j) == newPaths.end())
|
if (!isValidPathTxn(txn, *j) && newPaths.find(*j) == newPaths.end())
|
||||||
throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid")
|
throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid")
|
||||||
% i->path % *j);
|
% i->path % *j);
|
||||||
|
|
||||||
|
//TODO Also do this for stateReferences????
|
||||||
|
|
||||||
setDeriver(txn, i->path, i->deriver);
|
setDeriver(txn, i->path, i->deriver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -817,7 +854,7 @@ void registerValidPaths(const Transaction & txn, const ValidPathInfos & infos)
|
||||||
|
|
||||||
/* Invalidate a path. The caller is responsible for checking that
|
/* Invalidate a path. The caller is responsible for checking that
|
||||||
there are no referrers. */
|
there are no referrers. */
|
||||||
static void invalidatePath(Transaction & txn, const Path & path)
|
static void invalidatePath(Transaction & txn, const Path & path) //TODO Adjust for state paths????
|
||||||
{
|
{
|
||||||
debug(format("unregistering path `%1%'") % path);
|
debug(format("unregistering path `%1%'") % path);
|
||||||
|
|
||||||
|
|
@ -830,7 +867,7 @@ static void invalidatePath(Transaction & txn, const Path & path)
|
||||||
nixDB.delPair(txn, dbDerivers, path); //TODO!!!!! also for state Derivers!!!!!!!!!!!!!!!
|
nixDB.delPair(txn, dbDerivers, path); //TODO!!!!! also for state Derivers!!!!!!!!!!!!!!!
|
||||||
}
|
}
|
||||||
|
|
||||||
nixDB.delPair(txn, dbValidPaths, path); //Always?
|
nixDB.delPair(txn, dbValidPaths, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -868,7 +905,7 @@ Path LocalStore::addToStore(const Path & _srcPath, bool fixed,
|
||||||
canonicalisePathMetaData(dstPath);
|
canonicalisePathMetaData(dstPath);
|
||||||
|
|
||||||
Transaction txn(nixDB);
|
Transaction txn(nixDB);
|
||||||
registerValidPath(txn, dstPath, h, PathSet(), PathSet(), "");
|
registerValidPath(txn, dstPath, "", h, PathSet(), PathSet(), ""); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!! CHECK if the first "" (statepath) is needed here
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -902,7 +939,8 @@ Path LocalStore::addTextToStore(const string & suffix, const string & s,
|
||||||
canonicalisePathMetaData(dstPath);
|
canonicalisePathMetaData(dstPath);
|
||||||
|
|
||||||
Transaction txn(nixDB);
|
Transaction txn(nixDB);
|
||||||
registerValidPath(txn, dstPath, hashPath(htSHA256, dstPath), references, PathSet(), ""); //There are no stateReferences in drvs..... so we dont need to register them (I think)
|
registerValidPath(txn, dstPath, "", hashPath(htSHA256, dstPath), references, PathSet(), ""); //There are no stateReferences in drvs..... so we dont need to register them (I think)
|
||||||
|
//A drvs has also no statepath, so that is ok...
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1107,7 +1145,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
|
||||||
/* !!! if we were clever, we could prevent the hashPath()
|
/* !!! if we were clever, we could prevent the hashPath()
|
||||||
here. */
|
here. */
|
||||||
if (!isValidPath(deriver)) deriver = "";
|
if (!isValidPath(deriver)) deriver = "";
|
||||||
registerValidPath(txn, dstPath,
|
registerValidPath(txn, dstPath, "", //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!! replace "" for a state path ??????
|
||||||
hashPath(htSHA256, dstPath), references, stateReferences, deriver);
|
hashPath(htSHA256, dstPath), references, stateReferences, deriver);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
@ -1183,6 +1221,9 @@ void verifyStore(bool checkContents)
|
||||||
/* "Realisable" paths are those that are valid or have a
|
/* "Realisable" paths are those that are valid or have a
|
||||||
substitute. */
|
substitute. */
|
||||||
PathSet realisablePaths(validPaths);
|
PathSet realisablePaths(validPaths);
|
||||||
|
|
||||||
|
|
||||||
|
//TODO Do also for validStatePaths
|
||||||
|
|
||||||
/* Check that the values of the substitute mappings are valid
|
/* Check that the values of the substitute mappings are valid
|
||||||
paths. */
|
paths. */
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,11 @@ public:
|
||||||
/* Implementations of abstract store API methods. */
|
/* Implementations of abstract store API methods. */
|
||||||
|
|
||||||
bool isValidPath(const Path & path);
|
bool isValidPath(const Path & path);
|
||||||
|
|
||||||
|
bool isValidStatePath(const Path & path);
|
||||||
|
|
||||||
|
bool isValidComponentOrStatePath(const Path & path);
|
||||||
|
|
||||||
Substitutes querySubstitutes(const Path & srcPath);
|
Substitutes querySubstitutes(const Path & srcPath);
|
||||||
|
|
||||||
Hash queryPathHash(const Path & path);
|
Hash queryPathHash(const Path & path);
|
||||||
|
|
@ -115,13 +119,14 @@ void clearSubstitutes();
|
||||||
of the file system contents of the path. The hash must be a
|
of the file system contents of the path. The hash must be a
|
||||||
SHA-256 hash. */
|
SHA-256 hash. */
|
||||||
void registerValidPath(const Transaction & txn,
|
void registerValidPath(const Transaction & txn,
|
||||||
const Path & path, const Hash & hash,
|
const Path & path, const Path & statepath, const Hash & hash,
|
||||||
const PathSet & references, const PathSet & stateReferences,
|
const PathSet & references, const PathSet & stateReferences,
|
||||||
const Path & deriver);
|
const Path & deriver);
|
||||||
|
|
||||||
struct ValidPathInfo
|
struct ValidPathInfo
|
||||||
{
|
{
|
||||||
Path path;
|
Path path;
|
||||||
|
Path statePath;
|
||||||
Path deriver;
|
Path deriver;
|
||||||
Hash hash;
|
Hash hash;
|
||||||
PathSet references;
|
PathSet references;
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,23 @@ bool RemoteStore::isValidPath(const Path & path)
|
||||||
return reply != 0;
|
return reply != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RemoteStore::isValidStatePath(const Path & path)
|
||||||
|
{
|
||||||
|
writeInt(wopIsValidStatePath, to);
|
||||||
|
writeString(path, to);
|
||||||
|
processStderr();
|
||||||
|
unsigned int reply = readInt(from);
|
||||||
|
return reply != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoteStore::isValidComponentOrStatePath(const Path & path)
|
||||||
|
{
|
||||||
|
writeInt(wopIsValidComponentOrStatePath, to);
|
||||||
|
writeString(path, to);
|
||||||
|
processStderr();
|
||||||
|
unsigned int reply = readInt(from);
|
||||||
|
return reply != 0;
|
||||||
|
}
|
||||||
|
|
||||||
Substitutes RemoteStore::querySubstitutes(const Path & path)
|
Substitutes RemoteStore::querySubstitutes(const Path & path)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,10 @@ public:
|
||||||
/* Implementations of abstract store API methods. */
|
/* Implementations of abstract store API methods. */
|
||||||
|
|
||||||
bool isValidPath(const Path & path);
|
bool isValidPath(const Path & path);
|
||||||
|
|
||||||
|
bool isValidStatePath(const Path & path);
|
||||||
|
|
||||||
|
bool isValidComponentOrStatePath(const Path & path);
|
||||||
|
|
||||||
Substitutes querySubstitutes(const Path & path);
|
Substitutes querySubstitutes(const Path & path);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,12 @@ public:
|
||||||
|
|
||||||
/* Checks whether a path is valid. */
|
/* Checks whether a path is valid. */
|
||||||
virtual bool isValidPath(const Path & path) = 0;
|
virtual bool isValidPath(const Path & path) = 0;
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
virtual bool isValidStatePath(const Path & path) = 0;
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
virtual bool isValidComponentOrStatePath(const Path & path) = 0;
|
||||||
|
|
||||||
/* Return the substitutes for the given path. */
|
/* Return the substitutes for the given path. */
|
||||||
virtual Substitutes querySubstitutes(const Path & path) = 0;
|
virtual Substitutes querySubstitutes(const Path & path) = 0;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ namespace nix {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
wopQuit,
|
wopQuit,
|
||||||
wopIsValidPath,
|
wopIsValidPath,
|
||||||
|
wopIsValidStatePath,
|
||||||
|
wopIsValidComponentOrStatePath,
|
||||||
wopQuerySubstitutes,
|
wopQuerySubstitutes,
|
||||||
wopHasSubstitutes,
|
wopHasSubstitutes,
|
||||||
wopQueryPathHash,
|
wopQueryPathHash,
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,24 @@ static void performOp(Source & from, Sink & to, unsigned int op)
|
||||||
writeInt(result, to);
|
writeInt(result, to);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case wopIsValidStatePath: {
|
||||||
|
Path path = readStorePath(from);
|
||||||
|
startWork();
|
||||||
|
bool result = store->isValidStatePath(path);
|
||||||
|
stopWork();
|
||||||
|
writeInt(result, to);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case wopIsValidComponentOrStatePath: {
|
||||||
|
Path path = readStorePath(from);
|
||||||
|
startWork();
|
||||||
|
bool result = store->isValidComponentOrStatePath(path);
|
||||||
|
stopWork();
|
||||||
|
writeInt(result, to);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case wopHasSubstitutes: {
|
case wopHasSubstitutes: {
|
||||||
Path path = readStorePath(from);
|
Path path = readStorePath(from);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue