1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-25 19:51:00 +01:00

* Conversion to a BDB-free store. Meta-information for each valid

path (content hash, references, deriver) is now stored in
  /nix/var/nix/db/meta/<base-path>.info.  The referrers are stored
  separately in /nix/var/nix/db/meta/<base-path>.referrers.  This is
  done because the referrers can change, which the info file is in
  principle immutable.  The referrers must also be updated efficiently
  to prevent a regression of NIX-23 (quadratic complexity updating the
  referrers during garbage collection).

  This is just the conversion code, the rest of the code still uses
  BDB.
This commit is contained in:
Eelco Dolstra 2008-03-03 15:29:03 +00:00
parent f5e6c9bcfd
commit 91313011f9
2 changed files with 90 additions and 14 deletions

View file

@ -16,6 +16,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>
#include <fcntl.h> // !!! remove
namespace nix {
@ -58,6 +59,7 @@ static TableId dbDerivers = 0;
static void upgradeStore09();
static void upgradeStore11();
static void upgradeStore12();
void checkStoreNotSymlink()
@ -133,6 +135,7 @@ LocalStore::LocalStore(bool reserveSpace)
throw Error("your Nix store is no longer supported");
if (curSchema <= 2) upgradeStore09();
if (curSchema <= 3) upgradeStore11();
if (curSchema <= 4) upgradeStore12();
writeFile(schemaFN, (format("%1%") % nixSchemaVersion).str());
}
}
@ -328,7 +331,7 @@ void setReferences(const Transaction & txn, const Path & storePath,
}
void queryReferences(const Transaction & txn,
void oldQueryReferences(const Transaction & txn,
const Path & storePath, PathSet & references)
{
Paths references2;
@ -342,7 +345,7 @@ void queryReferences(const Transaction & txn,
void LocalStore::queryReferences(const Path & storePath,
PathSet & references)
{
nix::queryReferences(noTxn, storePath, references);
oldQueryReferences(noTxn, storePath, references);
}
@ -375,7 +378,7 @@ void setDeriver(const Transaction & txn, const Path & storePath,
}
static Path queryDeriver(const Transaction & txn, const Path & storePath)
static Path oldQueryDeriver(const Transaction & txn, const Path & storePath)
{
if (!isValidPathTxn(txn, storePath))
throw Error(format("path `%1%' is not valid") % storePath);
@ -389,7 +392,7 @@ static Path queryDeriver(const Transaction & txn, const Path & storePath)
Path LocalStore::queryDeriver(const Path & path)
{
return nix::queryDeriver(noTxn, path);
return oldQueryDeriver(noTxn, path);
}
@ -423,7 +426,7 @@ bool LocalStore::hasSubstitutes(const Path & path)
}
static void setHash(const Transaction & txn, const Path & storePath,
static void oldSetHash(const Transaction & txn, const Path & storePath,
const Hash & hash)
{
assert(hash.type == htSHA256);
@ -431,7 +434,7 @@ static void setHash(const Transaction & txn, const Path & storePath,
}
static Hash queryHash(const Transaction & txn, const Path & storePath)
static Hash oldQueryHash(const Transaction & txn, const Path & storePath)
{
string s;
nixDB.queryString(txn, dbValidPaths, storePath, s);
@ -451,7 +454,7 @@ Hash LocalStore::queryPathHash(const Path & path)
{
if (!isValidPath(path))
throw Error(format("path `%1%' is not valid") % path);
return queryHash(noTxn, path);
return oldQueryHash(noTxn, path);
}
@ -484,7 +487,7 @@ void registerValidPaths(const Transaction & txn,
assertStorePath(i->path);
debug(format("registering path `%1%'") % i->path);
setHash(txn, i->path, i->hash);
oldSetHash(txn, i->path, i->hash);
setReferences(txn, i->path, i->references);
@ -834,7 +837,7 @@ void verifyStore(bool checkContents)
} else {
if (checkContents) {
debug(format("checking contents of `%1%'") % *i);
Hash expected = queryHash(txn, *i);
Hash expected = oldQueryHash(txn, *i);
Hash current = hashPath(expected.type, *i);
if (current != expected) {
printMsg(lvlError, format("path `%1%' was modified! "
@ -864,7 +867,7 @@ void verifyStore(bool checkContents)
nixDB.delPair(txn, dbDerivers, *i);
}
else {
Path deriver = queryDeriver(txn, *i);
Path deriver = oldQueryDeriver(txn, *i);
if (!isStorePath(deriver)) {
printMsg(lvlError, format("removing corrupt deriver `%1%' for `%2%'")
% deriver % *i);
@ -888,7 +891,7 @@ void verifyStore(bool checkContents)
}
else {
PathSet references;
queryReferences(txn, *i, references);
oldQueryReferences(txn, *i, references);
for (PathSet::iterator j = references.begin();
j != references.end(); ++j)
{
@ -936,7 +939,7 @@ void verifyStore(bool checkContents)
else {
PathSet references;
queryReferences(txn, from, references);
oldQueryReferences(txn, from, references);
if (find(references.begin(), references.end(), to) == references.end()) {
printMsg(lvlError, format("adding missing referrer mapping from `%1%' to `%2%'")
% from % to);
@ -1144,4 +1147,77 @@ static void upgradeStore11()
}
Path metaFileFor(const Path & path)
{
string baseName = baseNameOf(path);
return (format("%1%/meta/%2%") % nixDBPath % baseName).str();
}
/* !!! move to util.cc */
void appendFile(const Path & path, const string & s)
{
AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
if (fd == -1)
throw SysError(format("opening file `%1%'") % path);
writeFull(fd, (unsigned char *) s.c_str(), s.size());
}
void newRegisterValidPath(const Path & path,
const Hash & hash, const PathSet & references,
const Path & deriver)
{
Path infoFile = metaFileFor(path) + ".info";
string refs;
for (PathSet::const_iterator i = references.begin(); i != references.end(); ++i) {
if (!refs.empty()) refs += " ";
refs += *i;
/* Update the referrer mapping for *i. This must be done
before the info file is written to maintain the invariant
that if `path' is a valid path, then all its references
have referrer mappings back to `path'. A " " is prefixed
to separate it from the previous entry. It's not suffixed
to deal with interrupted partial writes to this file. */
Path referrersFile = metaFileFor(*i) + ".referrers";
/* !!! locking */
appendFile(referrersFile, " " + path);
}
string info = (format(
"Hash: sha256:%1%\n"
"References: %2%\n"
"Deriver: %3%\n"
"Registered-At: %4%\n")
% printHash(hash) % refs % deriver % time(0)).str();
// !!! atomicity
writeFile(infoFile, info);
}
/* Upgrade from schema 4 (Nix 0.11) to schema 5 (Nix >= 0.12). The
old schema uses Berkeley DB, the new one stores store path
meta-information in files. */
static void upgradeStore12()
{
printMsg(lvlError, "upgrading Nix store to new schema (this may take a while)...");
Paths validPaths;
nixDB.enumTable(noTxn, dbValidPaths, validPaths);
for (Paths::iterator i = validPaths.begin(); i != validPaths.end(); ++i) {
Hash hash = oldQueryHash(noTxn, *i);
PathSet references; oldQueryReferences(noTxn, *i, references);
Path deriver = oldQueryDeriver(noTxn, *i);
newRegisterValidPath(*i, hash, references, deriver);
std::cerr << ".";
}
std::cerr << std::endl;
}
}

View file

@ -14,8 +14,8 @@ class Transaction;
/* Nix store and database schema version. Version 1 (or 0) was Nix <=
0.7. Version 2 was Nix 0.8 and 0.9. Version 3 is Nix 0.10.
Version 4 is Nix 0.11. */
const int nixSchemaVersion = 4;
Version 4 is Nix 0.11. Version 5 is Nix 0.12*/
const int nixSchemaVersion = 5;
extern string drvsLogDir;