* Made `nix-store -qR --include-outputs' much faster if there are

multiple paths specified on the command line (from O(n * m) to O(n +
  m), where n is the number of arguments and m is the size of the
  closure).
This commit is contained in:
Eelco Dolstra 2010-01-25 17:18:44 +00:00
parent 50e34891f0
commit fdcaf37361
3 changed files with 13 additions and 41 deletions

View file

@ -19,7 +19,7 @@ Derivation derivationFromPath(const Path & drvPath)
void computeFSClosure(const Path & storePath, void computeFSClosure(const Path & storePath,
PathSet & paths, bool flipDirection) PathSet & paths, bool flipDirection, bool includeOutputs)
{ {
if (paths.find(storePath) != paths.end()) return; if (paths.find(storePath) != paths.end()) return;
paths.insert(storePath); paths.insert(storePath);
@ -30,8 +30,15 @@ void computeFSClosure(const Path & storePath,
else else
store->queryReferences(storePath, references); store->queryReferences(storePath, references);
if (includeOutputs && isDerivation(storePath)) {
Derivation drv = derivationFromPath(storePath);
foreach (DerivationOutputs::iterator, i, drv.outputs)
if (store->isValidPath(i->second.path))
computeFSClosure(i->second.path, paths, flipDirection, true);
}
foreach (PathSet::iterator, i, references) foreach (PathSet::iterator, i, references)
computeFSClosure(*i, paths, flipDirection); computeFSClosure(*i, paths, flipDirection, includeOutputs);
} }

View file

@ -19,7 +19,8 @@ Derivation derivationFromPath(const Path & drvPath);
`referrers' relation instead of the `references' relation is `referrers' relation instead of the `references' relation is
returned. */ returned. */
void computeFSClosure(const Path & storePath, void computeFSClosure(const Path & storePath,
PathSet & paths, bool flipDirection = false); PathSet & paths, bool flipDirection = false,
bool includeOutputs = false);
/* Return the path corresponding to the output identifier `id' in the /* Return the path corresponding to the output identifier `id' in the
given derivation. */ given derivation. */

View file

@ -165,41 +165,6 @@ static void opPrintFixedPath(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 (store->isValidPath(j->second.path))
computeFSClosure(j->second.path, paths);
}
}
}
static Path maybeUseOutput(const Path & storePath, bool useOutput, bool forceRealise) static Path maybeUseOutput(const Path & storePath, bool useOutput, bool forceRealise)
{ {
if (forceRealise) realisePath(storePath); if (forceRealise) realisePath(storePath);
@ -310,8 +275,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
PathSet paths; PathSet paths;
foreach (Strings::iterator, i, opArgs) { foreach (Strings::iterator, i, opArgs) {
Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise); Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise);
if (query == qRequisites) if (query == qRequisites) computeFSClosure(path, paths, false, includeOutputs);
storePathRequisites(path, includeOutputs, paths);
else if (query == qReferences) store->queryReferences(path, paths); else if (query == qReferences) store->queryReferences(path, paths);
else if (query == qReferrers) store->queryReferrers(path, paths); else if (query == qReferrers) store->queryReferrers(path, paths);
else if (query == qReferrersClosure) computeFSClosure(path, paths, true); else if (query == qReferrersClosure) computeFSClosure(path, paths, true);