diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index c7ffb7528..1d654cd67 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -2,7 +2,6 @@ #include "misc.hh" #include "pathlocks.hh" #include "local-store.hh" -#include "util.hh" #include diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 769b3be7f..9d3cea7a0 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1,6 +1,5 @@ #include "config.h" #include "local-store.hh" -#include "util.hh" #include "globals.hh" #include "archive.hh" #include "pathlocks.hh" @@ -43,40 +42,37 @@ LocalStore::LocalStore() { substitutablePathsLoaded = false; + schemaPath = nixDBPath + "/schema"; + if (readOnlyMode) return; checkStoreNotSymlink(); - try { - createDirs(nixDBPath + "/info"); - createDirs(nixDBPath + "/referrer"); - } catch (Error & e) { - // !!! fix access check - printMsg(lvlTalkative, "cannot access Nix database; continuing anyway"); - readOnlyMode = true; - return; - } + Path globalLockPath = nixDBPath + "/big-lock"; + globalLock = open(globalLockPath.c_str(), O_RDWR | O_CREAT, 0666); + if (globalLock == -1) throw SysError(format("opening file `%1%'") % globalLockPath); - int curSchema = 0; - Path schemaFN = nixDBPath + "/schema"; - if (pathExists(schemaFN)) { - string s = readFile(schemaFN); - if (!string2Int(s, curSchema)) - throw Error(format("`%1%' is corrupt") % schemaFN); + if (!lockFile(globalLock, ltRead, false)) { + printMsg(lvlError, "waiting for the big Nix store lock..."); + lockFile(globalLock, ltRead, true); } + createDirs(nixDBPath + "/info"); + createDirs(nixDBPath + "/referrer"); + + //printMsg(lvlTalkative, "cannot access Nix database; continuing anyway"); + //readOnlyMode = true; + + int curSchema = getSchema(); if (curSchema > nixSchemaVersion) throw Error(format("current Nix store schema is version %1%, but I only support %2%") % curSchema % nixSchemaVersion); - - if (curSchema < nixSchemaVersion) { - if (curSchema == 0) /* new store */ - curSchema = nixSchemaVersion; - if (curSchema <= 1) - throw Error("your Nix store is no longer supported"); - if (curSchema <= 4) upgradeStore12(); - writeFile(schemaFN, (format("%1%") % nixSchemaVersion).str()); + if (curSchema == 0) { /* new store */ + curSchema = nixSchemaVersion; + writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str()); } + if (curSchema == 1) throw Error("your Nix store is no longer supported"); + if (curSchema < nixSchemaVersion) upgradeStore12(); } @@ -90,6 +86,18 @@ LocalStore::~LocalStore() } +int LocalStore::getSchema() +{ + int curSchema = 0; + if (pathExists(schemaPath)) { + string s = readFile(schemaPath); + if (!string2Int(s, curSchema)) + throw Error(format("`%1%' is corrupt") % schemaPath); + } + return curSchema; +} + + void copyPath(const Path & src, const Path & dst, PathFilter & filter) { debug(format("copying `%1%' to `%2%'") % src % dst); diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index ead49baae..57d9d765e 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -4,6 +4,7 @@ #include #include "store-api.hh" +#include "util.hh" namespace nix { @@ -114,6 +115,11 @@ public: private: + Path schemaPath; + + /* Lock file used for upgrading. */ + AutoCloseFD globalLock; + /* !!! The cache can grow very big. Maybe it should be pruned every once in a while. */ std::map pathInfoCache; @@ -121,6 +127,8 @@ private: /* Store paths for which the referrers file must be purged. */ PathSet delayedUpdates; + int getSchema(); + void registerValidPath(const ValidPathInfo & info, bool ignoreValidity = false); ValidPathInfo queryPathInfo(const Path & path); diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index d03c4513e..c260f253e 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -1,5 +1,5 @@ -#include "local-store.hh" #include "util.hh" +#include "local-store.hh" #include #include diff --git a/src/libstore/upgrade-schema.cc b/src/libstore/upgrade-schema.cc index b3d691485..6b8358582 100644 --- a/src/libstore/upgrade-schema.cc +++ b/src/libstore/upgrade-schema.cc @@ -3,6 +3,7 @@ #include "util.hh" #include "local-store.hh" #include "globals.hh" +#include "pathlocks.hh" #include @@ -18,8 +19,15 @@ Hash parseHashField(const Path & path, const string & s); meta-information in files. */ void LocalStore::upgradeStore12() { + if (!lockFile(globalLock, ltWrite, false)) { + printMsg(lvlError, "waiting for exclusive access to the Nix store..."); + lockFile(globalLock, ltWrite, true); + } + printMsg(lvlError, "upgrading Nix store to new schema (this may take a while)..."); + if (getSchema() >= nixSchemaVersion) return; /* somebody else beat us to it */ + /* Open the old Nix database and tables. */ Database nixDB; nixDB.open(nixDBPath); @@ -76,6 +84,10 @@ void LocalStore::upgradeStore12() } std::cerr << std::endl; + + writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str()); + + lockFile(globalLock, ltRead, true); }