diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index e58e6563f..dccdba533 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -167,6 +167,9 @@ public: files with the same contents. */ void optimiseStore(OptimiseStats & stats); + /* Generic variant of the above method. */ + void optimiseStore(); + /* Optimise a single store path. */ void optimisePath(const Path & path); diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 208d9688e..dd18d66fa 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -225,6 +225,22 @@ void LocalStore::optimiseStore(OptimiseStats & stats) } } +static string showBytes(unsigned long long bytes) +{ + return (format("%.2f MiB") % (bytes / (1024.0 * 1024.0))).str(); +} + +void LocalStore::optimiseStore() +{ + OptimiseStats stats; + + optimiseStore(stats); + + printMsg(lvlError, + format("%1% freed by hard-linking %2% files") + % showBytes(stats.bytesFreed) + % stats.filesLinked); +} void LocalStore::optimisePath(const Path & path) { diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 8ef673783..a0e9f2241 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -579,6 +579,13 @@ void RemoteStore::clearFailedPaths(const PathSet & paths) readInt(from); } +void RemoteStore::optimiseStore() +{ + openConnection(); + writeInt(wopOptimiseStore, to); + processStderr(); + readInt(from); +} void RemoteStore::processStderr(Sink * sink, Source * source) { diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index b01014764..98774c10b 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -82,7 +82,9 @@ public: PathSet queryFailedPaths(); void clearFailedPaths(const PathSet & paths); - + + void optimiseStore(); + private: AutoCloseFD fdSocket; FdSink to; diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index b635fee2c..3109f100e 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -250,6 +250,10 @@ public: `nix-store --register-validity'. */ string makeValidityRegistration(const PathSet & paths, bool showDerivers, bool showHash); + + /* Optimise the disk space usage of the Nix store by hard-linking files + with the same contents. */ + virtual void optimiseStore() = 0; }; diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index c7d3a726a..4b040b77c 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -42,6 +42,7 @@ typedef enum { wopQueryValidPaths = 31, wopQuerySubstitutablePaths = 32, wopQueryValidDerivers = 33, + wopOptimiseStore = 34 } WorkerOp; diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index ced356c34..0f3235d76 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -508,6 +508,13 @@ static void performOp(bool trusted, unsigned int clientVersion, break; } + case wopOptimiseStore: + startWork(); + store->optimiseStore(); + stopWork(); + writeInt(1, to); + break; + default: throw Error(format("invalid operation %1%") % op); } diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 8c3744824..51839fac1 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -823,16 +823,6 @@ static void opRepairPath(Strings opFlags, Strings opArgs) } } - -static void showOptimiseStats(OptimiseStats & stats) -{ - printMsg(lvlError, - format("%1% freed by hard-linking %2% files") - % showBytes(stats.bytesFreed) - % stats.filesLinked); -} - - /* Optimise the disk space usage of the Nix store by hard-linking files with the same contents. */ static void opOptimise(Strings opFlags, Strings opArgs) @@ -840,17 +830,9 @@ static void opOptimise(Strings opFlags, Strings opArgs) if (!opArgs.empty() || !opFlags.empty()) throw UsageError("no arguments expected"); - OptimiseStats stats; - try { - ensureLocalStore().optimiseStore(stats); - } catch (...) { - showOptimiseStats(stats); - throw; - } - showOptimiseStats(stats); + store->optimiseStore(); } - static void opQueryFailedPaths(Strings opFlags, Strings opArgs) { if (!opArgs.empty() || !opFlags.empty())