forked from lix-project/lix
Reserve some disk space for the garbage collector
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. This actually revives some old code from the Berkeley DB days. Fixes #27.
This commit is contained in:
parent
2c26985835
commit
4bc4da331a
|
@ -195,7 +195,7 @@ void checkStoreNotSymlink()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LocalStore::LocalStore()
|
LocalStore::LocalStore(bool reserveSpace)
|
||||||
{
|
{
|
||||||
substitutablePathsLoaded = false;
|
substitutablePathsLoaded = false;
|
||||||
|
|
||||||
|
@ -221,6 +221,24 @@ LocalStore::LocalStore()
|
||||||
|
|
||||||
checkStoreNotSymlink();
|
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
|
/* Acquire the big fat lock in shared mode to make sure that no
|
||||||
schema upgrade is in progress. */
|
schema upgrade is in progress. */
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -91,7 +91,7 @@ public:
|
||||||
|
|
||||||
/* Initialise the local store, upgrading the schema if
|
/* Initialise the local store, upgrading the schema if
|
||||||
necessary. */
|
necessary. */
|
||||||
LocalStore();
|
LocalStore(bool reserveSpace = true);
|
||||||
|
|
||||||
~LocalStore();
|
~LocalStore();
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ RemoteStore::RemoteStore()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RemoteStore::openConnection()
|
void RemoteStore::openConnection(bool reserveSpace)
|
||||||
{
|
{
|
||||||
if (initialised) return;
|
if (initialised) return;
|
||||||
initialised = true;
|
initialised = true;
|
||||||
|
@ -75,6 +75,8 @@ void RemoteStore::openConnection()
|
||||||
if (GET_PROTOCOL_MAJOR(daemonVersion) != GET_PROTOCOL_MAJOR(PROTOCOL_VERSION))
|
if (GET_PROTOCOL_MAJOR(daemonVersion) != GET_PROTOCOL_MAJOR(PROTOCOL_VERSION))
|
||||||
throw Error("Nix daemon protocol version not supported");
|
throw Error("Nix daemon protocol version not supported");
|
||||||
writeInt(PROTOCOL_VERSION, to);
|
writeInt(PROTOCOL_VERSION, to);
|
||||||
|
if (GET_PROTOCOL_MINOR(daemonVersion) >= 11)
|
||||||
|
writeInt(reserveSpace, to);
|
||||||
processStderr();
|
processStderr();
|
||||||
}
|
}
|
||||||
catch (Error & e) {
|
catch (Error & e) {
|
||||||
|
@ -462,7 +464,7 @@ Roots RemoteStore::findRoots()
|
||||||
|
|
||||||
void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
|
void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
|
||||||
{
|
{
|
||||||
openConnection();
|
openConnection(false);
|
||||||
|
|
||||||
writeInt(wopCollectGarbage, to);
|
writeInt(wopCollectGarbage, to);
|
||||||
writeInt(options.action, to);
|
writeInt(options.action, to);
|
||||||
|
|
|
@ -86,7 +86,7 @@ private:
|
||||||
unsigned int daemonVersion;
|
unsigned int daemonVersion;
|
||||||
bool initialised;
|
bool initialised;
|
||||||
|
|
||||||
void openConnection();
|
void openConnection(bool reserveSpace = true);
|
||||||
|
|
||||||
void processStderr(Sink * sink = 0, Source * source = 0);
|
void processStderr(Sink * sink = 0, Source * source = 0);
|
||||||
|
|
||||||
|
|
|
@ -322,10 +322,10 @@ namespace nix {
|
||||||
boost::shared_ptr<StoreAPI> store;
|
boost::shared_ptr<StoreAPI> store;
|
||||||
|
|
||||||
|
|
||||||
boost::shared_ptr<StoreAPI> openStore()
|
boost::shared_ptr<StoreAPI> openStore(bool reserveSpace)
|
||||||
{
|
{
|
||||||
if (getEnv("NIX_REMOTE") == "")
|
if (getEnv("NIX_REMOTE") == "")
|
||||||
return boost::shared_ptr<StoreAPI>(new LocalStore());
|
return boost::shared_ptr<StoreAPI>(new LocalStore(reserveSpace));
|
||||||
else
|
else
|
||||||
return boost::shared_ptr<StoreAPI>(new RemoteStore());
|
return boost::shared_ptr<StoreAPI>(new RemoteStore());
|
||||||
}
|
}
|
||||||
|
|
|
@ -327,7 +327,7 @@ extern boost::shared_ptr<StoreAPI> store;
|
||||||
|
|
||||||
/* Factory method: open the Nix database, either through the local or
|
/* Factory method: open the Nix database, either through the local or
|
||||||
remote implementation. */
|
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
|
/* Display a set of paths in human-readable form (i.e., between quotes
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace nix {
|
||||||
#define WORKER_MAGIC_1 0x6e697863
|
#define WORKER_MAGIC_1 0x6e697863
|
||||||
#define WORKER_MAGIC_2 0x6478696f
|
#define WORKER_MAGIC_2 0x6478696f
|
||||||
|
|
||||||
#define PROTOCOL_VERSION 0x10a
|
#define PROTOCOL_VERSION 0x10b
|
||||||
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
|
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
|
||||||
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
|
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
|
||||||
|
|
||||||
|
|
|
@ -843,7 +843,7 @@ void run(Strings args)
|
||||||
if (!op) throw UsageError("no operation specified");
|
if (!op) throw UsageError("no operation specified");
|
||||||
|
|
||||||
if (op != opDump && op != opRestore) /* !!! hack */
|
if (op != opDump && op != opRestore) /* !!! hack */
|
||||||
store = openStore();
|
store = openStore(op != opGC);
|
||||||
|
|
||||||
op(opFlags, opArgs);
|
op(opFlags, opArgs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -625,8 +625,12 @@ static void processConnection()
|
||||||
throw Error("if you run `nix-worker' as root, then you MUST set `build-users-group'!");
|
throw Error("if you run `nix-worker' as root, then you MUST set `build-users-group'!");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool reserveSpace = true;
|
||||||
|
if (GET_PROTOCOL_MINOR(clientVersion) >= 11)
|
||||||
|
reserveSpace = readInt(from) != 0;
|
||||||
|
|
||||||
/* Open the store. */
|
/* Open the store. */
|
||||||
store = boost::shared_ptr<StoreAPI>(new LocalStore());
|
store = boost::shared_ptr<StoreAPI>(new LocalStore(reserveSpace));
|
||||||
|
|
||||||
stopWork();
|
stopWork();
|
||||||
to.flush();
|
to.flush();
|
||||||
|
|
Loading…
Reference in a new issue