1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-26 12:10:59 +01:00

State dirs/files to be versioned and state rights (user,grp,chmod) are now store in the db. Thuss we can remove their derivations at garbage collection time.

This commit is contained in:
Wouter den Breejen 2007-10-18 17:45:31 +00:00
parent 2d84c9e50c
commit 53e31381fa
9 changed files with 282 additions and 78 deletions

View file

@ -1889,9 +1889,8 @@ void DerivationGoal::computeClosure()
for (DerivationOutputs::iterator i = drv.outputs.begin(); for (DerivationOutputs::iterator i = drv.outputs.begin();
i != drv.outputs.end(); ++i) i != drv.outputs.end(); ++i)
{ {
//Register the path as a store-state path
if(isStateDrvPathTxn(txn, drvPath)) if(isStateDrvPathTxn(txn, drvPath))
setStateComponentTxn(txn, i->second.path); setStateComponentTxn(txn, i->second.path); //Register the path as a store-state path
registerValidPath(txn, registerValidPath(txn,
i->second.path, //component path i->second.path, //component path
@ -1919,6 +1918,27 @@ void DerivationGoal::computeClosure()
//Save the new revision //Save the new revision
setStateRevisionsTxn(txn, rivisionMapping, statePath, "Initial build revision."); setStateRevisionsTxn(txn, rivisionMapping, statePath, "Initial build revision.");
//Convert stateInfo from drv to DB format
DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs;
StateInfos infos;
for (DerivationStateOutputDirs::const_reverse_iterator j = stateOutputDirs.rbegin(); j != stateOutputDirs.rend(); ++j){
DerivationStateOutputDir d = j->second;
StateInfo si;
si.path = d.path;
si.type = d.type;
if(d.interval != ""){
bool succeed = string2UnsignedInt(d.interval, si.interval);
if(!succeed)
throw Error(format("Malformed interval value '%1%' in drv '%2%'") % d.interval % drvPath);
}
else
si.interval = 0;
infos.push_back(si);
}
setVersionedStateEntriesTxn(txn, statePath, infos); //register subdirs/files and their types of versioning
setStateUserGroupTxn(txn, statePath, queryCallingUsername(), "nixbld", 700); //register the user and group
//Shared state //Shared state
Path sharedState = drv.stateOutputs.find("state")->second.sharedState; Path sharedState = drv.stateOutputs.find("state")->second.sharedState;
@ -2598,7 +2618,7 @@ void Worker::getInfo()
args.push_back("--query-info"); args.push_back("--query-info");
args.insert(args.end(), paths2.begin(), paths2.end()); args.insert(args.end(), paths2.begin(), paths2.end());
string res = runProgram(sub, false, args); string res = runProgram(sub, false, args);
printMsg(lvlError, format("run: '%1%' res: '%2%'") % sub % res); //printMsg(lvlError, format("run: '%1%' res: '%2%'") % sub % res);
std::istringstream str(res); std::istringstream str(res);
while (true) { while (true) {
@ -2623,8 +2643,6 @@ void Worker::getInfo()
} }
} }
} }
printMsg(lvlError, format("AAAAAAAAA: '%1%'") % store->isStateComponent("/nix/store/3pw7vmdwdf3ccx6h6i2w0j52ribjswzn-hellotest-1.0"));
} }
} }

View file

