From fdcaf37361126793a1416ef5b348e5bf2f0fd1a0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 25 Jan 2010 17:18:44 +0000 Subject: [PATCH] * 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). --- src/libstore/misc.cc | 11 +++++++++-- src/libstore/misc.hh | 3 ++- src/nix-store/nix-store.cc | 40 ++------------------------------------ 3 files changed, 13 insertions(+), 41 deletions(-) diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index f2b4c7a4ee..2d7d13a0e7 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -19,7 +19,7 @@ Derivation derivationFromPath(const Path & drvPath) void computeFSClosure(const Path & storePath, - PathSet & paths, bool flipDirection) + PathSet & paths, bool flipDirection, bool includeOutputs) { if (paths.find(storePath) != paths.end()) return; paths.insert(storePath); @@ -30,8 +30,15 @@ void computeFSClosure(const Path & storePath, else 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) - computeFSClosure(*i, paths, flipDirection); + computeFSClosure(*i, paths, flipDirection, includeOutputs); } diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh index f3aa34076c..0bc9a2ee0d 100644 --- a/src/libstore/misc.hh +++ b/src/libstore/misc.hh @@ -19,7 +19,8 @@ Derivation derivationFromPath(const Path & drvPath); `referrers' relation instead of the `references' relation is returned. */ 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 given derivation. */ diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index b873baacb9..22effc65dc 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -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) { if (forceRealise) realisePath(storePath); @@ -310,10 +275,9 @@ static void opQuery(Strings opFlags, Strings opArgs) PathSet paths; foreach (Strings::iterator, i, opArgs) { Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise); - if (query == qRequisites) - storePathRequisites(path, includeOutputs, paths); + if (query == qRequisites) computeFSClosure(path, paths, false, includeOutputs); 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); } Paths sorted = topoSortPaths(paths);