* Maintain the references/referers relation also for derivations.
This simplifies garbage collection and `nix-store --query --requisites' since we no longer need to treat derivations specially. * Better maintaining of the invariants, e.g., setReferences() can only be called on a valid/substitutable path.
This commit is contained in:
		
							parent
							
								
									2a2756b856
								
							
						
					
					
						commit
						a24b78e9f1
					
				
					 8 changed files with 84 additions and 82 deletions
				
			
		|  | @ -1135,8 +1135,7 @@ void DerivationGoal::computeClosure() | |||
|          i != drv.outputs.end(); ++i) | ||||
|     { | ||||
|         registerValidPath(txn, i->second.path, | ||||
|             contentHashes[i->second.path]); | ||||
|         setReferences(txn, i->second.path, | ||||
|             contentHashes[i->second.path], | ||||
|             allReferences[i->second.path]); | ||||
|     } | ||||
|     txn.commit(); | ||||
|  | @ -1494,7 +1493,7 @@ void SubstitutionGoal::finished() | |||
| 
 | ||||
|     Transaction txn; | ||||
|     createStoreTransaction(txn); | ||||
|     registerValidPath(txn, storePath, contentHash); | ||||
|     registerValidPath(txn, storePath, contentHash, references); | ||||
|     txn.commit(); | ||||
| 
 | ||||
|     outputLock->setDeletion(true); | ||||
|  |  | |||
|  | @ -28,23 +28,4 @@ Derivation derivationFromPath(const Path & drvPath); | |||
| void computeFSClosure(const Path & storePath, | ||||
|     PathSet & paths, bool flipDirection = false); | ||||
| 
 | ||||
| /* Place in `paths' the set of paths that are required to `realise'
 | ||||
|    the given store path, i.e., all paths necessary for valid | ||||
|    deployment of the path.  For a derivation, this is the union of | ||||
|    requisites of the inputs, plus the derivation; for other store | ||||
|    paths, it is the set of paths in the FS closure of the path.  If | ||||
|    `includeOutputs' is true, include the requisites of the output | ||||
|    paths of derivations as well. | ||||
| 
 | ||||
|    Note that this function can be used to implement three different | ||||
|    deployment policies: | ||||
| 
 | ||||
|    - Source deployment (when called on a derivation). | ||||
|    - Binary deployment (when called on an output path). | ||||
|    - Source/binary deployment (when called on a derivation with | ||||
|      `includeOutputs' set to true). | ||||
| */ | ||||
| void storePathRequisites(const Path & storePath, | ||||
|     bool includeOutputs, PathSet & paths); | ||||
| 
 | ||||
| #endif /* !__BUILD_H */ | ||||
|  |  | |||
|  | @ -14,8 +14,16 @@ Hash hashTerm(ATerm t) | |||
| 
 | ||||