@ -449,7 +449,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
bool gcKeepDerivations = bool gcKeepDerivations =
queryBoolSetting("gc-keep-derivations", true); queryBoolSetting("gc-keep-derivations", true);
printMsg(lvlError, format("gcKeepOutputs %1% gcKeepDerivations: %2%") % gcKeepOutputs % gcKeepDerivations); //printMsg(lvlError, format("gcKeepOutputs %1% gcKeepDerivations: %2%") % gcKeepOutputs % gcKeepDerivations);
/* Acquire the global GC root. This prevents /* Acquire the global GC root. This prevents
a) New roots from being added. a) New roots from being added.
@ -483,8 +483,6 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
for (PathSet::const_iterator i = roots.begin(); i != roots.end(); ++i) for (PathSet::const_iterator i = roots.begin(); i != roots.end(); ++i)
computeFSClosure(canonPath(*i), livePaths, true, true, 0); computeFSClosure(canonPath(*i), livePaths, true, true, 0);
printMsg(lvlError, format("STAGE X"));
/* Note that the deriver need not be valid (e.g., if we /* Note that the deriver need not be valid (e.g., if we
previously ran the collector with `gcKeepDerivations' previously ran the collector with `gcKeepDerivations'
turned off). */ turned off). */
@ -519,8 +517,6 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
} }
} }
printMsg(lvlError, format("STAGE Y"));
if (gcKeepOutputs) { if (gcKeepOutputs) {
/* Hmz, identical to storePathRequisites in nix-store. */ /* Hmz, identical to storePathRequisites in nix-store. */
for (PathSet::iterator i = livePaths.begin(); i != livePaths.end(); ++i) for (PathSet::iterator i = livePaths.begin(); i != livePaths.end(); ++i)
@ -591,7 +587,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
*/ */
PathSet allStatePathDerivations; PathSet allStatePathDerivations;
for (PathSet::iterator i = allLiveStatePaths.begin(); i != allLiveStatePaths.end(); ++i){ for (PathSet::iterator i = allLiveStatePaths.begin(); i != allLiveStatePaths.end(); ++i){
printMsg(lvlError, format("Live state path `%1%'") % *i); //printMsg(lvlError, format("Live state path `%1%'") % *i);
Path stateDrv = queryStatePathDrvTxn(noTxn, *i); Path stateDrv = queryStatePathDrvTxn(noTxn, *i);
allStatePathDerivations.insert(stateDrv); allStatePathDerivations.insert(stateDrv);
//printMsg(lvlError, format("Live state path drv `%1%'") % stateDrv); //printMsg(lvlError, format("Live state path drv `%1%'") % stateDrv);
@ -640,8 +636,6 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
if(*i != "/nix/store/zg8x9wdhcs4j0hvf33vg34c7m65adrpa-env-manifest") if(*i != "/nix/store/zg8x9wdhcs4j0hvf33vg34c7m65adrpa-env-manifest")
continue; continue;
printMsg(lvlError, format("Consider DEL `%1%'") % *i);
PathSet references; PathSet references;
store->queryStoreReferences(*i, references, 0); store->queryStoreReferences(*i, references, 0);
for (PathSet::iterator j = references.begin(); j != references.end(); ++j) { for (PathSet::iterator j = references.begin(); j != references.end(); ++j) {

View file

@ -158,6 +158,18 @@ static TableId dbStateSnapshots = 0;
*/ */
static TableId dbSharedState = 0; static TableId dbSharedState = 0;
/*
* StatePath :: string
* the string is converted to something of type StateInfos
*/
static TableId dbVersionItems = 0;
/*
* StatePath :: string
* the string contains the user,group and chmod
*/
static TableId dbStateRights = 0;
static void upgradeStore07(); static void upgradeStore07();
static void upgradeStore09(); static void upgradeStore09();
@ -228,6 +240,8 @@ LocalStore::LocalStore(bool reserveSpace)
dbStateSnapshots = nixDB.openTable("stateSnapshots"); dbStateSnapshots = nixDB.openTable("stateSnapshots");
dbSharedState = nixDB.openTable("sharedState"); dbSharedState = nixDB.openTable("sharedState");
dbSolidStateReferences = nixDB.openTable("references_solid_c_s"); /* The contents of this table is included in references_c_s */ dbSolidStateReferences = nixDB.openTable("references_solid_c_s"); /* The contents of this table is included in references_c_s */
dbVersionItems = nixDB.openTable("stateItems");
dbStateRights = nixDB.openTable("stateRights");
int curSchema = 0; int curSchema = 0;
Path schemaFN = nixDBPath + "/schema"; Path schemaFN = nixDBPath + "/schema";
@ -556,7 +570,7 @@ static PathSet getXReferrers(const Transaction & txn, const Path & store_or_stat
for (Strings::const_iterator i = keys.begin(); i != keys.end(); ++i){ for (Strings::const_iterator i = keys.begin(); i != keys.end(); ++i){
Path getStatePath; Path getStatePath;
unsigned int getRevision; unsigned int getRevision;
splitDBKey(*i, getStatePath, getRevision); splitDBRevKey(*i, getStatePath, getRevision);
if(latest[getStatePath] == 0) //either it is unset if(latest[getStatePath] == 0) //either it is unset
latest[getStatePath] = getRevision; latest[getStatePath] = getRevision;
@ -575,7 +589,7 @@ static PathSet getXReferrers(const Transaction & txn, const Path & store_or_stat
//printMsg(lvlError, format("AAAAA '%1%'") % (*i).first); //printMsg(lvlError, format("AAAAA '%1%'") % (*i).first);
Strings references; Strings references;
nixDB.queryStrings(txn, table, mergeToDBKey((*i).first, (*i).second), references); nixDB.queryStrings(txn, table, mergeToDBRevKey((*i).first, (*i).second), references);
for (Strings::iterator j = references.begin(); j != references.end(); ++j){ for (Strings::iterator j = references.begin(); j != references.end(); ++j){
//printMsg(lvlError, format("TEST: '%1%' has ref '%2%' check with '%3%'") % (*i).first % *j % path); //printMsg(lvlError, format("TEST: '%1%' has ref '%2%' check with '%3%'") % (*i).first % *j % path);
if(*j == path) if(*j == path)
@ -1852,6 +1866,29 @@ void LocalStore::revertToRevision(const Path & statePath, const unsigned int rev
txn.commit(); txn.commit();
} }
void setVersionedStateEntriesTxn(const Transaction & txn, const Path & statePath,
const StateInfos & infos, const unsigned int revision, const unsigned int timestamp)
{
setVersionedStateEntries(nixDB, txn, dbVersionItems, dbStateRevisions,
statePath, infos, revision, timestamp);
}
bool getVersionedStateEntriesTxn(const Transaction & txn, const Path & statePath,
StateInfos & infos, const unsigned int revision, const unsigned int timestamp)
{
return getVersionedStateEntries(nixDB, txn, dbVersionItems, dbStateRevisions,
statePath, infos, revision, timestamp);
}
void setStateUserGroupTxn(const Transaction & txn, const Path & statePath, const string & user, const string & group, int chmod)
{
setStateUserGroup(nixDB, txn, dbStateRights, statePath, user, group, chmod);
}
void getStateUserGroupTxn(const Transaction & txn, const Path & statePath, string & user, string & group, int & chmod)
{
getStateUserGroup(nixDB, txn, dbStateRights, statePath, user, group, chmod);
}
typedef std::map<Hash, std::pair<Path, ino_t> > HashToPath; typedef std::map<Hash, std::pair<Path, ino_t> > HashToPath;

View file

@ -275,6 +275,12 @@ bool querySharedStateTxn(const Transaction & txn, const Path & statePath, Path &
void setStateComponentTxn(const Transaction & txn, const Path & storePath); void setStateComponentTxn(const Transaction & txn, const Path & storePath);
void setVersionedStateEntriesTxn(const Transaction & txn, const Path & statePath, const StateInfos & infos, const unsigned int revision = 0, const unsigned int timestamp = 0);
bool getVersionedStateEntriesTxn(const Transaction & txn, const Path & statePath, StateInfos & infos, const unsigned int revision = 0, const unsigned int timestamp = 0);
void setStateUserGroupTxn(const Transaction & txn, const Path & statePath, const string & user, const string & group, int chmod);
void getStateUserGroupTxn(const Transaction & txn, const Path & statePath, string & user, string & group, int & chmod);
} }

View file

@ -219,8 +219,6 @@ ValidPathInfo decodeValidPathInfo(std::istream & str)
{ {
ValidPathInfo info; ValidPathInfo info;
printMsg(lvlError, format("BEFORE decodeValidPathInfo"));
getline(str, info.path); getline(str, info.path);
if (str.eof()) { info.path = ""; return info; } if (str.eof()) { info.path = ""; return info; }
@ -238,8 +236,6 @@ ValidPathInfo decodeValidPathInfo(std::istream & str)
if(store->isStateComponent(info.path)){ if(store->isStateComponent(info.path)){
printMsg(lvlError, format("STATE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"));
getline(str, s); getline(str, s);
if (!string2Int(s, n)) if (!string2Int(s, n))
throw Error("number expected"); throw Error("number expected");
@ -258,8 +254,6 @@ ValidPathInfo decodeValidPathInfo(std::istream & str)
if (!str || str.eof()) if (!str || str.eof())
throw Error("missing input"); throw Error("missing input");
printMsg(lvlError, format("AFTER decodeValidPathInfo"));
return info; return info;
} }

View file

@ -359,24 +359,70 @@ void scanAndUpdateAllReferencesRecusivelyTxn(const Transaction & txn, const Path
} }
} }
void rsyncPaths(const Path & from, const Path & to, const bool addSlashes) //TODO bool shellexpansion, bool failure for nix-env
{
//TODO Could be a symlink (to a non-existing dir)
/*
if(!DirectoryExist(from))
throw Error(format("Path `%1%' doenst exist ...") % from);
if(!DirectoryExist(to))
throw Error(format("Path `%1%' doenst exist ...") % to);
*/
Path from2 = from;
Path to2 = to;
if(addSlashes){
//We add a slash / to the end to ensure the contents is copyed
if(from2[from2.length() - 1] != '/')
from2 = from2 + "/";
if(to2[to2.length() - 1] != '/')
to2 = to2 + "/";
}
printMsg(lvlError, format("Rsync from: '%1%' to: '%2%'") % from2 % to2);
//Rsync from --> to and also with '-avHx --delete'
//This makes the paths completely equal (also deletes) and retains times ownership etc.
Strings p_args;
p_args.push_back("-avHx");
p_args.push_back("--delete");
p_args.push_back(from2);
p_args.push_back(to2);
runProgram_AndPrintOutput(nixRsync, true, p_args, "rsync");
}
// ******************************************************* DB FUNCTIONS ******************************************************************** // ******************************************************* DB FUNCTIONS ********************************************************************
/* State specific db functions */ /* State specific db functions */
Path mergeToDBKey(const Path & statePath, const unsigned int intvalue) Path mergeToDBKey(const string & s1, const string & s2)
{ {
string prefix = "-KEY-"; string prefix = "-KEY-";
return statePath + prefix + unsignedInt2String(intvalue); return s1 + prefix + s2;
}
Path mergeToDBRevKey(const Path & statePath, const unsigned int intvalue)
{
return mergeToDBKey(statePath, unsignedInt2String(intvalue));
} }
void splitDBKey(const Path & revisionedStatePath, Path & statePath, unsigned int & intvalue) void splitDBKey(const string & s, string & s1, string & s2)
{ {
string prefix = "-KEY-"; string prefix = "-KEY-";
size_t getPos = s.find_last_of(prefix);
int pos = revisionedStatePath.find_last_of(prefix); if(getPos == string::npos)
statePath = revisionedStatePath.substr(0, pos - prefix.length() + 1); throw Error(format("No prefx '%1%' found in '%2%' so we cannot split") % prefix % s);
//printMsg(lvlError, format("'%2%' - '%1%'") % revisionedStatePath.substr(pos+1, revisionedStatePath.length()) % int2String(pos));
bool succeed = string2UnsignedInt(revisionedStatePath.substr(pos+1, revisionedStatePath.length()), intvalue); int pos = getPos;
s1 = s.substr(0, pos - prefix.length() + 1);
s2 = s.substr(pos+1, s.length());
}
void splitDBRevKey(const Path & revisionedStatePath, Path & statePath, unsigned int & intvalue)
{
string s2;
splitDBKey(revisionedStatePath, statePath, s2);
bool succeed = string2UnsignedInt(s2, intvalue);
if(!succeed) if(!succeed)
throw Error(format("Malformed revision value of path '%1%'") % revisionedStatePath); throw Error(format("Malformed revision value of path '%1%'") % revisionedStatePath);
} }
@ -417,7 +463,7 @@ bool lookupHighestRevivison(const Strings & keys, const Path & statePath, string
//printMsg(lvlError, format("'%1%' - '%2%'") % *i % statePath); //printMsg(lvlError, format("'%1%' - '%2%'") % *i % statePath);
Path getStatePath; Path getStatePath;
unsigned int getRevision; unsigned int getRevision;
splitDBKey(*i, getStatePath, getRevision); splitDBRevKey(*i, getStatePath, getRevision);
if(getRevision > highestRev){ if(getRevision > highestRev){
if(lowerthan != 0){ if(lowerthan != 0){
@ -432,19 +478,19 @@ bool lookupHighestRevivison(const Strings & keys, const Path & statePath, string
if(highestRev == 0) //no records found if(highestRev == 0) //no records found
return false; return false;
key = mergeToDBKey(statePath, highestRev); //final key that matches revision + statePath key = mergeToDBRevKey(statePath, highestRev); //final key that matches revision + statePath
return true; return true;
} }
bool revisionToTimeStamp(Database & nixDB, const Transaction & txn, TableId revisions_table, const Path & statePath, const int revision, unsigned int & timestamp) bool revisionToTimeStamp(Database & nixDB, const Transaction & txn, TableId revisions_table, const Path & statePath, const int revision, unsigned int & timestamp)
{ {
string key = mergeToDBKey(statePath, revision); string key = mergeToDBRevKey(statePath, revision);
Strings references; Strings references;
bool notempty = nixDB.queryStrings(txn, revisions_table, key, references); bool notempty = nixDB.queryStrings(txn, revisions_table, key, references);
if(notempty){ if(notempty){
Path empty; Path empty;
splitDBKey(*(references.begin()), empty, timestamp); //extract the timestamp splitDBRevKey(*(references.begin()), empty, timestamp); //extract the timestamp
//printMsg(lvlError, format("PRINT '%1%'") % timestamp); //printMsg(lvlError, format("PRINT '%1%'") % timestamp);
return true; return true;
} }
@ -472,17 +518,13 @@ void setStateReferences(Database & nixDB, const Transaction & txn, TableId refer
//Warning if it already exists //Warning if it already exists
Strings empty; Strings empty;
if( nixDB.queryStrings(txn, references_table, mergeToDBKey(statePath, timestamp2), empty) ) if( nixDB.queryStrings(txn, references_table, mergeToDBRevKey(statePath, timestamp2), empty) )
printMsg(lvlError, format("Warning: The timestamp '%1%' (now: '%5%') / revision '%4%' already exists for set-references of path '%2%' with db '%3%'") printMsg(lvlError, format("Warning: The timestamp '%1%' (now: '%5%') / revision '%4%' already exists for set-references of path '%2%' with db '%3%'")
% timestamp2 % statePath % references_table % revision % getTimeStamp()); % timestamp2 % statePath % references_table % revision % getTimeStamp());
//Create the key //Create the key
string key = mergeToDBKey(statePath, timestamp2); string key = mergeToDBRevKey(statePath, timestamp2);
//printMsg(lvlError, format("Set references '%1%'") % key);
//for (Strings::const_iterator i = references.begin(); i != references.end(); ++i)
// printMsg(lvlError, format("reference '%1%'") % *i);
//Insert //Insert
nixDB.setStrings(txn, references_table, key, references, false); //The false makes sure also empty references are set nixDB.setStrings(txn, references_table, key, references, false); //The false makes sure also empty references are set
} }
@ -514,12 +556,12 @@ bool queryStateReferences(Database & nixDB, const Transaction & txn, TableId ref
} }
//If a specific key is given: check if this timestamp exists key in the table //If a specific key is given: check if this timestamp exists key in the table
key = mergeToDBKey(statePath, timestamp2); key = mergeToDBRevKey(statePath, timestamp2);
bool found = false; bool found = false;
for (Strings::const_iterator i = keys.begin(); i != keys.end(); ++i) { for (Strings::const_iterator i = keys.begin(); i != keys.end(); ++i) {
if(key == *i){ if(key == *i){
found = true; found = true;
key = mergeToDBKey(statePath, timestamp2); key = mergeToDBRevKey(statePath, timestamp2);
} }
} }
@ -555,10 +597,10 @@ void removeAllStatePathRevisions(Database & nixDB, const Transaction & txn, Tabl
for (RevisionInfos::iterator i = revisions.begin(); i != revisions.end(); ++i){ for (RevisionInfos::iterator i = revisions.begin(); i != revisions.end(); ++i){
unsigned int rev = (*i).first; unsigned int rev = (*i).first;
nixDB.delPair(txn, revisions_table, mergeToDBKey(statePath, rev)); nixDB.delPair(txn, revisions_table, mergeToDBRevKey(statePath, rev));
//Remove all comments //Remove all comments
nixDB.delPair(txn, revisions_comments, mergeToDBKey(statePath, rev)); nixDB.delPair(txn, revisions_comments, mergeToDBRevKey(statePath, rev));
} }
//Remove all snapshots //Remove all snapshots
@ -588,11 +630,11 @@ void setStateRevisions(Database & nixDB, const Transaction & txn, TableId revisi
//Insert all ss_epochs into snapshots_table with the current ts. //Insert all ss_epochs into snapshots_table with the current ts.
for (RevisionClosure::const_iterator i = revisions.begin(); i != revisions.end(); ++i){ for (RevisionClosure::const_iterator i = revisions.begin(); i != revisions.end(); ++i){
string key = mergeToDBKey((*i).first, timestamp); string key = mergeToDBRevKey((*i).first, timestamp);
Strings data; Strings data;
//the map<> takes care of the sorting on the Path //the map<> takes care of the sorting on the Path
for (Snapshots::const_iterator j = (*i).second.begin(); j != (*i).second.end(); ++j) for (Snapshots::const_iterator j = (*i).second.begin(); j != (*i).second.end(); ++j)
data.push_back(mergeToDBKey((*j).first, (*j).second)); data.push_back(mergeToDBRevKey((*j).first, (*j).second));
nixDB.setStrings(txn, snapshots_table, key, data); nixDB.setStrings(txn, snapshots_table, key, data);
} }
@ -602,7 +644,7 @@ void setStateRevisions(Database & nixDB, const Transaction & txn, TableId revisi
unsigned int revision = getNewRevisionNumber(nixDB, txn, revisions_table, statePath); //get a new revision number unsigned int revision = getNewRevisionNumber(nixDB, txn, revisions_table, statePath); //get a new revision number
string key = mergeToDBKey(statePath, revision); string key = mergeToDBRevKey(statePath, revision);
//get all its requisites //get all its requisites
PathSet statePath_references; PathSet statePath_references;
@ -612,7 +654,7 @@ void setStateRevisions(Database & nixDB, const Transaction & txn, TableId revisi
//save in db //save in db
Strings data; Strings data;
for (PathSet::const_iterator j = statePath_references.begin(); j != statePath_references.end(); ++j) for (PathSet::const_iterator j = statePath_references.begin(); j != statePath_references.end(); ++j)
data.push_back(mergeToDBKey(*j, timestamp)); data.push_back(mergeToDBRevKey(*j, timestamp));
nixDB.setStrings(txn, revisions_table, key, data, false); //The false makes sure also empty revisions are set nixDB.setStrings(txn, revisions_table, key, data, false); //The false makes sure also empty revisions are set
@ -644,7 +686,7 @@ bool queryStateRevisions(Database & nixDB, const Transaction & txn, TableId revi
return false; return false;
} }
else else
key = mergeToDBKey(statePath, root_revision); key = mergeToDBRevKey(statePath, root_revision);
//Get references pointing to snapshots_table from revisions_table with root_revision //Get references pointing to snapshots_table from revisions_table with root_revision
Strings statePaths; Strings statePaths;
@ -658,7 +700,7 @@ bool queryStateRevisions(Database & nixDB, const Transaction & txn, TableId revi
Path getStatePath; Path getStatePath;
unsigned int getTimestamp; unsigned int getTimestamp;
splitDBKey(*i, getStatePath, getTimestamp); splitDBRevKey(*i, getStatePath, getTimestamp);
//query state versioined directorys/files //query state versioined directorys/files
/* /*
@ -684,7 +726,7 @@ bool queryStateRevisions(Database & nixDB, const Transaction & txn, TableId revi
Path snapshottedPath; Path snapshottedPath;
unsigned int revision; unsigned int revision;
splitDBKey(*j, snapshottedPath, revision); splitDBRevKey(*j, snapshottedPath, revision);
snapshots[snapshottedPath] = revision; snapshots[snapshottedPath] = revision;
counter++; counter++;
@ -713,7 +755,7 @@ bool queryAvailableStateRevisions(Database & nixDB, const Transaction & txn, Tab
Path getStatePath; Path getStatePath;
unsigned int getRevision; unsigned int getRevision;
splitDBKey(*i, getStatePath, getRevision); splitDBRevKey(*i, getStatePath, getRevision);
//save the date and comments //save the date and comments
RevisionInfo rev; RevisionInfo rev;
@ -735,36 +777,93 @@ bool queryAvailableStateRevisions(Database & nixDB, const Transaction & txn, Tab
return true; return true;
} }
void rsyncPaths(const Path & from, const Path & to, const bool addSlashes) //TODO bool shellexpansion, bool failure for nix-env void setVersionedStateEntries(Database & nixDB, const Transaction & txn, TableId versionItems, TableId revisions_table,
const Path & statePath, const StateInfos & infos, const unsigned int revision, const unsigned int timestamp)
{ {
//TODO Could be a symlink (to a non-existing dir) if( !isValidStatePathTxn(txn, statePath) )
/* throw Error(format("path '%1%' is not a statepath") % statePath);
if(!DirectoryExist(from))
throw Error(format("Path `%1%' doenst exist ...") % from); //TODO THIS IS THE SAME CODE AS IN SETSTATEREFERENCES !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if(!DirectoryExist(to)) //Find the timestamp if we need
throw Error(format("Path `%1%' doenst exist ...") % to); unsigned int timestamp2 = timestamp;
*/ if(revision == 0 && timestamp == 0)
timestamp2 = getTimeStamp();
Path from2 = from; else if(revision != 0 && timestamp == 0){
Path to2 = to; bool found = revisionToTimeStamp(nixDB, txn, revisions_table, statePath, revision, timestamp2);
if(addSlashes){ if(!found)
//We add a slash / to the end to ensure the contents is copyed throw Error(format("Revision '%1%' cannot be matched to a timestamp...") % revision);
if(from2[from2.length() - 1] != '/')
from2 = from2 + "/";
if(to2[to2.length() - 1] != '/')
to2 = to2 + "/";
} }
printMsg(lvlError, format("Rsync from: '%1%' to: '%2%'") % from2 % to2); Strings ss;
for (StateInfos::const_iterator i = infos.begin(); i != infos.end(); ++i) {
StateInfo si = *i;
ss.push_back(mergeToDBKey(si.path, mergeToDBKey(si.type, unsignedInt2String(si.interval))));
}
nixDB.setStrings(txn, versionItems, statePath, ss);
}
bool getVersionedStateEntries(Database & nixDB, const Transaction & txn, TableId versionItems, TableId revisions_table,
const Path & statePath, StateInfos & infos, const unsigned int revision, const unsigned int timestamp)
{
if( !isValidStatePathTxn(txn, statePath) )
throw Error(format("path '%1%' is not a statepath") % statePath);
//TODO THIS IS THE SAME CODE AS IN QUERY STATEREFERRERS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
//Convert revision to timestamp number useing the revisions_table
unsigned int timestamp2 = timestamp;
if(timestamp == 0 && revision != 0){
bool found = revisionToTimeStamp(nixDB, txn, revisions_table, statePath, revision, timestamp2);
if(!found) //we are asked for references of some revision, but there are no references registered yet, so we return false;
return false;
}
//Rsync from --> to and also with '-avHx --delete' Strings ss;
//This makes the paths completely equal (also deletes) and retains times ownership etc. bool found = nixDB.queryStrings(txn, versionItems, statePath, ss);
Strings p_args; if(!found)
p_args.push_back("-avHx"); return false;
p_args.push_back("--delete");
p_args.push_back(from2); for (Strings::const_iterator i = ss.begin(); i != ss.end(); ++i) {
p_args.push_back(to2);
runProgram_AndPrintOutput(nixRsync, true, p_args, "rsync"); StateInfo si;
string s1;
string interval;
splitDBKey(*i, s1, interval);
bool succeed = string2UnsignedInt(interval, si.interval);
if(!succeed)
throw Error(format("Malformed TS value of record '%1%'") % *i);
string path;
string type;
splitDBKey(s1, si.path, si.type);
infos.push_back(si);
}
return true;
}
void setStateUserGroup(Database & nixDB, const Transaction & txn, TableId stateRights, const Path & statePath, const string & user, const string & group, int chmod)
{
string value = mergeToDBKey(user,mergeToDBKey(group, int2String(chmod)));
nixDB.setString(txn, stateRights, statePath, value);
}
void getStateUserGroup(Database & nixDB, const Transaction & txn, TableId stateRights, const Path & statePath, string & user, string & group, int & chmod)
{
string value;
bool notEmpty = nixDB.queryString(txn, stateRights, statePath, value);
if(!notEmpty)
throw Error(format("No rights found for path '%1%'") % statePath);
string s1;
string chmod_s;
splitDBKey(value, s1, chmod_s);
bool succeed = string2Int(chmod_s, chmod);
if(!succeed)
throw Error(format("Malformed chmod value of path '%1%'") % statePath);
splitDBKey(s1, user, group);
} }
} }

View file

@ -42,10 +42,14 @@ namespace nix {
unsigned int getNewRevisionNumber(Database & nixDB, const Transaction & txn, TableId table, const Path & statePath); unsigned int getNewRevisionNumber(Database & nixDB, const Transaction & txn, TableId table, const Path & statePath);
/* TODO */ /* TODO */
Path mergeToDBKey(const Path & statePath, const unsigned int intvalue); Path mergeToDBKey(const string & s1, const string & s2);
Path mergeToDBRevKey(const Path & statePath, const unsigned int intvalue);
/* TODO */ /* TODO */
void splitDBKey(const Path & revisionedStatePath, Path & statePath, unsigned int & intvalue); void splitDBKey(const string & s, string & s1, string & s2);
void splitDBRevKey(const Path & revisionedStatePath, Path & statePath, unsigned int & intvalue);
/* TODO */ /* TODO */
bool revisionToTimeStamp(Database & nixDB, const Transaction & txn, TableId revisions_table, const Path & statePath, const int revision, unsigned int & timestamp); bool revisionToTimeStamp(Database & nixDB, const Transaction & txn, TableId revisions_table, const Path & statePath, const int revision, unsigned int & timestamp);
@ -70,11 +74,28 @@ namespace nix {
bool queryAvailableStateRevisions(Database & nixDB, const Transaction & txn, TableId revisions_table, TableId revisions_comments, bool queryAvailableStateRevisions(Database & nixDB, const Transaction & txn, TableId revisions_table, TableId revisions_comments,
const Path & statePath, RevisionInfos & revisions); const Path & statePath, RevisionInfos & revisions);
/**/
void invalidateAllStateReferences(Database & nixDB, const Transaction & txn, TableId references_table, const Path & statePath); void invalidateAllStateReferences(Database & nixDB, const Transaction & txn, TableId references_table, const Path & statePath);
/**/
void removeAllStatePathRevisions(Database & nixDB, const Transaction & txn, TableId revisions_table, void removeAllStatePathRevisions(Database & nixDB, const Transaction & txn, TableId revisions_table,
TableId revisions_comments, TableId snapshots_table, TableId statecounters, const Path & statePath); TableId revisions_comments, TableId snapshots_table, TableId statecounters, const Path & statePath);
/**/
void setVersionedStateEntries(Database & nixDB, const Transaction & txn, TableId versionItems, TableId revisions_table,
const Path & statePath, const StateInfos & infos, const unsigned int revision = 0, const unsigned int timestamp = 0);
/**/
bool getVersionedStateEntries(Database & nixDB, const Transaction & txn, TableId versionItems, TableId revisions_table,
const Path & statePath, StateInfos & infos, const unsigned int revision = 0, const unsigned int timestamp = 0);
/**/
void setStateUserGroup(Database & nixDB, const Transaction & txn, TableId stateRights, const Path & statePath, const string & user, const string & group, int chmod);
/**/
void getStateUserGroup(Database & nixDB, const Transaction & txn, TableId stateRights, const Path & statePath, string & user, string & group, int & chmod);
} }

View file

@ -76,6 +76,15 @@ typedef map<Path, Snapshots> RevisionClosure;
typedef map<Path, unsigned int> RevisionClosureTS; //Paht with a timestamp about when the revision was made. typedef map<Path, unsigned int> RevisionClosureTS; //Paht with a timestamp about when the revision was made.
typedef map<int, Strings> StateReferences; typedef map<int, Strings> StateReferences;
struct StateInfo
{
string path;
string type;
unsigned int interval;
};
typedef list<StateInfo> StateInfos;
typedef enum { typedef enum {
lvlError, lvlError,

View file

@ -621,9 +621,35 @@ void run(Strings args)
printMsg(lvlError, format("REF `%1%'") % *j); printMsg(lvlError, format("REF `%1%'") % *j);
} }
} }
store = openStore();
Path statePath = "/mySTATEPATH";
unsigned int revision = 0;
unsigned int timestamp = 1234;
StateInfos infos;
StateInfo s1;
s1.path = "a"; s1.type = "t1"; s1.interval = 0;
StateInfo s2;
s2.path = "b"; s2.type = "t2"; s2.interval = 1000;
infos.push_back(s1);
infos.push_back(s2);
setVersionedStateEntries(nixDB, txn, dbVersionItems, dbStateRevisions,
statePath, infos, revision, timestamp);
StateInfos getInfos;
bool b = getVersionedStateEntries(nixDB, txn, dbVersionItems, dbStateRevisions,
statePath, getInfos, revision, timestamp);
printMsg(lvlError, format("B: %1%") % b);
for (StateInfos::const_iterator i = getInfos.begin(); i != getInfos.end(); ++i) {
StateInfo si = *i;
printMsg(lvlError, format("SI: %1% %2% %3%") % si.path % si.type % si.interval);
}
return; return;
*/ */
/* test */ /* test */