mirror of
https://github.com/NixOS/nix.git
synced 2025-11-26 04:00:59 +01:00
Fixed referrer issue
This commit is contained in:
parent
7d91f62b71
commit
5e0716bbbb
5 changed files with 219 additions and 165 deletions
|
|
@ -618,20 +618,6 @@ bool Database::queryStateReferences(const Transaction & txn, TableId references_
|
||||||
return queryStrings(txn, references_table, key, references); //now that we have the key, we can query the references
|
return queryStrings(txn, references_table, key, references); //now that we have the key, we can query the references
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::setStateReferrers(const Transaction & txn, TableId referrers_table, TableId revisions_table,
|
|
||||||
const Path & statePath, const Strings & referrers, int revision)
|
|
||||||
{
|
|
||||||
//Exactly the same as the setStateReferences
|
|
||||||
setStateReferences(txn, referrers_table, revisions_table, statePath, referrers, revision);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Database::queryStateReferrers(const Transaction & txn, TableId referrers_table, TableId revisions_table,
|
|
||||||
const Path & statePath, Strings & referrers, int revision, int timestamp)
|
|
||||||
{
|
|
||||||
//Exactly the same as queryStateReferences
|
|
||||||
return queryStateReferences(txn, referrers_table, revisions_table, statePath, referrers, revision, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Database::setStateRevisions(const Transaction & txn, TableId revisions_table, TableId snapshots_table,
|
void Database::setStateRevisions(const Transaction & txn, TableId revisions_table, TableId snapshots_table,
|
||||||
const RevisionClosure & revisions)
|
const RevisionClosure & revisions)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,6 @@ private:
|
||||||
/* TODO */
|
/* TODO */
|
||||||
int getNewRevisionNumber(const Transaction & txn, TableId table, const Path & statePath);
|
int getNewRevisionNumber(const Transaction & txn, TableId table, const Path & statePath);
|
||||||
|
|
||||||
/* */
|
|
||||||
bool revisionToTimeStamp(const Transaction & txn, TableId revisions_table, const Path & statePath, const int revision, int & timestamp);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Database();
|
Database();
|
||||||
~Database();
|
~Database();
|
||||||
|
|
@ -105,6 +102,9 @@ public:
|
||||||
/* TODO */
|
/* TODO */
|
||||||
void splitDBKey(const Path & revisionedStatePath, Path & statePath, int & revision);
|
void splitDBKey(const Path & revisionedStatePath, Path & statePath, int & revision);
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
bool revisionToTimeStamp(const Transaction & txn, TableId revisions_table, const Path & statePath, const int revision, int & timestamp);
|
||||||
|
|
||||||
/* Set the stateReferences for a specific revision (and older until the next higher revision number in the table) */
|
/* Set the stateReferences for a specific revision (and older until the next higher revision number in the table) */
|
||||||
void setStateReferences(const Transaction & txn, TableId references_table, TableId revisions_table,
|
void setStateReferences(const Transaction & txn, TableId references_table, TableId revisions_table,
|
||||||
const Path & statePath, const Strings & references, int revision = -1);
|
const Path & statePath, const Strings & references, int revision = -1);
|
||||||
|
|
@ -113,14 +113,6 @@ public:
|
||||||
bool queryStateReferences(const Transaction & txn, TableId references_table, TableId revisions_table,
|
bool queryStateReferences(const Transaction & txn, TableId references_table, TableId revisions_table,
|
||||||
const Path & statePath, Strings & references, int revision = -1, int timestamp = -1);
|
const Path & statePath, Strings & references, int revision = -1, int timestamp = -1);
|
||||||
|
|
||||||
/* Set the stateReferences for a specific revision (and older until the next higher revision number in the table) */
|
|
||||||
void setStateReferrers(const Transaction & txn, TableId referrers_table, TableId revisions_table,
|
|
||||||
const Path & statePath, const Strings & referrers, int revision = -1);
|
|
||||||
|
|
||||||
/* Returns the referrers for a specific revision (and older until the next higher revision number in the table) */
|
|
||||||
bool queryStateReferrers(const Transaction & txn, TableId referrers_table, TableId revisions_table,
|
|
||||||
const Path & statePath, Strings & referrers, int revision = -1, int timestamp = -1);
|
|
||||||
|
|
||||||
/* Set the revision number of the statePath and the revision numbers of all state paths in the references closure */
|
/* Set the revision number of the statePath and the revision numbers of all state paths in the references closure */
|
||||||
void setStateRevisions(const Transaction & txn, TableId revisions_table, TableId snapshots_table,
|
void setStateRevisions(const Transaction & txn, TableId revisions_table, TableId snapshots_table,
|
||||||
const RevisionClosure & revisions);
|
const RevisionClosure & revisions);
|
||||||
|
|
|
||||||
|
|
@ -63,26 +63,17 @@ static TableId dbComponentStateReferences = 0;
|
||||||
static TableId dbStateComponentReferences = 0;
|
static TableId dbStateComponentReferences = 0;
|
||||||
static TableId dbStateStateReferences = 0;
|
static TableId dbStateStateReferences = 0;
|
||||||
|
|
||||||
|
|
||||||
/* dbReferrers :: Path -> Path
|
|
||||||
|
|
||||||
This table is just the reverse mapping of dbReferences. This table
|
|
||||||
can have duplicate keys, each corresponding value denoting a single
|
|
||||||
referrer. */
|
|
||||||
static TableId dbComponentComponentReferrers = 0;
|
|
||||||
static TableId dbComponentStateReferrers = 0;
|
|
||||||
|
|
||||||
/* dbStateReferrers :: Path -> Path
|
|
||||||
|
|
||||||
This table is just the reverse mapping of dbStateReferences. This table
|
|
||||||
can have duplicate keys, each corresponding value denoting a single
|
|
||||||
referrer. */
|
|
||||||
static TableId dbStateComponentReferrers = 0;
|
|
||||||
static TableId dbStateStateReferrers = 0;
|
|
||||||
|
|
||||||
/* dbSolidStateReferences :: Path -> [Path]
|
/* dbSolidStateReferences :: Path -> [Path]
|
||||||
*
|
*
|
||||||
* TODO Comment!!!!!!!!!!!!!!!!!!!!!!!1
|
* This is used to store references that are ALWAYS detected while scanning
|
||||||
|
* the store path, this is to include components that cannont be configured
|
||||||
|
* to put their state in /nix/state. We then use this workaround:
|
||||||
|
* mozilla firefox has state in
|
||||||
|
* ~/.mozilla/firefox --symlinked_to--> /nix/state/...HASH.....-firefox/
|
||||||
|
*
|
||||||
|
* Now the component firefox in the store does now detect the HASH since it
|
||||||
|
* is not in there, so we store the state path in this table which causes a
|
||||||
|
* scan of the firefox-store path to always return the firefox state path.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static TableId dbSolidStateReferences = 0;
|
static TableId dbSolidStateReferences = 0;
|
||||||
|
|
@ -111,36 +102,69 @@ static TableId dbSubstitutes = 0;
|
||||||
static TableId dbDerivers = 0;
|
static TableId dbDerivers = 0;
|
||||||
|
|
||||||
/* dbStateCounters :: StatePath -> Int
|
/* dbStateCounters :: StatePath -> Int
|
||||||
|
* This table lists the state path sub folders that are of type interval.
|
||||||
This table lists the state folders that state managed components
|
*
|
||||||
and are of type interval.
|
* Some folders/files need only to be committed every 10'th run, so
|
||||||
|
* we store the counting in this table
|
||||||
*/
|
*/
|
||||||
static TableId dbStateCounters = 0;
|
static TableId dbStateCounters = 0;
|
||||||
|
|
||||||
/* dbStateInfo :: Path -> DerivationPath
|
/* dbStateInfo :: Path ->
|
||||||
|
*
|
||||||
This table lists the all the state managed components, TODO we could store the entire DRV in here in the future
|
* This table lists all the store components, that are state-store components
|
||||||
|
* meaning that this component has a /nix/state/ entry to store its state
|
||||||
|
* and thus this component (should) have a reference to that state path
|
||||||
|
*
|
||||||
|
* TODO the value is now empty but we could store the entire DRV in here in the future
|
||||||
*/
|
*/
|
||||||
static TableId dbStateInfo = 0;
|
static TableId dbStateInfo = 0;
|
||||||
|
|
||||||
/* dbStateRevisions :: StatePath -> [StatePath]
|
/* dbStateRevisions :: StatePath -> [StatePath]
|
||||||
|
*
|
||||||
This table lists the ...............
|
* This table stores the revisions of state components and its dependecies
|
||||||
|
* on other state components. A revsion has a number of statepaths at a
|
||||||
|
* certain a timestamp.
|
||||||
|
*
|
||||||
|
* For example, a state path A at revision 1 depends on its own statepath at
|
||||||
|
* a ceratain timstamp and 1 other statepath at a certain timstamp:
|
||||||
|
*
|
||||||
|
* /nix/state/HASH-A-1.0-test-KEY-1
|
||||||
|
* -->
|
||||||
|
* [ /nix/state/HASH-A-1.0-test-KEY-1186135321, /nix/state/HASH-B-1.0-test-KEY-1186135321 ]
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
static TableId dbStateRevisions = 0;
|
static TableId dbStateRevisions = 0;
|
||||||
|
|
||||||
/* dbStateSnapshots :: StatePath -> RevisionNumbers
|
/* dbStateSnapshots :: StatePath -> RevisionNumbers
|
||||||
|
*
|
||||||
This table lists the ...............
|
* This table stores the snapshot numbers the sub state files/folders
|
||||||
|
* at a certain timestamp. These snapshot numbers are just timestamps
|
||||||
|
* produced by ext3cow
|
||||||
|
*
|
||||||
|
* /nix/state/HASH-A-1.0-test-KEY-1185473750
|
||||||
|
* -->
|
||||||
|
* [ 1185473750, 00118547375 ]
|
||||||
|
*
|
||||||
|
* The timestamps are ordered based on the path of the subfolder !!
|
||||||
|
*
|
||||||
|
* So if a has:
|
||||||
|
*
|
||||||
|
* /nix/state/....A../log
|
||||||
|
* /nix/state/....A../cache
|
||||||
|
*
|
||||||
|
* then ./cache has TS 1185473750
|
||||||
|
* and ./log has TS 00118547375
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
static TableId dbStateSnapshots = 0;
|
static TableId dbStateSnapshots = 0;
|
||||||
|
|
||||||
/* dbSharedState :: Path -> Path
|
/* dbSharedState :: Path -> Path
|
||||||
*
|
*
|
||||||
* Lists all paths that are shared with other paths
|
* This table links each statepath to a list of epoch numbers.
|
||||||
|
* These numbers represent the timestamps of the sub-state folders
|
||||||
|
* when they are snapshotted.
|
||||||
|
*
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
static TableId dbSharedState = 0;
|
static TableId dbSharedState = 0;
|
||||||
|
|
||||||
|
|
@ -213,14 +237,9 @@ LocalStore::LocalStore(bool reserveSpace)
|
||||||
dbComponentStateReferences = nixDB.openTable("references_c_s");
|
dbComponentStateReferences = nixDB.openTable("references_c_s");
|
||||||
dbStateComponentReferences = nixDB.openTable("references_s_c");
|
dbStateComponentReferences = nixDB.openTable("references_s_c");
|
||||||
dbStateStateReferences = nixDB.openTable("references_s_s");
|
dbStateStateReferences = nixDB.openTable("references_s_s");
|
||||||
dbComponentComponentReferrers = nixDB.openTable("referrers", true); /* must be sorted */ /* c_c */
|
|
||||||
dbComponentStateReferrers = nixDB.openTable("referrers_c_s", true);
|
|
||||||
dbStateComponentReferrers = nixDB.openTable("referrers_s_c", true);
|
|
||||||
dbStateStateReferrers = nixDB.openTable("referrers_s_s", true);
|
|
||||||
dbStateRevisions = nixDB.openTable("staterevisions");
|
dbStateRevisions = nixDB.openTable("staterevisions");
|
||||||
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 */
|
||||||
|
|
||||||
int curSchema = 0;
|
int curSchema = 0;
|
||||||
|
|
@ -402,12 +421,12 @@ static bool isRealisableComponentOrStatePath(const Transaction & txn, const Path
|
||||||
return isValidComponentOrStatePathTxn(txn, path) || readSubstitutes(txn, path).size() > 0; //TODO State paths are not yet in substitutes !!!!!!!!!!!!!! ??
|
return isValidComponentOrStatePathTxn(txn, path) || readSubstitutes(txn, path).size() > 0; //TODO State paths are not yet in substitutes !!!!!!!!!!!!!! ??
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
static string addPrefix(const string & prefix, const string & s)
|
static string addPrefix(const string & prefix, const string & s)
|
||||||
{
|
{
|
||||||
return prefix + string(1, (char) 0) + s;
|
return prefix + string(1, (char) 0) + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static string stripPrefix(const string & prefix, const string & s)
|
static string stripPrefix(const string & prefix, const string & s)
|
||||||
{
|
{
|
||||||
if (s.size() <= prefix.size() ||
|
if (s.size() <= prefix.size() ||
|
||||||
|
|
@ -417,7 +436,7 @@ static string stripPrefix(const string & prefix, const string & s)
|
||||||
% s % prefix);
|
% s % prefix);
|
||||||
return string(s, prefix.size() + 1);
|
return string(s, prefix.size() + 1);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
void setReferences(const Transaction & txn, const Path & store_or_statePath,
|
void setReferences(const Transaction & txn, const Path & store_or_statePath,
|
||||||
|
|
@ -447,7 +466,7 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath,
|
||||||
|
|
||||||
PathSet oldReferences = PathSet(oldReferences_c_c.begin(), oldReferences_c_c.end());
|
PathSet oldReferences = PathSet(oldReferences_c_c.begin(), oldReferences_c_c.end());
|
||||||
PathSet oldStateReferences = PathSet(oldReferences_c_s.begin(), oldReferences_c_s.end());
|
PathSet oldStateReferences = PathSet(oldReferences_c_s.begin(), oldReferences_c_s.end());
|
||||||
if (oldReferences == references && oldStateReferences == stateReferences) return; //watch out we way need to set the referrers.... (at a ts)
|
if (oldReferences == references && oldStateReferences == stateReferences) return;
|
||||||
|
|
||||||
nixDB.setStrings(txn, dbComponentComponentReferences, store_or_statePath, Paths(references.begin(), references.end()));
|
nixDB.setStrings(txn, dbComponentComponentReferences, store_or_statePath, Paths(references.begin(), references.end()));
|
||||||
nixDB.setStrings(txn, dbComponentStateReferences, store_or_statePath, Paths(stateReferences.begin(), stateReferences.end()));
|
nixDB.setStrings(txn, dbComponentStateReferences, store_or_statePath, Paths(stateReferences.begin(), stateReferences.end()));
|
||||||
|
|
@ -533,53 +552,108 @@ void LocalStore::queryAllReferences(const Path & path, PathSet & allReferences,
|
||||||
queryAllReferencesTxn(noTxn, path, allReferences, revision);
|
queryAllReferencesTxn(noTxn, path, allReferences, revision);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PathSet getXReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision, const TableId & table)
|
static PathSet getXReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision, const bool component_or_state)
|
||||||
{
|
{
|
||||||
/*
|
TableId table;
|
||||||
|
Path path;
|
||||||
|
|
||||||
|
if( !isValidPathTxn(txn, store_or_statePath) && !isValidStatePathTxn(txn, store_or_statePath) )
|
||||||
|
throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath);
|
||||||
|
|
||||||
|
//NO TS
|
||||||
|
if(component_or_state){ //we need component references
|
||||||
if(isValidPathTxn(txn, store_or_statePath)){
|
if(isValidPathTxn(txn, store_or_statePath)){
|
||||||
PathSet referrers;
|
path = store_or_statePath;
|
||||||
|
table = dbComponentComponentReferences;
|
||||||
|
}
|
||||||
|
else if(isValidStatePathTxn(txn, store_or_statePath)){
|
||||||
|
path = toNonSharedPathTxn(txn, store_or_statePath); //Lookup its where it points to if its shared
|
||||||
|
table = dbComponentStateReferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printMsg(lvlError, format("we need component references: '%1%' '%2%' '%3%'") % path % store_or_statePath % table);
|
||||||
|
|
||||||
|
//check which key refers to our 'path' (we dont have to deal with timestamps since componentpaths are immutable)
|
||||||
Strings keys;
|
Strings keys;
|
||||||
nixDB.enumTable(txn, table, keys, store_or_statePath + string(1, (char) 0));
|
nixDB.enumTable(txn, table, keys);
|
||||||
for (Strings::iterator i = keys.begin(); i != keys.end(); ++i)
|
PathSet referrers;
|
||||||
referrers.insert(stripPrefix(store_or_statePath, *i));
|
for (Strings::const_iterator i = keys.begin(); i != keys.end(); ++i){
|
||||||
|
|
||||||
|
Strings references;
|
||||||
|
nixDB.queryStrings(txn, table, *i, references);
|
||||||
|
for (Strings::iterator j = references.begin(); j != references.end(); ++j){
|
||||||
|
if(*j == path)
|
||||||
|
referrers.insert(*i); //we found a referrer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return referrers;
|
return referrers;
|
||||||
}
|
}
|
||||||
else if(isValidStatePathTxn(txn, store_or_statePath)){
|
//TS
|
||||||
Path statePath_ns = toNonSharedPathTxn(txn, store_or_statePath); //Lookup its where it points to if its shared
|
else{ //we need state references
|
||||||
Paths referrers;
|
|
||||||
nixDB.queryStateReferrers(txn, table, dbStateRevisions, statePath_ns, referrers, revision);
|
|
||||||
PathSet p(referrers.begin(), referrers.end());
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath);
|
|
||||||
*/
|
|
||||||
|
|
||||||
//TODO!!!!!!!!!!!!!!!!!!!! use revision !!!!!!!!!!!!!!!!!!!!! add timestamp ?????
|
|
||||||
|
|
||||||
PathSet referrers;
|
|
||||||
|
|
||||||
if(isValidPathTxn(txn, store_or_statePath)){
|
if(isValidPathTxn(txn, store_or_statePath)){
|
||||||
|
path = store_or_statePath;
|
||||||
|
table = dbStateComponentReferences;
|
||||||
}
|
}
|
||||||
else if(isValidStatePathTxn(txn, store_or_statePath)){
|
else if(isValidStatePathTxn(txn, store_or_statePath)){
|
||||||
Path statePath_ns = toNonSharedPathTxn(txn, store_or_statePath); //Lookup its where it points to if its shared
|
path = toNonSharedPathTxn(txn, store_or_statePath); //Lookup its where it points to if its shared
|
||||||
|
table = dbStateStateReferences;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath);
|
|
||||||
|
|
||||||
|
//printMsg(lvlError, format("we need state references: '%1%' '%2%' '%3%'") % path % store_or_statePath % table);
|
||||||
|
|
||||||
|
//Now in references of ALL referrers, (possibly lookup their latest TS based on revision)
|
||||||
|
int timestamp;
|
||||||
|
if(revision != -1){
|
||||||
|
bool succeed = nixDB.revisionToTimeStamp(txn, dbStateRevisions, path, revision, timestamp);
|
||||||
|
if(!succeed)
|
||||||
|
throw Error(format("Getreferrers cannot find timestamp for revision: '%1%'") % revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
Strings keys;
|
||||||
|
nixDB.enumTable(txn, table, keys);
|
||||||
|
map<string, int> latest;
|
||||||
|
for (Strings::const_iterator i = keys.begin(); i != keys.end(); ++i){
|
||||||
|
Path getStatePath;
|
||||||
|
int getRevision;
|
||||||
|
nixDB.splitDBKey(*i, getStatePath, getRevision);
|
||||||
|
|
||||||
|
if(latest[getStatePath] == 0) //either it is unset
|
||||||
|
latest[getStatePath] = getRevision;
|
||||||
|
else if(latest[getStatePath] < getRevision){
|
||||||
|
if(revision != -1 && getRevision <= timestamp) //or it is greater, but not greater then the timestamp
|
||||||
|
latest[getStatePath] = getRevision;
|
||||||
|
else //we need the latest so greater is good
|
||||||
|
latest[getStatePath] = getRevision;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//now check if they refer to 'path' (if you cant find it, then they dont referr to it)
|
||||||
|
PathSet referrers;
|
||||||
|
for (map<string, int>::const_iterator i = latest.begin(); i != latest.end(); ++i){
|
||||||
|
|
||||||
|
//printMsg(lvlError, format("AAAAA '%1%'") % (*i).first);
|
||||||
|
|
||||||
|
Strings references;
|
||||||
|
nixDB.queryStrings(txn, table, nixDB.mergeToDBKey((*i).first, (*i).second), references);
|
||||||
|
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);
|
||||||
|
if(*j == path)
|
||||||
|
referrers.insert((*i).first); //we found a referrer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return referrers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PathSet getReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision)
|
static PathSet getReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision)
|
||||||
{
|
{
|
||||||
return getXReferrers(txn, store_or_statePath, revision, dbComponentComponentReferrers);
|
return getXReferrers(txn, store_or_statePath, revision, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PathSet getStateReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision)
|
static PathSet getStateReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision)
|
||||||
{
|
{
|
||||||
return getXReferrers(txn, store_or_statePath, revision, dbStateStateReferrers);
|
return getXReferrers(txn, store_or_statePath, revision, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void queryReferrersTxn(const Transaction & txn,
|
void queryReferrersTxn(const Transaction & txn,
|
||||||
|
|
@ -629,6 +703,41 @@ void setDeriver(const Transaction & txn, const Path & storePath, const Path & de
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Private function only used by addStateDeriver
|
||||||
|
* Merges a new derivation into a list of derivations, this function takes username and statepath
|
||||||
|
* into account. This function is used to update derivations that have only changed in their sub state
|
||||||
|
* paths that need to be versioned for example. We assume newdrv is the newest.
|
||||||
|
*/
|
||||||
|
PathSet mergeNewDerivationIntoList(const Path & storepath, const Path & newdrv, const PathSet drvs, bool deleteDrvs)
|
||||||
|
{
|
||||||
|
PathSet newdrvs;
|
||||||
|
|
||||||
|
Derivation drv = derivationFromPath(newdrv);
|
||||||
|
string identifier = drv.stateOutputs.find("state")->second.stateIdentifier;
|
||||||
|
string user = drv.stateOutputs.find("state")->second.username;
|
||||||
|
|
||||||
|
for (PathSet::iterator i = drvs.begin(); i != drvs.end(); ++i) //Check if we need to remove old drvs
|
||||||
|
{
|
||||||
|
Path drv = *i;
|
||||||
|
Derivation getdrv = derivationFromPath(drv);
|
||||||
|
string getIdentifier = getdrv.stateOutputs.find("state")->second.stateIdentifier;
|
||||||
|
string getUser = getdrv.stateOutputs.find("state")->second.username;
|
||||||
|
|
||||||
|
if(identifier == getIdentifier && getUser == user) //only insert if it doenst already exist
|
||||||
|
{
|
||||||
|
//We also check if it's NOT exactly the same drvpath
|
||||||
|
if(drv != newdrv && deleteDrvs){
|
||||||
|
printMsg(lvlTalkative, format("Deleting decrepated state derivation: %1% with identifier %2% and user %3%") % drv % identifier % user);
|
||||||
|
deletePath(drv); //Deletes the DRV from DISK!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newdrvs.insert(drv);
|
||||||
|
}
|
||||||
|
|
||||||
|
newdrvs.insert(newdrv);
|
||||||
|
return newdrvs;
|
||||||
|
}
|
||||||
|
|
||||||
void addStateDeriver(const Transaction & txn, const Path & storePath, const Path & deriver)
|
void addStateDeriver(const Transaction & txn, const Path & storePath, const Path & deriver)
|
||||||
{
|
{
|
||||||
|
|
@ -652,7 +761,6 @@ void addStateDeriver(const Transaction & txn, const Path & storePath, const Path
|
||||||
nixDB.setStrings(txn, dbDerivers, storePath, data); //update the derivers db.
|
nixDB.setStrings(txn, dbDerivers, storePath, data); //update the derivers db.
|
||||||
|
|
||||||
nixDB.setString(txn, dbStateInfo, storePath, ""); //update the dbinfo db. (maybe TODO)
|
nixDB.setString(txn, dbStateInfo, storePath, ""); //update the dbinfo db. (maybe TODO)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -752,6 +860,7 @@ PathSet queryDerivers(const Transaction & txn, const Path & storePath, const str
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wrapper around converting the drvPath to the statePath
|
//Wrapper around converting the drvPath to the statePath
|
||||||
|
/*
|
||||||
PathSet queryDeriversStatePath(const Transaction & txn, const Path & storePath, const string & identifier, const string & user)
|
PathSet queryDeriversStatePath(const Transaction & txn, const Path & storePath, const string & identifier, const string & user)
|
||||||
{
|
{
|
||||||
PathSet drvs = queryDerivers(txn, storePath, identifier, user);
|
PathSet drvs = queryDerivers(txn, storePath, identifier, user);
|
||||||
|
|
@ -762,6 +871,7 @@ PathSet queryDeriversStatePath(const Transaction & txn, const Path & storePath,
|
||||||
}
|
}
|
||||||
return statePaths;
|
return statePaths;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
const int substituteVersion = 2;
|
const int substituteVersion = 2;
|
||||||
|
|
@ -1428,12 +1538,15 @@ void verifyStore(bool checkContents)
|
||||||
for (PathSet::iterator j = references.begin();
|
for (PathSet::iterator j = references.begin();
|
||||||
j != references.end(); ++j)
|
j != references.end(); ++j)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
string dummy;
|
string dummy;
|
||||||
if (!nixDB.queryString(txn, dbComponentComponentReferrers, addPrefix(*j, *i), dummy)) {
|
if (!nixDB.queryString(txn, dbComponentComponentReferrers, addPrefix(*j, *i), dummy)) {
|
||||||
printMsg(lvlError, format("adding missing referrer mapping from `%1%' to `%2%'")
|
printMsg(lvlError, format("adding missing referrer mapping from `%1%' to `%2%'")
|
||||||
% *j % *i);
|
% *j % *i);
|
||||||
nixDB.setString(txn, dbComponentComponentReferrers, addPrefix(*j, *i), "");
|
nixDB.setString(txn, dbComponentComponentReferrers, addPrefix(*j, *i), "");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (isValid && validPaths.find(*j) == validPaths.end()) {
|
if (isValid && validPaths.find(*j) == validPaths.end()) {
|
||||||
printMsg(lvlError, format("incomplete closure: `%1%' needs missing `%2%'")
|
printMsg(lvlError, format("incomplete closure: `%1%' needs missing `%2%'")
|
||||||
% *i % *j);
|
% *i % *j);
|
||||||
|
|
@ -1444,12 +1557,13 @@ void verifyStore(bool checkContents)
|
||||||
|
|
||||||
/* Check the `referrers' table. */
|
/* Check the `referrers' table. */
|
||||||
//TODO TODO Do the exact same thing for the other dbreferres and references
|
//TODO TODO Do the exact same thing for the other dbreferres and references
|
||||||
|
/*
|
||||||
printMsg(lvlInfo, "checking the referrers table");
|
printMsg(lvlInfo, "checking the referrers table");
|
||||||
Strings referrers;
|
Strings referrers;
|
||||||
nixDB.enumTable(txn, dbComponentComponentReferrers, referrers);
|
nixDB.enumTable(txn, dbComponentComponentReferrers, referrers);
|
||||||
for (Strings::iterator i = referrers.begin(); i != referrers.end(); ++i) {
|
for (Strings::iterator i = referrers.begin(); i != referrers.end(); ++i) {
|
||||||
|
|
||||||
/* Decode the entry (it's a tuple of paths). */
|
// Decode the entry (it's a tuple of paths)
|
||||||
string::size_type nul = i->find((char) 0);
|
string::size_type nul = i->find((char) 0);
|
||||||
if (nul == string::npos) {
|
if (nul == string::npos) {
|
||||||
printMsg(lvlError, format("removing bad referrer table entry `%1%'") % *i);
|
printMsg(lvlError, format("removing bad referrer table entry `%1%'") % *i);
|
||||||
|
|
@ -1484,8 +1598,8 @@ void verifyStore(bool checkContents)
|
||||||
setReferences(txn, from, references, stateReferences, -1);
|
setReferences(txn, from, references, stateReferences, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//TODO Check stateinfo and statecounters table
|
//TODO Check stateinfo and statecounters table
|
||||||
|
|
||||||
|
|
@ -1553,41 +1667,6 @@ vector<int> LocalStore::getStatePathsInterval(const PathSet & statePaths)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Merges a new .... into the list TODO
|
|
||||||
//This is all about one store path
|
|
||||||
//We assume newdrv is the newest
|
|
||||||
PathSet mergeNewDerivationIntoList(const Path & storepath, const Path & newdrv, const PathSet drvs, bool deleteDrvs)
|
|
||||||
{
|
|
||||||
PathSet newdrvs;
|
|
||||||
|
|
||||||
Derivation drv = derivationFromPath(newdrv);
|
|
||||||
string identifier = drv.stateOutputs.find("state")->second.stateIdentifier;
|
|
||||||
string user = drv.stateOutputs.find("state")->second.username;
|
|
||||||
|
|
||||||
for (PathSet::iterator i = drvs.begin(); i != drvs.end(); ++i) //Check if we need to remove old drvs
|
|
||||||
{
|
|
||||||
Path drv = *i;
|
|
||||||
Derivation getdrv = derivationFromPath(drv);
|
|
||||||
string getIdentifier = getdrv.stateOutputs.find("state")->second.stateIdentifier;
|
|
||||||
string getUser = getdrv.stateOutputs.find("state")->second.username;
|
|
||||||
|
|
||||||
if(identifier == getIdentifier && getUser == user) //only insert if it doenst already exist
|
|
||||||
{
|
|
||||||
//We also check if it's NOT exactly the same drvpath
|
|
||||||
if(drv != newdrv && deleteDrvs){
|
|
||||||
printMsg(lvlTalkative, format("Deleting decrepated state derivation: %1% with identifier %2% and user %3%") % drv % identifier % user);
|
|
||||||
deletePath(drv); //Deletes the DRV from DISK!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
newdrvs.insert(drv);
|
|
||||||
}
|
|
||||||
|
|
||||||
newdrvs.insert(newdrv);
|
|
||||||
return newdrvs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Place in `paths' the set of paths that are required to `realise'
|
/* Place in `paths' the set of paths that are required to `realise'
|
||||||
the given store path, i.e., all paths necessary for valid
|
the given store path, i.e., all paths necessary for valid
|
||||||
deployment of the path. For a derivation, this is the union of
|
deployment of the path. For a derivation, this is the union of
|
||||||
|
|
@ -1836,11 +1915,12 @@ static void upgradeStore09()
|
||||||
|
|
||||||
if (!pathExists(nixDBPath + "/referers")) return;
|
if (!pathExists(nixDBPath + "/referers")) return;
|
||||||
|
|
||||||
|
/*
|
||||||
Transaction txn(nixDB);
|
Transaction txn(nixDB);
|
||||||
|
|
||||||
std::cerr << "converting referers to referrers...";
|
std::cerr << "converting referers to referrers...";
|
||||||
|
|
||||||
TableId dbReferers = nixDB.openTable("referers"); /* sic! */
|
TableId dbReferers = nixDB.openTable("referers"); // sic!
|
||||||
|
|
||||||
Paths referersKeys;
|
Paths referersKeys;
|
||||||
nixDB.enumTable(txn, dbReferers, referersKeys);
|
nixDB.enumTable(txn, dbReferers, referersKeys);
|
||||||
|
|
@ -1864,11 +1944,14 @@ static void upgradeStore09()
|
||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
|
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
|
|
||||||
nixDB.closeTable(dbReferers);
|
nixDB.closeTable(dbReferers);
|
||||||
|
*/
|
||||||
|
|
||||||
nixDB.deleteTable("referers");
|
nixDB.deleteTable("referers");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,12 +178,11 @@ void setDeriver(const Transaction & txn, const Path & path,
|
||||||
deriver has been set. */
|
deriver has been set. */
|
||||||
Path queryDeriver(const Transaction & txn, const Path & path);
|
Path queryDeriver(const Transaction & txn, const Path & path);
|
||||||
|
|
||||||
/* Query the derivers of a state-store path. Gives an error (TODO?) if no
|
/* Query the derivers of a state-store path. */
|
||||||
deriver has been set. */
|
|
||||||
PathSet queryDerivers(const Transaction & txn, const Path & storePath, const string & identifier, const string & user);
|
PathSet queryDerivers(const Transaction & txn, const Path & storePath, const string & identifier, const string & user);
|
||||||
|
|
||||||
/* TODO */
|
/* Query the derivers of a state path. (are there more then 1 for a statepath?) */
|
||||||
PathSet queryDeriversStatePath(const Transaction & txn, const Path & storePath, const string & identifier, const string & user);
|
//PathSet queryDeriversStatePath(const Transaction & txn, const Path & storePath, const string & identifier, const string & user);
|
||||||
|
|
||||||
/* Delete a value from the nixStore directory. */
|
/* Delete a value from the nixStore directory. */
|
||||||
void deleteFromStore(const Path & path, unsigned long long & bytesFreed);
|
void deleteFromStore(const Path & path, unsigned long long & bytesFreed);
|
||||||
|
|
@ -208,12 +207,9 @@ void deletePathWrapped(const Path & path,
|
||||||
|
|
||||||
void deletePathWrapped(const Path & path);
|
void deletePathWrapped(const Path & path);
|
||||||
|
|
||||||
/* TODO */
|
/* Adds a new deriver based on storePath to the dbDerivers table */
|
||||||
void addStateDeriver(const Transaction & txn, const Path & storePath, const Path & deriver);
|
void addStateDeriver(const Transaction & txn, const Path & storePath, const Path & deriver);
|
||||||
|
|
||||||
/* TODO */
|
|
||||||
PathSet mergeNewDerivationIntoList(const Path & storepath, const Path & newdrv, const PathSet drvs, bool deleteDrvs = false);
|
|
||||||
|
|
||||||
bool isStateComponentTxn(const Transaction & txn, const Path & path);
|
bool isStateComponentTxn(const Transaction & txn, const Path & path);
|
||||||
|
|
||||||
bool isStateDrvPathTxn(const Transaction & txn, const Path & drvPath);
|
bool isStateDrvPathTxn(const Transaction & txn, const Path & drvPath);
|
||||||
|
|
|
||||||
|
|
@ -419,8 +419,6 @@ void scanAndUpdateAllReferencesTxn(const Transaction & txn, const Path & statePa
|
||||||
//diff_state_references_added.size() != 0 || diff_state_references_removed.size() != 0 )
|
//diff_state_references_added.size() != 0 || diff_state_references_removed.size() != 0 )
|
||||||
|
|
||||||
//We always set the referernces so we know they were scanned (maybe the same) at a certain time
|
//We always set the referernces so we know they were scanned (maybe the same) at a certain time
|
||||||
if(true)
|
|
||||||
{
|
|
||||||
printMsg(lvlError, format("Updating new references for statepath: '%1%'") % statePath);
|
printMsg(lvlError, format("Updating new references for statepath: '%1%'") % statePath);
|
||||||
Path drvPath = queryStatePathDrvTxn(txn, statePath);
|
Path drvPath = queryStatePathDrvTxn(txn, statePath);
|
||||||
registerValidPath(txn,
|
registerValidPath(txn,
|
||||||
|
|
@ -431,7 +429,6 @@ void scanAndUpdateAllReferencesTxn(const Transaction & txn, const Path & statePa
|
||||||
drvPath,
|
drvPath,
|
||||||
-1); //Set at a new timestamp
|
-1); //Set at a new timestamp
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void scanAndUpdateAllReferencesRecusivelyTxn(const Transaction & txn, const Path & statePath) //TODO Can also work for statePaths???
|
void scanAndUpdateAllReferencesRecusivelyTxn(const Transaction & txn, const Path & statePath) //TODO Can also work for statePaths???
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue