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:
parent
2d84c9e50c
commit
53e31381fa
9 changed files with 282 additions and 78 deletions
|
|
@ -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"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue