From 8a7874d77dc31f8c4885043398e0333e24ebda86 Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Fri, 18 May 2007 19:50:58 +0000 Subject: [PATCH] in the middle of adding nixStoreState ... --- scripts/nix-pull.in | 2 ++ src/libexpr/primops.cc | 28 +++++++++--------- src/libmain/shared.cc | 3 +- src/libstore/build.cc | 10 ++++++- src/libstore/derivations.cc | 28 ++++++++++++++++++ src/libstore/derivations.hh | 6 ++++ src/libstore/globals.cc | 1 + src/libstore/globals.hh | 4 +-- src/libstore/store-api.cc | 17 +++++++++-- src/libutil/util.cc | 57 ++++++++++++++++++++++++++++++++++++- src/libutil/util.hh | 4 +++ 11 files changed, 138 insertions(+), 22 deletions(-) diff --git a/scripts/nix-pull.in b/scripts/nix-pull.in index 46f9f147c..c2e022e12 100644 --- a/scripts/nix-pull.in +++ b/scripts/nix-pull.in @@ -21,6 +21,8 @@ $stateDir = "@localstatedir@/nix" unless defined $stateDir; my $storeDir = $ENV{"NIX_STORE_DIR"}; $storeDir = "@storedir@" unless defined $storeDir; +my $storeStateDir = $ENV{"NIX_STORE_STATE_DIR"}; +$storeStateDir = "@storestatedir@" unless defined $storeStateDir; # Prevent access problems in shared-stored installations. umask 0022; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 6d6cd4d21..81d3b117e 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -396,6 +396,7 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) bool disableState = false; string shareState = "none"; string syncState = "all"; + string stateIndentifier = ""; for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) { string key = aterm2String(i->key); @@ -427,22 +428,13 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) else if(key == "stateDirs") { enableState = true; - value = evalExpr(state, value); - ATermList list = evalList(state, value); - printMsg(lvlError, format("DIRS `%1%'") % value); - printMsg(lvlError, format("DIRS `%1%'") % list); - for (ATermIterator j(list); j; ++j){ - Expr v = evalExpr(state, *j); - printMsg(lvlError, format("DIRS2 `%1%'") % v); - ATermMap stateDirattrs; queryAllAttrs(evalExpr(state, v), stateDirattrs, true); - DerivationStateOutputDir dir = DerivationStateOutputDir(); for (ATermMap::const_iterator k = stateDirattrs.begin(); k != stateDirattrs.end(); ++k) { @@ -455,7 +447,7 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) startNest(nest, lvlVomit, format("processing statedir attribute `%1%'") % statekey); try { string s = coerceToString(state, statevalue, context, true); - printMsg(lvlError, format("DIRS4 `%1%'") % s); + if (statekey == "dir") { dir.path = s; } else if (statekey == "type") { dir.type = s; } else if (statekey == "interval") { dir.interval = s; } @@ -469,16 +461,15 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) } drv.stateOutputDirs[dir.path] = dir; - //Expr e = queryAttr(v, "dir"); //printMsg(lvlError, format("DIRS3 `%1%'") % e); - } } else if(key == "shareState") { string s = coerceToString(state, value, context, true); shareState = s; } else if(key == "synchronization") { string s = coerceToString(state, value, context, true); syncState = s; } else if(key == "enableState") { bool b = evalBool(state, value); disableState = true; } + else if(key == "indentifier"){ string s = coerceToString(state, value, context, true); stateIndentifier = s; } /* All other attributes are passed to the builder through the environment. */ @@ -570,12 +561,19 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, outputHash); /* Add the state path based on the outPath */ - //hash h = .... - drv.env["statepath"] = outPath; + string callingUser = "wouterdb"; //TODO: Change into variable + string statePrefix = "/nix/state/"; //TODO: Change into variable + + //Path outPath = makeStatePath("stateOutput:statepath", hashDerivationModulo(state, drv), drvName); + + string componentHash = printHash(hashDerivationModulo(state, drv)); + Hash hash = hashString(htSHA256, stateIndentifier + callingUser + componentHash); //calculate state hash + string statePath = statePrefix + printHash(hash) + "/"; //make the state path + drv.env["statepath"] = statePath; string enableStateS = "false"; if(enableState && disableState == false) enableStateS = "true"; - drv.stateOutputs["stateOptions"] = DerivationStateOutput(outPath, outputHashAlgo, outputHash, enableStateS, shareState, syncState); + drv.stateOutputs["state"] = DerivationStateOutput(statePath, outputHashAlgo, outputHash, enableStateS, shareState, syncState); /* Write the resulting term into the Nix store directory. */ Path drvPath = writeDerivation(drv, drvName); diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 568c975c2..7e7f165ef 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -87,9 +87,10 @@ static void initAndRun(int argc, char * * argv) { /* Setup Nix paths. */ nixStore = canonPath(getEnv("NIX_STORE_DIR", getEnv("NIX_STORE", NIX_STORE_DIR))); + nixStoreState = canonPath(getEnv("NIX_STORE_STATE_DIR", NIX_STORE_STATE_DIR)); //store state dir usually /nix/state nixDataDir = canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR)); nixLogDir = canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR)); - nixStateDir = canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR)); + nixStateDir = canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR)); //nix global state dir nixDBPath = getEnv("NIX_DB_DIR", nixStateDir + "/db"); nixConfDir = canonPath(getEnv("NIX_CONF_DIR", NIX_CONF_DIR)); nixLibexecDir = canonPath(getEnv("NIX_LIBEXEC_DIR", NIX_LIBEXEC_DIR)); diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 7009876f1..53ee3fe2d 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -588,6 +588,9 @@ private: /* The temporary directory. */ Path tmpDir; + + /* The state directory. */ + Path stateDir; /* File descriptor for the log file. */ AutoCloseFD fdLogFile; @@ -759,7 +762,7 @@ void DerivationGoal::haveDerivation() assert(store->isValidPath(drvPath)); /* Get the derivation. */ - drv = derivationFromPath(drvPath); + drv = derivationFromPath(drvPath); //wouter look here for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i) @@ -1370,6 +1373,11 @@ void DerivationGoal::startBuilder() /* Create a temporary directory where the build will take place. */ tmpDir = createTempDir(); + + /* Create the state directory where the component can store it's state files place */ + stateDir = createStateDirs(drv.stateOutputDirs, drv.stateOutputs); + + //TODO create the startupscript /* For convenience, set an environment pointing to the top build directory. */ diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index fb595d636..c26009bf7 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -82,6 +82,34 @@ Derivation parseDerivation(ATerm t) out.hash = aterm2String(hash); drv.outputs[aterm2String(id)] = out; } + + //parse state part + for (ATermIterator i(stateOuts); i; ++i) { + ATerm id, statepath, hashAlgo, hash, enabled, shared, synchronization; + if (!matchDerivationStateOutput(*i, id, statepath, hashAlgo, hash, enabled, shared, synchronization)) + throwBadDrv(t); + DerivationStateOutput stateOut; + stateOut.statepath = aterm2String(statepath); + //checkPath(stateOut.path); //should we check the statpath .... ??? + stateOut.hashAlgo = aterm2String(hashAlgo); + stateOut.hash = aterm2String(hash); + stateOut.enabled = aterm2String(enabled); + stateOut.shared = aterm2String(shared); + stateOut.synchronization = aterm2String(synchronization); + drv.stateOutputs[aterm2String(id)] = stateOut; + } + + //parse state dirs part + for (ATermIterator i(stateOutDirs); i; ++i) { + ATerm id, path, type, interval; + if (!matchDerivationStateOutputDir(*i, id, path, type, interval)) + throwBadDrv(t); + DerivationStateOutputDir stateOutDirs; + stateOutDirs.path = aterm2String(path); + stateOutDirs.type = aterm2String(type); + stateOutDirs.interval = aterm2String(interval); + drv.stateOutputDirs[aterm2String(id)] = stateOutDirs; + } for (ATermIterator i(inDrvs); i; ++i) { ATerm drvPath; diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index a4d0e24b1..ec4404d02 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -69,6 +69,12 @@ struct DerivationStateOutputDir this->type = type; this->interval = interval; } + + //sort function + /*bool operator<(const DerivationStateOutputDir& a, const DerivationStateOutputDir& b) { + return a.path < b.path; + } */ + bool operator<(const DerivationStateOutputDir& a) const { return path < a.path; } }; diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index b0316f77c..17f084143 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -9,6 +9,7 @@ namespace nix { string nixStore = "/UNINIT"; +string nixStoreState = "/UNINIT"; string nixDataDir = "/UNINIT"; string nixLogDir = "/UNINIT"; string nixStateDir = "/UNINIT"; diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 51fa68594..af1076e9f 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -18,8 +18,8 @@ extern string nixDataDir; /* !!! fix */ /* nixLogDir is the directory where we log various operations. */ extern string nixLogDir; -/* nixStateDir is the directory where state is stored. */ -extern string nixStateDir; +/* nixStateDir is the directory where the state dirs of the components are stored. */ +extern string nixStoreState; /* nixDBPath is the path name of our Berkeley DB environment. */ extern string nixDBPath; diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 4d5441318..197b9dda2 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -66,8 +66,7 @@ void checkStoreName(const string & name) } -Path makeStorePath(const string & type, - const Hash & hash, const string & suffix) +Path makeStorePath(const string & type, const Hash & hash, const string & suffix) { /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ string s = type + ":sha256:" + printHash(hash) + ":" @@ -80,6 +79,20 @@ Path makeStorePath(const string & type, + "-" + suffix; } +Path makeStatePath(const string & type, const Hash & hash, const string & suffix) +{ + /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ + string s = type + ":sha256:" + printHash(hash) + ":" + + nixStoreState + ":" + suffix; + + checkStoreName(suffix); + + return nixStoreState + "/" + + printHash32(compressHash(hashString(htSHA256, s), 20)) + + "-" + suffix; +} + + Path makeFixedOutputPath(bool recursive, string hashAlgo, Hash hash, string name) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index ae5af2492..bcdc42208 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -15,7 +15,7 @@ #include #include "util.hh" - +#include "../libstore/derivations.hh" extern char * * environ; @@ -348,6 +348,61 @@ Path createTempDir(const Path & tmpRoot) } } +//TODO include rights, variable svn ... ? +Path createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const DerivationStateOutputs & stateOutputs) +{ + /*while (1) { + checkInterrupt(); + if (mkdir(statePath.c_str(), 0777) == 0) { + if (chown(statePath.c_str(), (uid_t) -1, getegid()) != 0) + throw SysError(format("setting group of state directory `%1%'") % statePath); + return tmpDir; + } + if (errno != EEXIST) + throw SysError(format("creating state directory `%1%'") % statePath); + }*/ + + string stateDir = stateOutputs.find("state")->second.statepath; + + //Convert the map into a sortable vector + vector stateDirsVector; + for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){ + stateDirsVector.push_back(i->second); + } + sort(stateDirsVector.begin(), stateDirsVector.end()); + + for (vector::iterator i = stateDirsVector.begin(); i != stateDirsVector.end(); ++i) + { + DerivationStateOutputDir d = *(i); + printMsg(lvlError, format("test `%1%'") % d.path); + + //calc create repos for this state location + Hash hash = hashString(htSHA256, stateDir + d.path); + + /* + cd ... + svnadmin create hashcode + + //create dirs + svn checkout file:///nix/state/XXXX/PATH_TO_REPOS dir + chmod .... + chmod .... + + //create commit script + svn add * + svn revert file-that-I-do-not-want-added another-file-not-to-add + + */ + } + + //create super commit script + + + //return root path + Path tmpDir; + return tmpDir; +} + void createDirs(const Path & path) { diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 4d284ccfd..a76823824 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -2,6 +2,7 @@ #define __UTIL_H #include "types.hh" +#include "../libstore/derivations.hh" #include #include @@ -72,6 +73,9 @@ void makePathReadOnly(const Path & path); /* Create a temporary directory. */ Path createTempDir(const Path & tmpRoot = ""); +/* Create a state directory. */ +Path createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const DerivationStateOutputs & stateOutputs); + /* Create a directory and all its parents, if necessary. */ void createDirs(const Path & path);