* Added an option "fsync-metadata" to fsync() changes to

/nix/var/nix/db.
* Removed the function writeStringToFile since it does (almost) the
  same thing as writeFile.
This commit is contained in:
Eelco Dolstra 2010-01-29 12:22:58 +00:00
parent ad529fb89f
commit 07ffdc2862
6 changed files with 37 additions and 28 deletions

View file

@ -233,7 +233,17 @@ build-use-chroot = /dev /proc /bin</programlisting>
<filename>configure</filename> at build time.</para></listitem> <filename>configure</filename> at build time.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry><term><literal>fsync-metadata</literal></term>
<listitem><para>If set to <literal>true</literal>, changes to the
Nix store metadata (in <filename>/nix/var/nix/db</filename>) are
synchronously flushed to disk. This improves robustness in case
of system crashes, but reduces performance. The default is
<literal>false</literal>.</para></listitem>
</varlistentry>
</variablelist> </variablelist>

View file

@ -1318,18 +1318,18 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook()
string s; string s;
foreach (PathSet::iterator, i, allInputs) s += *i + "\n"; foreach (PathSet::iterator, i, allInputs) s += *i + "\n";
writeStringToFile(inputListFN, s); writeFile(inputListFN, s);
/* The `outputs' file lists all outputs that have to be copied /* The `outputs' file lists all outputs that have to be copied
from the remote system. */ from the remote system. */
s = ""; s = "";
foreach (DerivationOutputs::iterator, i, drv.outputs) foreach (DerivationOutputs::iterator, i, drv.outputs)
s += i->second.path + "\n"; s += i->second.path + "\n";
writeStringToFile(outputListFN, s); writeFile(outputListFN, s);
/* The `references' file has exactly the format accepted by /* The `references' file has exactly the format accepted by
`nix-store --register-validity'. */ `nix-store --register-validity'. */
writeStringToFile(referencesFN, writeFile(referencesFN,
makeValidityRegistration(allInputs, true, false)); makeValidityRegistration(allInputs, true, false));
/* Tell the hook to proceed. */ /* Tell the hook to proceed. */
@ -1493,7 +1493,7 @@ void DerivationGoal::startBuilder()
} }
/* Write closure info to `fileName'. */ /* Write closure info to `fileName'. */
writeStringToFile(tmpDir + "/" + fileName, writeFile(tmpDir + "/" + fileName,
makeValidityRegistration(paths, false, false)); makeValidityRegistration(paths, false, false));
} }
@ -1570,7 +1570,7 @@ void DerivationGoal::startBuilder()
support Samba-in-QEMU. */ support Samba-in-QEMU. */
createDirs(chrootRootDir + "/etc"); createDirs(chrootRootDir + "/etc");
writeStringToFile(chrootRootDir + "/etc/passwd", writeFile(chrootRootDir + "/etc/passwd",
(format( (format(
"nixbld:x:%1%:65534:Nix build user:/:/noshell\n" "nixbld:x:%1%:65534:Nix build user:/:/noshell\n"
"nobody:x:65534:65534:Nobody:/:/noshell\n") "nobody:x:65534:65534:Nobody:/:/noshell\n")

View file

@ -89,6 +89,8 @@ LocalStore::LocalStore()
} }
if (curSchema == 1) throw Error("your Nix store is no longer supported"); if (curSchema == 1) throw Error("your Nix store is no longer supported");
if (curSchema < nixSchemaVersion) upgradeStore12(); if (curSchema < nixSchemaVersion) upgradeStore12();
doFsync = queryBoolSetting("fsync-metadata", false);
} }
@ -222,7 +224,7 @@ static Path tmpFileForAtomicUpdate(const Path & path)
} }
static void appendReferrer(const Path & from, const Path & to, bool lock) void LocalStore::appendReferrer(const Path & from, const Path & to, bool lock)
{ {
Path referrersFile = referrersFileFor(from); Path referrersFile = referrersFileFor(from);
@ -237,6 +239,8 @@ static void appendReferrer(const Path & from, const Path & to, bool lock)
string s = " " + to; string s = " " + to;
writeFull(fd, (const unsigned char *) s.c_str(), s.size()); writeFull(fd, (const unsigned char *) s.c_str(), s.size());
if (doFsync) fdatasync(fd);
} }
@ -267,6 +271,8 @@ void LocalStore::rewriteReferrers(const Path & path, bool purge, PathSet referre
writeFull(fd, (const unsigned char *) s.c_str(), s.size()); writeFull(fd, (const unsigned char *) s.c_str(), s.size());
if (doFsync) fdatasync(fd);
fd.close(); /* for Windows; can't rename open file */ fd.close(); /* for Windows; can't rename open file */
if (rename(tmpFile.c_str(), referrersFile.c_str()) == -1) if (rename(tmpFile.c_str(), referrersFile.c_str()) == -1)
@ -347,7 +353,7 @@ void LocalStore::registerValidPath(const ValidPathInfo & info, bool ignoreValidi
/* Atomically rewrite the info file. */ /* Atomically rewrite the info file. */
Path tmpFile = tmpFileForAtomicUpdate(infoFile); Path tmpFile = tmpFileForAtomicUpdate(infoFile);
writeFile(tmpFile, s); writeFile(tmpFile, s, doFsync);
if (rename(tmpFile.c_str(), infoFile.c_str()) == -1) if (rename(tmpFile.c_str(), infoFile.c_str()) == -1)
throw SysError(format("cannot rename `%1%' to `%2%'") % tmpFile % infoFile); throw SysError(format("cannot rename `%1%' to `%2%'") % tmpFile % infoFile);
@ -737,7 +743,7 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name,
StringSource source(dump); StringSource source(dump);
restorePath(dstPath, source); restorePath(dstPath, source);
} else } else
writeStringToFile(dstPath, dump); writeFile(dstPath, dump);
canonicalisePathMetaData(dstPath); canonicalisePathMetaData(dstPath);
@ -792,7 +798,7 @@ Path LocalStore::addTextToStore(const string & name, const string & s,
if (pathExists(dstPath)) deletePathWrapped(dstPath); if (pathExists(dstPath)) deletePathWrapped(dstPath);
writeStringToFile(dstPath, s); writeFile(dstPath, s);
canonicalisePathMetaData(dstPath); canonicalisePathMetaData(dstPath);
@ -871,7 +877,7 @@ void LocalStore::exportPath(const Path & path, bool sign,
Path tmpDir = createTempDir(); Path tmpDir = createTempDir();
AutoDelete delTmp(tmpDir); AutoDelete delTmp(tmpDir);
Path hashFile = tmpDir + "/hash"; Path hashFile = tmpDir + "/hash";
writeStringToFile(hashFile, printHash(hash)); writeFile(hashFile, printHash(hash));
Path secretKey = nixConfDir + "/signing-key.sec"; Path secretKey = nixConfDir + "/signing-key.sec";
checkSecrecy(secretKey); checkSecrecy(secretKey);
@ -947,7 +953,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
if (requireSignature) { if (requireSignature) {
Path sigFile = tmpDir + "/sig"; Path sigFile = tmpDir + "/sig";
writeStringToFile(sigFile, signature); writeFile(sigFile, signature);
Strings args; Strings args;
args.push_back("rsautl"); args.push_back("rsautl");

View file

@ -158,12 +158,17 @@ private:
/* Store paths for which the referrers file must be purged. */ /* Store paths for which the referrers file must be purged. */
PathSet delayedUpdates; PathSet delayedUpdates;
/* Whether to do an fsync() after writing Nix metadata. */
bool doFsync;
int getSchema(); int getSchema();
void registerValidPath(const ValidPathInfo & info, bool ignoreValidity = false); void registerValidPath(const ValidPathInfo & info, bool ignoreValidity = false);
ValidPathInfo queryPathInfo(const Path & path, bool ignoreErrors = false); ValidPathInfo queryPathInfo(const Path & path, bool ignoreErrors = false);
void appendReferrer(const Path & from, const Path & to, bool lock);
void rewriteReferrers(const Path & path, bool purge, PathSet referrers); void rewriteReferrers(const Path & path, bool purge, PathSet referrers);
void flushDelayedUpdates(); void flushDelayedUpdates();

View file

@ -15,6 +15,7 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h>
#include "util.hh" #include "util.hh"
@ -220,12 +221,13 @@ string readFile(const Path & path)
} }
void writeFile(const Path & path, const string & s) void writeFile(const Path & path, const string & s, bool doFsync)
{ {
AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666); AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666);
if (fd == -1) if (fd == -1)
throw SysError(format("opening file `%1%'") % path); throw SysError(format("opening file `%1%'") % path);
writeFull(fd, (unsigned char *) s.c_str(), s.size()); writeFull(fd, (unsigned char *) s.c_str(), s.size());
if (doFsync) fdatasync(fd);
} }
@ -413,16 +415,6 @@ Paths createDirs(const Path & path)
} }
void writeStringToFile(const Path & path, const string & s)
{
AutoCloseFD fd(open(path.c_str(),
O_CREAT | O_EXCL | O_WRONLY, 0666));
if (fd == -1)
throw SysError(format("creating file `%1%'") % path);
writeFull(fd, (unsigned char *) s.c_str(), s.size());
}
LogType logType = ltPretty; LogType logType = ltPretty;
Verbosity verbosity = lvlInfo; Verbosity verbosity = lvlInfo;

View file

@ -62,7 +62,7 @@ string readFile(int fd);
string readFile(const Path & path); string readFile(const Path & path);
/* Write a string to a file. */ /* Write a string to a file. */
void writeFile(const Path & path, const string & s); void writeFile(const Path & path, const string & s, bool doFsync = false);
/* Read a line from a file descriptor. */ /* Read a line from a file descriptor. */
string readLine(int fd); string readLine(int fd);
@ -93,10 +93,6 @@ Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
list of created directories, in order of creation. */ list of created directories, in order of creation. */
Paths createDirs(const Path & path); Paths createDirs(const Path & path);
/* Create a file and write the given text to it. The file is written
in binary mode (i.e., no end-of-line conversions). The path should
not already exist. */
void writeStringToFile(const Path & path, const string & s);
template<class T, class A> template<class T, class A>
T singleton(const A & a) T singleton(const A & a)