| Path writeDerivation(const Derivation & drv, const string & name) | ||||
| { | ||||
|     PathSet references; | ||||
|     references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end()); | ||||
|     for (DerivationInputs::const_iterator i = drv.inputDrvs.begin(); | ||||
|          i != drv.inputDrvs.end(); ++i) | ||||
|         references.insert(i->first); | ||||
|     /* Note that the outputs of a derivation are *not* references
 | ||||
|        (that can be missing (of course) and should not necessarily be | ||||
|        held during a garbage collection). */ | ||||
|     return addTextToStore(name + drvExtension, | ||||
|         atPrint(unparseDerivation(drv))); | ||||
|         atPrint(unparseDerivation(drv)), references); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,44 +27,3 @@ void computeFSClosure(const Path & storePath, | |||
|          i != references.end(); ++i) | ||||
|         computeFSClosure(*i, paths, flipDirection); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void storePathRequisites(const Path & storePath, | ||||
|     bool includeOutputs, PathSet & paths) | ||||
| { | ||||
|     checkInterrupt(); | ||||
|      | ||||
|     if (paths.find(storePath) != paths.end()) return; | ||||
| 
 | ||||
|     if (isDerivation(storePath)) { | ||||
| 
 | ||||
|         paths.insert(storePath); | ||||
|          | ||||
|         Derivation drv = derivationFromPath(storePath); | ||||
| 
 | ||||
|         for (DerivationInputs::iterator i = drv.inputDrvs.begin(); | ||||
|              i != drv.inputDrvs.end(); ++i) | ||||
|             /* !!! Maybe this is too strict, since it will include
 | ||||
|                *all* output paths of the input derivation, not just | ||||
|                the ones needed by this derivation. */ | ||||
|             storePathRequisites(i->first, includeOutputs, paths); | ||||
| 
 | ||||
|         for (PathSet::iterator i = drv.inputSrcs.begin(); | ||||
|              i != drv.inputSrcs.end(); ++i) | ||||
|             storePathRequisites(*i, includeOutputs, paths); | ||||
| 
 | ||||
|         if (includeOutputs) { | ||||
| 
 | ||||
|             for (DerivationOutputs::iterator i = drv.outputs.begin(); | ||||
|                  i != drv.outputs.end(); ++i) | ||||
|                 if (isValidPath(i->second.path)) | ||||
|                     storePathRequisites(i->second.path, includeOutputs, paths); | ||||
| 
 | ||||
|         } | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|     else { | ||||
|         computeFSClosure(storePath, paths); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -229,7 +229,7 @@ void canonicalisePathMetaData(const Path & path) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| static bool isValidPathTxn(const Path & path, const Transaction & txn) | ||||
| static bool isValidPathTxn(const Transaction & txn, const Path & path) | ||||
| { | ||||
|     string s; | ||||
|     return nixDB.queryString(txn, dbValidPaths, path, s); | ||||
|  | @ -238,13 +238,29 @@ static bool isValidPathTxn(const Path & path, const Transaction & txn) | |||
| 
 | ||||
| bool isValidPath(const Path & path) | ||||
| { | ||||
|     return isValidPathTxn(path, noTxn); | ||||
|     return isValidPathTxn(noTxn, path); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Substitutes readSubstitutes(const Transaction & txn, | ||||
|     const Path & srcPath); | ||||
| 
 | ||||
| 
 | ||||
| static bool isRealisablePath(const Transaction & txn, const Path & path) | ||||
| { | ||||
|     return isValidPathTxn(txn, path) | ||||
|         || readSubstitutes(txn, path).size() > 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void setReferences(const Transaction & txn, const Path & storePath, | ||||
|     const PathSet & references) | ||||
| { | ||||
|     if (!isRealisablePath(txn, storePath)) | ||||
|         throw Error( | ||||
|             format("cannot set references for path `%1%' which is invalid and has no substitutes") | ||||
|             % storePath); | ||||
|      | ||||
|     nixDB.setStrings(txn, dbReferences, storePath, | ||||
|         Paths(references.begin(), references.end())); | ||||
| 
 | ||||
|  | @ -265,8 +281,8 @@ void setReferences(const Transaction & txn, const Path & storePath, | |||
| void queryReferences(const Path & storePath, PathSet & references) | ||||
| { | ||||
|     Paths references2; | ||||
|     //    if (!isValidPath(storePath))
 | ||||
|     //        throw Error(format("path `%1%' is not valid") % storePath);
 | ||||
|     if (!isRealisablePath(noTxn, storePath)) | ||||
|         throw Error(format("path `%1%' is not valid") % storePath); | ||||
|     nixDB.queryStrings(noTxn, dbReferences, storePath, references2); | ||||
|     references.insert(references2.begin(), references2.end()); | ||||
| } | ||||
|  | @ -275,8 +291,8 @@ void queryReferences(const Path & storePath, PathSet & references) | |||
| void queryReferers(const Path & storePath, PathSet & referers) | ||||
| { | ||||
|     Paths referers2; | ||||
|     //    if (!isValidPath(storePath))
 | ||||
|     //        throw Error(format("path `%1%' is not valid") % storePath);
 | ||||
|     if (!isRealisablePath(noTxn, storePath)) | ||||
|         throw Error(format("path `%1%' is not valid") % storePath); | ||||
|     nixDB.queryStrings(noTxn, dbReferers, storePath, referers2); | ||||
|     referers.insert(referers2.begin(), referers2.end()); | ||||
| } | ||||
|  | @ -370,7 +386,7 @@ void clearSubstitutes() | |||
| 
 | ||||
| 
 | ||||
| void registerValidPath(const Transaction & txn, | ||||
|     const Path & _path, const Hash & hash) | ||||
|     const Path & _path, const Hash & hash, const PathSet & references) | ||||
| { | ||||
|     Path path(canonPath(_path)); | ||||
|     assertStorePath(path); | ||||
|  | @ -380,11 +396,11 @@ void registerValidPath(const Transaction & txn, | |||
|     debug(format("registering path `%1%'") % path); | ||||
|     nixDB.setString(txn, dbValidPaths, path, "sha256:" + printHash(hash)); | ||||
| 
 | ||||
|     setReferences(txn, path, references); | ||||
|      | ||||
|     /* Check that all referenced paths are also valid. */ | ||||
|     Paths references; | ||||
|     nixDB.queryStrings(txn, dbReferences, path, references); | ||||
|     for (Paths::iterator i = references.begin(); i != references.end(); ++i) | ||||
|         if (!isValidPathTxn(*i, txn)) | ||||
|     for (PathSet::iterator i = references.begin(); i != references.end(); ++i) | ||||
|         if (!isValidPathTxn(txn, *i)) | ||||
|             throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid") | ||||
|                 % path % *i); | ||||
| } | ||||
|  | @ -451,7 +467,7 @@ Path addToStore(const Path & _srcPath) | |||
|             canonicalisePathMetaData(dstPath); | ||||
|              | ||||
|             Transaction txn(nixDB); | ||||
|             registerValidPath(txn, dstPath, h); | ||||
|             registerValidPath(txn, dstPath, h, PathSet()); | ||||
|             txn.commit(); | ||||
|         } | ||||
| 
 | ||||
|  | @ -462,7 +478,8 @@ Path addToStore(const Path & _srcPath) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| Path addTextToStore(const string & suffix, const string & s) | ||||
| Path addTextToStore(const string & suffix, const string & s, | ||||
|     const PathSet & references) | ||||
| { | ||||
|     Hash hash = hashString(htSHA256, s); | ||||
| 
 | ||||
|  | @ -483,7 +500,8 @@ Path addTextToStore(const string & suffix, const string & s) | |||
|             canonicalisePathMetaData(dstPath); | ||||
|              | ||||
|             Transaction txn(nixDB); | ||||
|             registerValidPath(txn, dstPath, hashPath(htSHA256, dstPath)); | ||||
|             registerValidPath(txn, dstPath, | ||||
|                 hashPath(htSHA256, dstPath), references); | ||||
|             txn.commit(); | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ void clearSubstitutes(); | |||
|    of the file system contents of the path.  The hash must be a | ||||
|    SHA-256 hash. */ | ||||
| void registerValidPath(const Transaction & txn, | ||||
|     const Path & path, const Hash & hash); | ||||
|     const Path & path, const Hash & hash, const PathSet & references); | ||||
| 
 | ||||
| /* Throw an exception if `path' is not directly in the Nix store. */ | ||||
| void assertStorePath(const Path & path); | ||||
|  | @ -97,7 +97,8 @@ Path addToStore(const Path & srcPath); | |||
| 
 | ||||
| /* Like addToStore, but the contents written to the output path is a
 | ||||
|    regular file containing the given string. */ | ||||
| Path addTextToStore(const string & suffix, const string & s); | ||||
| Path addTextToStore(const string & suffix, const string & s, | ||||
|     const PathSet & references); | ||||
| 
 | ||||
| /* Delete a value from the nixStore directory. */ | ||||
| void deleteFromStore(const Path & path); | ||||
|  |  | |||
|  | @ -205,7 +205,8 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs, | |||
| 
 | ||||
|     /* Also write a copy of the list of inputs to the store; we need
 | ||||
|        it for future modifications of the environment. */ | ||||
|     Path inputsFile = addTextToStore("env-inputs", atPrint(inputs2)); | ||||
|     Path inputsFile = addTextToStore("env-inputs", atPrint(inputs2), | ||||
|         PathSet() /* !!! incorrect */); | ||||
| 
 | ||||
|     Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3( | ||||
|         makeBind(toATerm("system"), | ||||
|  |  | |||
|  | @ -74,6 +74,41 @@ static void opAdd(Strings opFlags, Strings opArgs) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Place in `paths' the set of paths that are required to `realise'
 | ||||
|    the given store path, i.e., all paths necessary for valid | ||||
|    deployment of the path.  For a derivation, this is the union of | ||||
|    requisites of the inputs, plus the derivation; for other store | ||||
|    paths, it is the set of paths in the FS closure of the path.  If | ||||
|    `includeOutputs' is true, include the requisites of the output | ||||
|    paths of derivations as well. | ||||
| 
 | ||||
|    Note that this function can be used to implement three different | ||||
|    deployment policies: | ||||
| 
 | ||||
|    - Source deployment (when called on a derivation). | ||||
|    - Binary deployment (when called on an output path). | ||||
|    - Source/binary deployment (when called on a derivation with | ||||
|      `includeOutputs' set to true). | ||||
| */ | ||||
| static void storePathRequisites(const Path & storePath, | ||||
|     bool includeOutputs, PathSet & paths) | ||||
| { | ||||
|     computeFSClosure(storePath, paths); | ||||
| 
 | ||||
|     if (includeOutputs) { | ||||
|         for (PathSet::iterator i = paths.begin(); | ||||
|              i != paths.end(); ++i) | ||||
|             if (isDerivation(*i)) { | ||||
|                 Derivation drv = derivationFromPath(*i); | ||||
|                 for (DerivationOutputs::iterator j = drv.outputs.begin(); | ||||
|                      j != drv.outputs.end(); ++j) | ||||
|                     if (isValidPath(j->second.path)) | ||||
|                         computeFSClosure(j->second.path, paths); | ||||
|             } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Path maybeUseOutput(const Path & storePath, bool useOutput, bool forceRealise) | ||||
| { | ||||
|     if (forceRealise) realisePath(storePath); | ||||
|  | @ -221,7 +256,7 @@ static void opValidPath(Strings opFlags, Strings opArgs) | |||
|     createStoreTransaction(txn); | ||||
|     for (Strings::iterator i = opArgs.begin(); | ||||
|          i != opArgs.end(); ++i) | ||||
|         registerValidPath(txn, *i, hashPath(htSHA256, *i)); | ||||
|         registerValidPath(txn, *i, hashPath(htSHA256, *i), PathSet()); | ||||
|     txn.commit(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue