aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/store.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-12-05 11:05:19 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-12-05 11:05:19 +0000
commitcff6fd22ebfbfdbbda9b30c68cb61e25db718147 (patch)
treec23d83656f72f4bc7097c4ba03fa54b853e3ef50 /src/libstore/store.cc
parentfeaab52203a51a4abec23f5d878f6f4dea29dcd5 (diff)
* Allow successors that don't exist but have a substitute.
* Integrity: check in successor / substitute registration whether the target path exists or has a substitute.
Diffstat (limited to 'src/libstore/store.cc')
-rw-r--r--src/libstore/store.cc107
1 files changed, 73 insertions, 34 deletions
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index 2e066a3d4..acdb4708e 100644
--- a/src/libstore/store.cc
+++ b/src/libstore/store.cc
@@ -156,9 +156,35 @@ void copyPath(const Path & src, const Path & dst)
}
+static bool isValidPathTxn(const Path & path, const Transaction & txn)
+{
+ string s;
+ return nixDB.queryString(txn, dbValidPaths, path, s);
+}
+
+
+bool isValidPath(const Path & path)
+{
+ return isValidPathTxn(path, noTxn);
+}
+
+
+static bool isUsablePathTxn(const Path & path, const Transaction & txn)
+{
+ if (isValidPathTxn(path, txn)) return true;
+ Paths subs;
+ nixDB.queryStrings(txn, dbSubstitutes, path, subs);
+ return subs.size() > 0;
+}
+
+
void registerSuccessor(const Transaction & txn,
const Path & srcPath, const Path & sucPath)
{
+ if (!isUsablePathTxn(sucPath, txn)) throw Error(
+ format("path `%1%' cannot be a successor, since it is not usable")
+ % sucPath);
+
Path known;
if (nixDB.queryString(txn, dbSuccessors, srcPath, known) &&
known != sucPath)
@@ -196,6 +222,10 @@ Paths queryPredecessors(const Path & sucPath)
void registerSubstitute(const Path & srcPath, const Path & subPath)
{
+ if (!isValidPathTxn(subPath, noTxn)) throw Error(
+ format("path `%1%' cannot be a substitute, since it is not valid")
+ % subPath);
+
Transaction txn(nixDB);
Paths subs;
@@ -236,13 +266,6 @@ void registerValidPath(const Transaction & txn, const Path & _path)
}
-bool isValidPath(const Path & path)
-{
- string s;
- return nixDB.queryString(noTxn, dbValidPaths, path, s);
-}
-
-
static void setOrClearStrings(Transaction & txn,
TableId table, const string & key, const Strings & value)
{
@@ -277,6 +300,12 @@ static void invalidatePath(const Path & path, Transaction & txn)
throw Error("integrity error in substitutes mapping");
subs.remove(path);
setOrClearStrings(txn, dbSubstitutes, *i, subs);
+
+ /* If path *i now has no substitutes left, and is not valid,
+ then it too should be invalidated. This is because it may
+ be a substitute or successor. */
+ if (subs.size() == 0 && !isValidPathTxn(*i, txn))
+ invalidatePath(*i, txn);
}
nixDB.delPair(txn, dbSubstitutesRev, path);
}
@@ -367,8 +396,7 @@ void verifyStore()
PathSet validPaths;
nixDB.enumTable(txn, dbValidPaths, paths);
- for (Paths::iterator i = paths.begin(); i != paths.end(); ++i)
- {
+ for (Paths::iterator i = paths.begin(); i != paths.end(); ++i) {
Path path = *i;
if (!pathExists(path)) {
debug(format("path `%1%' disappeared") % path);
@@ -377,32 +405,14 @@ void verifyStore()
validPaths.insert(path);
}
- /* Check that the values of the successor mappings are valid
- paths. */
- Paths sucs;
- nixDB.enumTable(txn, dbSuccessors, sucs);
- for (Paths::iterator i = sucs.begin(); i != sucs.end(); ++i) {
- /* Note that *i itself does not have to be valid, just its
- successor. */
- Path sucPath;
- if (nixDB.queryString(txn, dbSuccessors, *i, sucPath) &&
- validPaths.find(sucPath) == validPaths.end())
- {
- debug(format("found successor mapping to non-existent path `%1%'") % sucPath);
- nixDB.delPair(txn, dbSuccessors, *i);
- }
- }
+ /* !!! the code below does not allow transitive substitutes.
+ I.e., if B is a substitute of A, then B must be a valid path.
+ B cannot itself be invalid but have a substitute. */
- /* Check that the keys of the reverse successor mappings are valid
- paths. */
- Paths rsucs;
- nixDB.enumTable(txn, dbSuccessorsRev, rsucs);
- for (Paths::iterator i = rsucs.begin(); i != rsucs.end(); ++i) {
- if (validPaths.find(*i) == validPaths.end()) {
- debug(format("found reverse successor mapping for non-existent path `%1%'") % *i);
- nixDB.delPair(txn, dbSuccessorsRev, *i);
- }
- }
+ /* "Usable" paths are those that are valid or have a substitute.
+ These are the paths that are allowed to appear in the
+ right-hand side of a sute mapping. */
+ PathSet usablePaths(validPaths);
/* Check that the values of the substitute mappings are valid
paths. */
@@ -418,6 +428,8 @@ void verifyStore()
subPaths2.push_back(*j);
if (subPaths.size() != subPaths2.size())
setOrClearStrings(txn, dbSubstitutes, *i, subPaths2);
+ if (subPaths2.size() > 0)
+ usablePaths.insert(*i);
}
/* Check that the keys of the reverse substitute mappings are
@@ -431,5 +443,32 @@ void verifyStore()
}
}
+ /* Check that the values of the successor mappings are usable
+ paths. */
+ Paths sucs;
+ nixDB.enumTable(txn, dbSuccessors, sucs);
+ for (Paths::iterator i = sucs.begin(); i != sucs.end(); ++i) {
+ /* Note that *i itself does not have to be valid, just its
+ successor. */
+ Path sucPath;
+ if (nixDB.queryString(txn, dbSuccessors, *i, sucPath) &&
+ usablePaths.find(sucPath) == usablePaths.end())
+ {
+ debug(format("found successor mapping to non-existent path `%1%'") % sucPath);
+ nixDB.delPair(txn, dbSuccessors, *i);
+ }
+ }
+
+ /* Check that the keys of the reverse successor mappings are valid
+ paths. */
+ Paths rsucs;
+ nixDB.enumTable(txn, dbSuccessorsRev, rsucs);
+ for (Paths::iterator i = rsucs.begin(); i != rsucs.end(); ++i) {
+ if (usablePaths.find(*i) == usablePaths.end()) {
+ debug(format("found reverse successor mapping for non-existent path `%1%'") % *i);
+ nixDB.delPair(txn, dbSuccessorsRev, *i);
+ }
+ }
+
txn.commit();
}