aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/local-store.cc20
-rw-r--r--src/libstore/local-store.hh2
-rw-r--r--src/libstore/remote-store.cc6
-rw-r--r--src/libstore/remote-store.hh2
-rw-r--r--src/libstore/store-api.cc4
-rw-r--r--src/libstore/store-api.hh2
-rw-r--r--src/libstore/worker-protocol.hh2
-rw-r--r--src/nix-store/nix-store.cc2
-rw-r--r--src/nix-worker/nix-worker.cc6
9 files changed, 35 insertions, 11 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index f04436b7f..1ce62aeaf 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -195,7 +195,7 @@ void checkStoreNotSymlink()
}
-LocalStore::LocalStore()
+LocalStore::LocalStore(bool reserveSpace)
{
substitutablePathsLoaded = false;
@@ -221,6 +221,24 @@ LocalStore::LocalStore()
checkStoreNotSymlink();
+ /* We can't open a SQLite database if the disk is full. Since
+ this prevents the garbage collector from running when it's most
+ needed, we reserve some dummy space that we can free just
+ before doing a garbage collection. */
+ try {
+ Path reservedPath = nixDBPath + "/reserved";
+ if (reserveSpace) {
+ int reservedSize = queryIntSetting("gc-reserved-space", 1024 * 1024);
+ struct stat st;
+ if (stat(reservedPath.c_str(), &st) == -1 ||
+ st.st_size != reservedSize)
+ writeFile(reservedPath, string(reservedSize, 'X'));
+ }
+ else
+ deletePath(reservedPath);
+ } catch (SysError & e) { /* don't care about errors */
+ }
+
/* Acquire the big fat lock in shared mode to make sure that no
schema upgrade is in progress. */
try {
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 8e3cbe5ce..0ff3e7b39 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -91,7 +91,7 @@ public:
/* Initialise the local store, upgrading the schema if
necessary. */
- LocalStore();
+ LocalStore(bool reserveSpace = true);
~LocalStore();
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 0fd759b07..cbcf86054 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -43,7 +43,7 @@ RemoteStore::RemoteStore()
}
-void RemoteStore::openConnection()
+void RemoteStore::openConnection(bool reserveSpace)
{
if (initialised) return;
initialised = true;
@@ -75,6 +75,8 @@ void RemoteStore::openConnection()
if (GET_PROTOCOL_MAJOR(daemonVersion) != GET_PROTOCOL_MAJOR(PROTOCOL_VERSION))
throw Error("Nix daemon protocol version not supported");
writeInt(PROTOCOL_VERSION, to);
+ if (GET_PROTOCOL_MINOR(daemonVersion) >= 11)
+ writeInt(reserveSpace, to);
processStderr();
}
catch (Error & e) {
@@ -462,7 +464,7 @@ Roots RemoteStore::findRoots()
void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
{
- openConnection();
+ openConnection(false);
writeInt(wopCollectGarbage, to);
writeInt(options.action, to);
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index c5853ef53..823e694dd 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -86,7 +86,7 @@ private:
unsigned int daemonVersion;
bool initialised;
- void openConnection();
+ void openConnection(bool reserveSpace = true);
void processStderr(Sink * sink = 0, Source * source = 0);
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index 19bc048ab..b64988268 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -322,10 +322,10 @@ namespace nix {
boost::shared_ptr<StoreAPI> store;
-boost::shared_ptr<StoreAPI> openStore()
+boost::shared_ptr<StoreAPI> openStore(bool reserveSpace)
{
if (getEnv("NIX_REMOTE") == "")
- return boost::shared_ptr<StoreAPI>(new LocalStore());
+ return boost::shared_ptr<StoreAPI>(new LocalStore(reserveSpace));
else
return boost::shared_ptr<StoreAPI>(new RemoteStore());
}
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index a62a64816..fa766d12e 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -327,7 +327,7 @@ extern boost::shared_ptr<StoreAPI> store;
/* Factory method: open the Nix database, either through the local or
remote implementation. */
-boost::shared_ptr<StoreAPI> openStore();
+boost::shared_ptr<StoreAPI> openStore(bool reserveSpace = true);
/* Display a set of paths in human-readable form (i.e., between quotes
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index 6e0aadad4..c1ea7f758 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -8,7 +8,7 @@ namespace nix {
#define WORKER_MAGIC_1 0x6e697863
#define WORKER_MAGIC_2 0x6478696f
-#define PROTOCOL_VERSION 0x10a
+#define PROTOCOL_VERSION 0x10b
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index fa96725b1..36c041682 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -843,7 +843,7 @@ void run(Strings args)
if (!op) throw UsageError("no operation specified");
if (op != opDump && op != opRestore) /* !!! hack */
- store = openStore();
+ store = openStore(op != opGC);
op(opFlags, opArgs);
}
diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc
index c69b9de50..b7bce20bd 100644
--- a/src/nix-worker/nix-worker.cc
+++ b/src/nix-worker/nix-worker.cc
@@ -625,8 +625,12 @@ static void processConnection()
throw Error("if you run `nix-worker' as root, then you MUST set `build-users-group'!");
#endif
+ bool reserveSpace = true;
+ if (GET_PROTOCOL_MINOR(clientVersion) >= 11)
+ reserveSpace = readInt(from) != 0;
+
/* Open the store. */
- store = boost::shared_ptr<StoreAPI>(new LocalStore());
+ store = boost::shared_ptr<StoreAPI>(new LocalStore(reserveSpace));
stopWork();
to.flush();