about summary refs log tree commit diff
path: root/src/libstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/db.cc6
-rw-r--r--src/libstore/store.cc27
2 files changed, 26 insertions, 7 deletions
diff --git a/src/libstore/db.cc b/src/libstore/db.cc
index 82211bd1dee8..6740d6865ab6 100644
--- a/src/libstore/db.cc
+++ b/src/libstore/db.cc
@@ -194,9 +194,9 @@ void Database::open(const string & path)
            number, then run db_recover on the database to remove the
            existing DB environment (since changes only take effect on
            new environments). */
-        env->set_lk_max_locks(4000);
-        env->set_lk_max_lockers(4000);
-        env->set_lk_max_objects(4000);
+        env->set_lk_max_locks(10000);
+        env->set_lk_max_lockers(10000);
+        env->set_lk_max_objects(10000);
         env->set_lk_detect(DB_LOCK_DEFAULT);
 
         /* Dangerous, probably, but from the docs it *seems* that BDB
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index 9f50e597eb34..4b9e807d26c5 100644
--- a/src/libstore/store.cc
+++ b/src/libstore/store.cc
@@ -319,6 +319,9 @@ void setReferences(const Transaction & txn, const Path & 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()));
@@ -454,6 +457,9 @@ void registerSubstitute(const Transaction & txn,
     
     Substitutes subs = readSubstitutes(txn, srcPath);
 
+    if (find(subs.begin(), subs.end(), sub) != subs.end())
+        return;
+
     /* New substitutes take precedence over old ones.  If the
        substitute is already present, it's moved to the front. */
     remove(subs.begin(), subs.end(), sub);
@@ -469,6 +475,9 @@ Substitutes querySubstitutes(const Transaction & txn, const Path & srcPath)
 }
 
 
+static void invalidatePath(Transaction & txn, const Path & path);
+
+
 void clearSubstitutes()
 {
     Transaction txn(nixDB);
@@ -477,10 +486,20 @@ void clearSubstitutes()
     Paths subKeys;
     nixDB.enumTable(txn, dbSubstitutes, subKeys);
     for (Paths::iterator i = subKeys.begin(); i != subKeys.end(); ++i) {
+        
         /* Delete all substitutes for path *i. */
         nixDB.delPair(txn, dbSubstitutes, *i);
+        
+        /* Maintain the cleanup invariant. */
+        if (!isValidPathTxn(txn, *i))
+            invalidatePath(txn, *i);
     }
 
+    /* !!! there should be no referers to any of the invalid
+       substitutable paths.  This should be the case by construction
+       (the only referers can be other invalid substitutable paths,
+       which have all been removed now). */
+    
     txn.commit();
 }
 
@@ -541,7 +560,7 @@ void registerValidPath(const Transaction & txn,
 
 /* Invalidate a path.  The caller is responsible for checking that
    there are no referers. */
-static void invalidatePath(const Path & path, Transaction & txn)
+static void invalidatePath(Transaction & txn, const Path & path)
 {
     debug(format("unregistering path `%1%'") % path);
 
@@ -673,7 +692,7 @@ void deleteFromStore(const Path & _path)
             (referers.size() == 1 &&
                 *referers.begin() != path))
             throw Error(format("cannot delete path `%1%' because it is in use") % path);
-        invalidatePath(path, txn);
+        invalidatePath(txn, path);
     }
     txn.commit();
 
@@ -692,10 +711,10 @@ void verifyStore(bool checkContents)
     for (Paths::iterator i = paths.begin(); i != paths.end(); ++i) {
         if (!pathExists(*i)) {
             printMsg(lvlError, format("path `%1%' disappeared") % *i);
-            invalidatePath(*i, txn);
+            invalidatePath(txn, *i);
         } else if (!isStorePath(*i)) {
             printMsg(lvlError, format("path `%1%' is not in the Nix store") % *i);
-            invalidatePath(*i, txn);
+            invalidatePath(txn, *i);
         } else {
             if (checkContents) {
                 Hash expected = queryHash(txn, *i);