blob: 7b944d3831a87fad7c105e056160c47d1c19df75 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Janak Ramakrishnane72d5222015-02-26 17:09:18 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.query2;
15
nharmata1bd4aaf2017-10-31 11:23:04 -040016import static com.google.common.collect.ImmutableSet.toImmutableSet;
Googler73b7b2e2017-03-23 17:20:58 +000017import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
shreyax432b2532019-01-23 11:16:07 -080018import static com.google.devtools.build.lib.pkgcache.FilteringPolicies.NO_FILTER;
Googler73b7b2e2017-03-23 17:20:58 +000019
Nathan Harmata46e5e412016-06-29 16:18:10 +000020import com.google.common.base.Ascii;
Janak Ramakrishnan36858732015-06-17 16:45:47 +000021import com.google.common.base.Function;
tomlua155b532017-11-08 20:12:47 +010022import com.google.common.base.Preconditions;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000023import com.google.common.base.Predicate;
Janak Ramakrishnanb735d2f2015-06-16 17:46:36 +000024import com.google.common.base.Predicates;
Nathan Harmata79e49652016-12-16 22:00:48 +000025import com.google.common.base.Throwables;
Janak Ramakrishnanf6f0fcc2015-06-19 20:24:52 +000026import com.google.common.collect.ArrayListMultimap;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000027import com.google.common.collect.Collections2;
Janak Ramakrishnancda5b662015-06-18 23:46:36 +000028import com.google.common.collect.ImmutableList;
Janak Ramakrishnan36858732015-06-17 16:45:47 +000029import com.google.common.collect.ImmutableMap;
nharmata398e6dab2018-04-12 15:31:26 -070030import com.google.common.collect.ImmutableMultimap;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000031import com.google.common.collect.ImmutableSet;
32import com.google.common.collect.Iterables;
Googlerd1911622016-06-27 15:43:11 +000033import com.google.common.collect.Maps;
Janak Ramakrishnan36858732015-06-17 16:45:47 +000034import com.google.common.collect.Multimap;
Miguel Alcon Pinto933c13a2015-09-16 18:37:45 +000035import com.google.common.collect.Sets;
Nathan Harmata7a5a2362017-03-08 22:42:01 +000036import com.google.common.util.concurrent.AsyncFunction;
37import com.google.common.util.concurrent.Futures;
38import com.google.common.util.concurrent.ListenableFuture;
39import com.google.common.util.concurrent.ListeningExecutorService;
40import com.google.common.util.concurrent.MoreExecutors;
41import com.google.common.util.concurrent.ThreadFactoryBuilder;
shahan602cc852018-06-06 20:09:57 -070042import com.google.devtools.build.lib.actions.FileStateValue;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000043import com.google.devtools.build.lib.cmdline.Label;
dannarkbe3cefc2018-12-13 11:52:45 -080044import com.google.devtools.build.lib.cmdline.LabelConstants;
Kristina Chodorow73fa2032015-08-28 17:57:46 +000045import com.google.devtools.build.lib.cmdline.PackageIdentifier;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000046import com.google.devtools.build.lib.cmdline.TargetParsingException;
Mark Schallerb889cf32015-03-17 20:55:30 +000047import com.google.devtools.build.lib.cmdline.TargetPattern;
philwo3bcb9f62017-09-06 12:52:21 +020048import com.google.devtools.build.lib.collect.compacthashset.CompactHashSet;
Nathan Harmata7a5a2362017-03-08 22:42:01 +000049import com.google.devtools.build.lib.concurrent.BlockingStack;
Nathan Harmata41b54172016-11-10 18:54:09 +000050import com.google.devtools.build.lib.concurrent.MultisetSemaphore;
Mark Schaller20c75012016-06-21 22:51:14 +000051import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
Mark Schaller4f48f1b2017-03-10 20:38:43 +000052import com.google.devtools.build.lib.events.DelegatingEventHandler;
Janak Ramakrishnan3533ab52016-01-14 18:14:09 +000053import com.google.devtools.build.lib.events.Event;
Mark Schaller4f48f1b2017-03-10 20:38:43 +000054import com.google.devtools.build.lib.events.EventKind;
Klaus Aehlig777b30d2017-02-24 16:30:15 +000055import com.google.devtools.build.lib.events.ExtendedEventHandler;
Janak Ramakrishnan0a4c6e42015-09-17 00:37:58 +000056import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
Dmitry Lomov6073eb62016-01-21 21:26:32 +000057import com.google.devtools.build.lib.packages.DependencyFilter;
Janak Ramakrishnan112840b2016-12-29 21:49:56 +000058import com.google.devtools.build.lib.packages.NoSuchPackageException;
Janak Ramakrishnan36858732015-06-17 16:45:47 +000059import com.google.devtools.build.lib.packages.NoSuchTargetException;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000060import com.google.devtools.build.lib.packages.NoSuchThingException;
61import com.google.devtools.build.lib.packages.Package;
62import com.google.devtools.build.lib.packages.Rule;
63import com.google.devtools.build.lib.packages.Target;
ulfjacke83775d2019-05-14 08:58:46 -070064import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
Mark Schallerb889cf32015-03-17 20:55:30 +000065import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
Nathan Harmata483ded92016-01-13 19:42:45 +000066import com.google.devtools.build.lib.profiler.AutoProfiler;
Janak Ramakrishnan643063d2015-06-25 16:21:49 +000067import com.google.devtools.build.lib.query2.engine.AllRdepsFunction;
Miguel Alcon Pinto42984f32015-11-06 19:05:13 +000068import com.google.devtools.build.lib.query2.engine.Callback;
Nathan Harmatae9826b42017-03-07 18:05:21 +000069import com.google.devtools.build.lib.query2.engine.KeyExtractor;
70import com.google.devtools.build.lib.query2.engine.MinDepthUniquifier;
Nathan Harmata5bb9cc92016-09-30 21:28:30 +000071import com.google.devtools.build.lib.query2.engine.OutputFormatterCallback;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000072import com.google.devtools.build.lib.query2.engine.QueryEvalResult;
73import com.google.devtools.build.lib.query2.engine.QueryException;
74import com.google.devtools.build.lib.query2.engine.QueryExpression;
shreyax159a6112018-06-12 15:34:09 -070075import com.google.devtools.build.lib.query2.engine.QueryExpressionContext;
Nathan Harmataed935602016-03-02 01:16:14 +000076import com.google.devtools.build.lib.query2.engine.QueryExpressionMapper;
Nathan Harmata7a5a2362017-03-08 22:42:01 +000077import com.google.devtools.build.lib.query2.engine.QueryUtil.MinDepthUniquifierImpl;
nharmatabf2e2d82017-06-21 23:12:51 +020078import com.google.devtools.build.lib.query2.engine.QueryUtil.MutableKeyExtractorBackedMapImpl;
nharmatac49e8742018-09-27 11:27:41 -070079import com.google.devtools.build.lib.query2.engine.QueryUtil.NonExceptionalUniquifier;
nharmatabf2e2d82017-06-21 23:12:51 +020080import com.google.devtools.build.lib.query2.engine.QueryUtil.ThreadSafeMutableKeyExtractorBackedSetImpl;
Nathan Harmata7a5a2362017-03-08 22:42:01 +000081import com.google.devtools.build.lib.query2.engine.QueryUtil.UniquifierImpl;
Googlerd1911622016-06-27 15:43:11 +000082import com.google.devtools.build.lib.query2.engine.StreamableQueryEnvironment;
Nathan Harmata7a5a2362017-03-08 22:42:01 +000083import com.google.devtools.build.lib.query2.engine.ThreadSafeOutputFormatterCallback;
Miguel Alcon Pinto42984f32015-11-06 19:05:13 +000084import com.google.devtools.build.lib.query2.engine.Uniquifier;
gregcea91495f2019-05-07 07:27:39 -070085import com.google.devtools.build.lib.query2.query.BlazeTargetAccessor;
Nathan Harmata4d89d112016-04-17 02:46:15 +000086import com.google.devtools.build.lib.skyframe.BlacklistedPackagePrefixesValue;
Nathan Harmatac686fd62016-04-26 17:41:20 +000087import com.google.devtools.build.lib.skyframe.ContainingPackageLookupFunction;
Mark Schallerb889cf32015-03-17 20:55:30 +000088import com.google.devtools.build.lib.skyframe.GraphBackedRecursivePackageProvider;
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +000089import com.google.devtools.build.lib.skyframe.PackageLookupValue;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000090import com.google.devtools.build.lib.skyframe.PackageValue;
Janak Ramakrishnan958ef822016-01-07 16:21:39 +000091import com.google.devtools.build.lib.skyframe.PrepareDepsOfPatternsFunction;
Mark Schallerb889cf32015-03-17 20:55:30 +000092import com.google.devtools.build.lib.skyframe.RecursivePackageProviderBackedTargetPatternResolver;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000093import com.google.devtools.build.lib.skyframe.TargetPatternValue;
Mark Schallerd7311e02015-07-07 16:36:09 +000094import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternKey;
Mark Schaller8ff5b3c2015-07-29 17:32:11 +000095import com.google.devtools.build.lib.skyframe.TransitiveTraversalValue;
juliexxiacc864752018-06-01 09:03:48 -070096import com.google.devtools.build.lib.skyframe.TraversalInfoRootPackageExtractor;
Googler407d3932019-05-16 15:13:59 -070097import com.google.devtools.build.lib.supplier.InterruptibleSupplier;
98import com.google.devtools.build.lib.supplier.MemoizingInterruptibleSupplier;
John Catere5fb5f02017-12-04 07:53:19 -080099import com.google.devtools.build.lib.vfs.Path;
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +0000100import com.google.devtools.build.lib.vfs.PathFragment;
101import com.google.devtools.build.lib.vfs.RootedPath;
Googler10028672018-10-25 12:14:34 -0700102import com.google.devtools.build.skyframe.EvaluationContext;
Mark Schallerd7311e02015-07-07 16:36:09 +0000103import com.google.devtools.build.skyframe.EvaluationResult;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000104import com.google.devtools.build.skyframe.SkyFunctionName;
105import com.google.devtools.build.skyframe.SkyKey;
Janak Ramakrishnan36858732015-06-17 16:45:47 +0000106import com.google.devtools.build.skyframe.SkyValue;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000107import com.google.devtools.build.skyframe.WalkableGraph;
108import com.google.devtools.build.skyframe.WalkableGraph.WalkableGraphFactory;
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000109import java.io.IOException;
Miguel Alcon Pinto47ea9482015-11-18 16:05:17 +0000110import java.util.ArrayList;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000111import java.util.Collection;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000112import java.util.HashSet;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000113import java.util.List;
114import java.util.Map;
115import java.util.Set;
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000116import java.util.concurrent.Callable;
117import java.util.concurrent.RejectedExecutionException;
118import java.util.concurrent.ThreadPoolExecutor;
Nathan Harmata71616b12016-09-28 20:20:48 +0000119import java.util.concurrent.TimeUnit;
nharmata641db6d2018-08-16 14:31:57 -0700120import java.util.function.BiConsumer;
Nathan Harmata79e49652016-12-16 22:00:48 +0000121import java.util.logging.Level;
Eric Fellheimera39f8a92015-07-28 19:11:23 +0000122import java.util.logging.Logger;
Janak Ramakrishnanb5a541a2015-06-19 20:55:01 +0000123
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000124/**
125 * {@link AbstractBlazeQueryEnvironment} that introspects the Skyframe graph to find forward and
Googlerd1911622016-06-27 15:43:11 +0000126 * reverse edges. Results obtained by calling {@link #evaluateQuery} are not guaranteed to be in any
127 * particular order. As well, this class eagerly loads the full transitive closure of targets, even
128 * if the full closure isn't needed.
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000129 *
130 * <p>This class has concurrent implementations of the
131 * {@link QueryTaskFuture}/{@link QueryTaskCallable} helper methods. The combination of this and the
132 * asynchronous evaluation model yields parallel query evaluation.
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000133 */
Googlerd1911622016-06-27 15:43:11 +0000134public class SkyQueryEnvironment extends AbstractBlazeQueryEnvironment<Target>
135 implements StreamableQueryEnvironment<Target> {
Janak Ramakrishnanae3a20a2016-01-08 16:24:29 +0000136 // 10k is likely a good balance between using batch efficiently and not blowing up memory.
137 // TODO(janakr): Unify with RecursivePackageProviderBackedTargetPatternResolver's constant.
nharmata1bd4aaf2017-10-31 11:23:04 -0400138 protected static final int BATCH_CALLBACK_SIZE = 10000;
gregcea91495f2019-05-07 07:27:39 -0700139 public static final int DEFAULT_THREAD_COUNT = Runtime.getRuntime().availableProcessors();
Nathan Harmata116c2f62016-06-28 15:58:20 +0000140 private static final int MAX_QUERY_EXPRESSION_LOG_CHARS = 1000;
lberki97abb522017-09-04 18:51:57 +0200141 private static final Logger logger = Logger.getLogger(SkyQueryEnvironment.class.getName());
Mark Schallerd7311e02015-07-07 16:36:09 +0000142
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000143 private final BlazeTargetAccessor accessor = new BlazeTargetAccessor(this);
Janak Ramakrishnandf694322016-11-08 18:28:12 +0000144 protected final int loadingPhaseThreads;
145 protected final WalkableGraphFactory graphFactory;
Janak Ramakrishnane77b6d22016-11-08 18:44:55 +0000146 protected final ImmutableList<String> universeScope;
Mark Schaller4f48f1b2017-03-10 20:38:43 +0000147 protected boolean blockUniverseEvaluationErrors;
148 protected ExtendedEventHandler universeEvalEventHandler;
149
Nathan Harmata64543472016-06-30 18:33:40 +0000150 protected final String parserPrefix;
Janak Ramakrishnandf694322016-11-08 18:28:12 +0000151 protected final PathPackageLocator pkgPath;
nharmatafac7c252018-09-12 15:31:23 -0700152 protected final int queryEvaluationParallelismLevel;
Mark Schaller6cebed62016-06-27 18:05:39 +0000153
154 // The following fields are set in the #beforeEvaluateQuery method.
Nathan Harmata41b54172016-11-10 18:54:09 +0000155 private MultisetSemaphore<PackageIdentifier> packageSemaphore;
Mark Schaller6cebed62016-06-27 18:05:39 +0000156 protected WalkableGraph graph;
Googleree343922019-03-05 08:51:12 -0800157 protected InterruptibleSupplier<ImmutableSet<PathFragment>> blacklistPatternsSupplier;
158 protected GraphBackedRecursivePackageProvider graphBackedRecursivePackageProvider;
159 protected ListeningExecutorService executor;
Mark Schallerd9d390a2016-06-21 22:01:28 +0000160 private RecursivePackageProviderBackedTargetPatternResolver resolver;
Googler5e65c982017-08-17 05:21:54 +0200161 protected final SkyKey universeKey;
Janak Ramakrishnan63edbd32016-11-11 18:56:25 +0000162 private final ImmutableList<TargetPatternKey> universeTargetPatternKeys;
Miguel Alcon Pintob45e2622015-08-21 18:31:23 +0000163
Mark Schaller4b801f22016-06-21 22:26:12 +0000164 public SkyQueryEnvironment(
165 boolean keepGoing,
166 int loadingPhaseThreads,
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000167 ExtendedEventHandler eventHandler,
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000168 Set<Setting> settings,
Mark Schaller20c75012016-06-21 22:51:14 +0000169 Iterable<QueryFunction> extraFunctions,
170 String parserPrefix,
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000171 WalkableGraphFactory graphFactory,
Mark Schaller20c75012016-06-21 22:51:14 +0000172 List<String> universeScope,
Mark Schaller4f48f1b2017-03-10 20:38:43 +0000173 PathPackageLocator pkgPath,
174 boolean blockUniverseEvaluationErrors) {
Nathan Harmata2e2b4592016-09-21 17:17:33 +0000175 this(
176 keepGoing,
177 loadingPhaseThreads,
178 // SkyQueryEnvironment operates on a prepopulated Skyframe graph. Therefore, query
179 // evaluation is completely CPU-bound.
180 /*queryEvaluationParallelismLevel=*/ DEFAULT_THREAD_COUNT,
181 eventHandler,
182 settings,
183 extraFunctions,
Nathan Harmata2e2b4592016-09-21 17:17:33 +0000184 parserPrefix,
185 graphFactory,
186 universeScope,
Mark Schaller4f48f1b2017-03-10 20:38:43 +0000187 pkgPath,
188 blockUniverseEvaluationErrors);
Nathan Harmata2e2b4592016-09-21 17:17:33 +0000189 }
190
191 protected SkyQueryEnvironment(
192 boolean keepGoing,
193 int loadingPhaseThreads,
194 int queryEvaluationParallelismLevel,
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000195 ExtendedEventHandler eventHandler,
Nathan Harmata2e2b4592016-09-21 17:17:33 +0000196 Set<Setting> settings,
197 Iterable<QueryFunction> extraFunctions,
Nathan Harmata2e2b4592016-09-21 17:17:33 +0000198 String parserPrefix,
199 WalkableGraphFactory graphFactory,
200 List<String> universeScope,
Mark Schaller4f48f1b2017-03-10 20:38:43 +0000201 PathPackageLocator pkgPath,
202 boolean blockUniverseEvaluationErrors) {
Mark Schaller4b801f22016-06-21 22:26:12 +0000203 super(
204 keepGoing,
205 /*strictScope=*/ true,
206 /*labelFilter=*/ Rule.ALL_LABELS,
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000207 eventHandler,
208 settings,
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000209 extraFunctions);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000210 this.loadingPhaseThreads = loadingPhaseThreads;
211 this.graphFactory = graphFactory;
Mark Schallerb889cf32015-03-17 20:55:30 +0000212 this.pkgPath = pkgPath;
Janak Ramakrishnane77b6d22016-11-08 18:44:55 +0000213 this.universeScope = ImmutableList.copyOf(Preconditions.checkNotNull(universeScope));
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000214 this.parserPrefix = parserPrefix;
Nathan Harmata71616b12016-09-28 20:20:48 +0000215 Preconditions.checkState(
216 !universeScope.isEmpty(), "No queries can be performed with an empty universe");
217 this.queryEvaluationParallelismLevel = queryEvaluationParallelismLevel;
Janak Ramakrishnane77b6d22016-11-08 18:44:55 +0000218 this.universeKey = graphFactory.getUniverseKey(universeScope, parserPrefix);
Mark Schaller4f48f1b2017-03-10 20:38:43 +0000219 this.blockUniverseEvaluationErrors = blockUniverseEvaluationErrors;
220 this.universeEvalEventHandler =
221 this.blockUniverseEvaluationErrors
222 ? new ErrorBlockingForwardingEventHandler(this.eventHandler)
223 : this.eventHandler;
224 this.universeTargetPatternKeys =
Janak Ramakrishnan63edbd32016-11-11 18:56:25 +0000225 PrepareDepsOfPatternsFunction.getTargetPatternKeys(
226 PrepareDepsOfPatternsFunction.getSkyKeys(universeKey, eventHandler));
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000227 }
228
mschallerfe883872017-07-17 22:40:11 +0200229 @Override
230 public void close() {
231 if (executor != null) {
232 executor.shutdownNow();
233 executor = null;
234 }
235 }
236
Googler5e65c982017-08-17 05:21:54 +0200237 /** Gets roots of graph which contains all nodes needed to evaluate {@code expr}. */
238 protected Set<SkyKey> getGraphRootsFromExpression(QueryExpression expr)
239 throws QueryException, InterruptedException {
240 return ImmutableSet.of(universeKey);
241 }
242
nharmata6147ebf2018-10-09 08:43:49 -0700243 protected void beforeEvaluateQuery(QueryExpression expr)
Googler5e65c982017-08-17 05:21:54 +0200244 throws QueryException, InterruptedException {
245 Set<SkyKey> roots = getGraphRootsFromExpression(expr);
Googler5e65c982017-08-17 05:21:54 +0200246
Googler53755202018-02-13 11:37:30 -0800247 EvaluationResult<SkyValue> result;
248 try (AutoProfiler p = AutoProfiler.logged("evaluation and walkable graph", logger)) {
Googler10028672018-10-25 12:14:34 -0700249 EvaluationContext evaluationContext =
250 EvaluationContext.newBuilder()
251 .setNumThreads(loadingPhaseThreads)
252 .setEventHander(universeEvalEventHandler)
253 .build();
Googlerdeb99592018-10-30 12:23:58 -0700254 result = graphFactory.prepareAndGet(roots, configureEvaluationContext(evaluationContext));
Googler53755202018-02-13 11:37:30 -0800255 }
Googler57f228a2017-12-21 08:10:15 -0800256
Googler53755202018-02-13 11:37:30 -0800257 if (graph == null || graph != result.getWalkableGraph()) {
Googler61c48b52017-10-30 17:33:04 -0400258 checkEvaluationResult(roots, result);
Janak Ramakrishnan3207f932016-11-16 23:16:53 +0000259 packageSemaphore = makeFreshPackageMultisetSemaphore();
260 graph = result.getWalkableGraph();
Googler407d3932019-05-16 15:13:59 -0700261 blacklistPatternsSupplier = MemoizingInterruptibleSupplier.of(new BlacklistSupplier(graph));
Janak Ramakrishnan3207f932016-11-16 23:16:53 +0000262 graphBackedRecursivePackageProvider =
juliexxiacc864752018-06-01 09:03:48 -0700263 new GraphBackedRecursivePackageProvider(
264 graph, universeTargetPatternKeys, pkgPath, new TraversalInfoRootPackageExtractor());
Eric Fellheimera39f8a92015-07-28 19:11:23 +0000265 }
Googler57f228a2017-12-21 08:10:15 -0800266
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000267 if (executor == null) {
268 executor = MoreExecutors.listeningDecorator(
269 new ThreadPoolExecutor(
270 /*corePoolSize=*/ queryEvaluationParallelismLevel,
271 /*maximumPoolSize=*/ queryEvaluationParallelismLevel,
272 /*keepAliveTime=*/ 1,
273 /*units=*/ TimeUnit.SECONDS,
274 /*workQueue=*/ new BlockingStack<Runnable>(),
275 new ThreadFactoryBuilder().setNameFormat("QueryEnvironment %d").build()));
Janak Ramakrishnan3207f932016-11-16 23:16:53 +0000276 }
Mark Schaller09f42d52017-01-20 21:57:32 +0000277 resolver =
shreyax159a6112018-06-12 15:34:09 -0700278 new RecursivePackageProviderBackedTargetPatternResolver(
Mark Schaller09f42d52017-01-20 21:57:32 +0000279 graphBackedRecursivePackageProvider,
280 eventHandler,
ulfjacke83775d2019-05-14 08:58:46 -0700281 FilteringPolicies.NO_FILTER,
Mark Schaller09f42d52017-01-20 21:57:32 +0000282 packageSemaphore);
Nathan Harmata41b54172016-11-10 18:54:09 +0000283 }
284
Googlerdeb99592018-10-30 12:23:58 -0700285 /**
286 * Configures the default {@link EvaluationContext} to change the behavior of how evaluations in
287 * {@link WalkableGraphFactory#prepareAndGet} work.
288 */
289 protected EvaluationContext configureEvaluationContext(EvaluationContext evaluationContext) {
290 return evaluationContext;
291 }
292
Nathan Harmata41b54172016-11-10 18:54:09 +0000293 protected MultisetSemaphore<PackageIdentifier> makeFreshPackageMultisetSemaphore() {
294 return MultisetSemaphore.unbounded();
295 }
296
297 @ThreadSafe
298 public MultisetSemaphore<PackageIdentifier> getPackageMultisetSemaphore() {
299 return packageSemaphore;
Mark Schaller6cebed62016-06-27 18:05:39 +0000300 }
Janak Ramakrishnan958ef822016-01-07 16:21:39 +0000301
Googler61c48b52017-10-30 17:33:04 -0400302 protected void checkEvaluationResult(Set<SkyKey> roots, EvaluationResult<SkyValue> result)
303 throws QueryException {
304 // If the only root is the universe key, we expect to see either a single successfully evaluated
305 // value or a cycle in the result.
306 if (roots.size() == 1 && Iterables.getOnlyElement(roots).equals(universeKey)) {
307 Collection<SkyValue> values = result.values();
308 if (!values.isEmpty()) {
309 Preconditions.checkState(
310 values.size() == 1,
311 "Universe query \"%s\" returned multiple values unexpectedly (%s values in result)",
312 universeScope,
313 values.size());
314 Preconditions.checkNotNull(result.get(universeKey), result);
315 } else {
316 // No values in the result, so there must be an error. We expect the error to be a cycle.
317 boolean foundCycle = !Iterables.isEmpty(result.getError().getCycleInfo());
318 Preconditions.checkState(
319 foundCycle,
320 "Universe query \"%s\" failed with non-cycle error: %s",
321 universeScope,
322 result.getError());
323 }
Mark Schallerd7311e02015-07-07 16:36:09 +0000324 }
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000325 }
326
327 @Override
Nathan Harmata2643c8e2016-07-01 23:19:23 +0000328 public final QueryExpression transformParsedQuery(QueryExpression queryExpression) {
nharmata327b9112018-01-31 10:48:31 -0800329 QueryExpressionMapper<Void> mapper = getQueryExpressionMapper();
adgard1e1cb72019-05-14 08:32:51 -0700330 QueryExpression transformedQueryExpression;
331 try (AutoProfiler p =
332 AutoProfiler.logged(
333 "transforming query", logger, /*minTimeForLoggingInMilliseconds=*/ 50)) {
334 transformedQueryExpression = queryExpression.accept(mapper);
335 }
lberki97abb522017-09-04 18:51:57 +0200336 logger.info(
337 String.format(
338 "transformed query [%s] to [%s]",
339 Ascii.truncate(
340 queryExpression.toString(), MAX_QUERY_EXPRESSION_LOG_CHARS, "[truncated]"),
341 Ascii.truncate(
342 transformedQueryExpression.toString(),
343 MAX_QUERY_EXPRESSION_LOG_CHARS,
344 "[truncated]")));
Nathan Harmataed935602016-03-02 01:16:14 +0000345 return transformedQueryExpression;
346 }
347
nharmata327b9112018-01-31 10:48:31 -0800348 protected QueryExpressionMapper<Void> getQueryExpressionMapper() {
Nathan Harmata64543472016-06-30 18:33:40 +0000349 if (universeScope.size() != 1) {
Nathan Harmata54a16f02016-12-13 17:49:27 +0000350 return QueryExpressionMapper.identity();
Nathan Harmata64543472016-06-30 18:33:40 +0000351 }
352 TargetPattern.Parser targetPatternParser = new TargetPattern.Parser(parserPrefix);
353 String universeScopePattern = Iterables.getOnlyElement(universeScope);
Nathan Harmata54a16f02016-12-13 17:49:27 +0000354 return new RdepsToAllRdepsQueryExpressionMapper(targetPatternParser, universeScopePattern);
Nathan Harmata64543472016-06-30 18:33:40 +0000355 }
356
Nathan Harmataed935602016-03-02 01:16:14 +0000357 @Override
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000358 protected void evalTopLevelInternal(
359 QueryExpression expr, OutputFormatterCallback<Target> callback)
360 throws QueryException, InterruptedException {
Nathan Harmata79e49652016-12-16 22:00:48 +0000361 Throwable throwableToThrow = null;
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000362 try {
363 super.evalTopLevelInternal(expr, callback);
Nathan Harmata79e49652016-12-16 22:00:48 +0000364 } catch (Throwable throwable) {
365 throwableToThrow = throwable;
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000366 } finally {
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000367 if (throwableToThrow != null) {
lberki97abb522017-09-04 18:51:57 +0200368 logger.log(
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000369 Level.INFO,
370 "About to shutdown query threadpool because of throwable",
371 throwableToThrow);
mschaller6d155d72018-08-28 15:12:34 -0700372 ListeningExecutorService obsoleteExecutor = executor;
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000373 // Signal that executor must be recreated on the next invocation.
374 executor = null;
mschaller6d155d72018-08-28 15:12:34 -0700375
376 // If evaluation failed abruptly (e.g. was interrupted), attempt to terminate all remaining
377 // tasks and then wait for them all to finish. We don't want to leave any dangling threads
378 // running tasks.
379 obsoleteExecutor.shutdownNow();
380 boolean interrupted = false;
381 boolean executorTerminated = false;
382 try {
383 while (!executorTerminated) {
384 try {
385 executorTerminated =
386 obsoleteExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
387 } catch (InterruptedException e) {
388 interrupted = true;
389 handleInterruptedShutdown();
390 }
391 }
392 } finally {
393 if (interrupted) {
394 Thread.currentThread().interrupt();
395 }
396 }
397
Nathan Harmata79e49652016-12-16 22:00:48 +0000398 Throwables.propagateIfPossible(
399 throwableToThrow, QueryException.class, InterruptedException.class);
Janak Ramakrishnan3207f932016-11-16 23:16:53 +0000400 }
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000401 }
402 }
403
mschaller6d155d72018-08-28 15:12:34 -0700404 /**
405 * Subclasses may implement special handling when the query threadpool shutdown process is
406 * interrupted. This isn't likely to happen unless there's a bug in the lifecycle management of
407 * query tasks.
408 */
409 protected void handleInterruptedShutdown() {}
410
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000411 @Override
412 public QueryEvalResult evaluateQuery(
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000413 QueryExpression expr, ThreadSafeOutputFormatterCallback<Target> callback)
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000414 throws QueryException, InterruptedException, IOException {
Googler5e65c982017-08-17 05:21:54 +0200415 beforeEvaluateQuery(expr);
Mark Schaller4d8baf82016-06-21 18:56:04 +0000416
417 // SkyQueryEnvironment batches callback invocations using a BatchStreamedCallback, created here
418 // so that there's one per top-level evaluateQuery call. The batch size is large enough that
419 // per-call costs of calling the original callback are amortized over a good number of targets,
420 // and small enough that holding a batch of targets in memory doesn't risk an OOM error.
421 //
422 // This flushes the batched callback prior to constructing the QueryEvalResult in the unlikely
423 // case of a race between the original callback and the eventHandler.
nharmatafac7c252018-09-12 15:31:23 -0700424 BatchStreamedCallback batchCallback = new BatchStreamedCallback(
425 callback,
426 BATCH_CALLBACK_SIZE,
nharmatac49e8742018-09-27 11:27:41 -0700427 createUniquifierForOuterBatchStreamedCallback(expr));
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000428 return super.evaluateQuery(expr, batchCallback);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000429 }
430
Googlerb3610d52016-10-24 19:18:36 +0000431 private Map<SkyKey, Collection<Target>> targetifyValues(
432 Map<SkyKey, ? extends Iterable<SkyKey>> input) throws InterruptedException {
Nathan Harmata41b54172016-11-10 18:54:09 +0000433 return targetifyValues(
434 input,
435 makePackageKeyToTargetKeyMap(ImmutableSet.copyOf(Iterables.concat(input.values()))));
436 }
437
438 private Map<SkyKey, Collection<Target>> targetifyValues(
439 Map<SkyKey, ? extends Iterable<SkyKey>> input,
440 Multimap<SkyKey, SkyKey> packageKeyToTargetKeyMap) throws InterruptedException {
Nathan Harmatabe597992016-10-10 15:59:00 +0000441 ImmutableMap.Builder<SkyKey, Collection<Target>> result = ImmutableMap.builder();
Googlerd1911622016-06-27 15:43:11 +0000442
Janak Ramakrishnane933d5e2016-01-08 16:43:54 +0000443 Map<SkyKey, Target> allTargets =
nharmata7c56dce2018-08-16 10:50:26 -0700444 getTargetKeyToTargetMapForPackageKeyToTargetKeyMap(packageKeyToTargetKeyMap);
Janak Ramakrishnan36858732015-06-17 16:45:47 +0000445
Googlerb3610d52016-10-24 19:18:36 +0000446 for (Map.Entry<SkyKey, ? extends Iterable<SkyKey>> entry : input.entrySet()) {
Nathan Harmatabe597992016-10-10 15:59:00 +0000447 Iterable<SkyKey> skyKeys = entry.getValue();
Miguel Alcon Pinto933c13a2015-09-16 18:37:45 +0000448 Set<Target> targets = CompactHashSet.createWithExpectedSize(Iterables.size(skyKeys));
449 for (SkyKey key : skyKeys) {
450 Target target = allTargets.get(key);
451 if (target != null) {
452 targets.add(target);
453 }
454 }
Nathan Harmatabe597992016-10-10 15:59:00 +0000455 result.put(entry.getKey(), targets);
Janak Ramakrishnan36858732015-06-17 16:45:47 +0000456 }
457 return result.build();
458 }
459
Nathan Harmatabe597992016-10-10 15:59:00 +0000460 private Map<SkyKey, Collection<Target>> getRawReverseDeps(
461 Iterable<SkyKey> transitiveTraversalKeys) throws InterruptedException {
462 return targetifyValues(graph.getReverseDeps(transitiveTraversalKeys));
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000463 }
464
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000465 private Set<Label> getAllowedDeps(Rule rule) throws InterruptedException {
Miguel Alcon Pinto4ffe28d2015-08-19 14:29:02 +0000466 Set<Label> allowedLabels = new HashSet<>(rule.getTransitions(dependencyFilter).values());
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000467 allowedLabels.addAll(rule.getVisibility().getDependencyLabels());
Marian Loburfdd788e2015-03-25 09:36:28 +0000468 // We should add deps from aspects, otherwise they are going to be filtered out.
469 allowedLabels.addAll(rule.getAspectLabelsSuperset(dependencyFilter));
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000470 return allowedLabels;
471 }
472
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000473 private Collection<Target> filterFwdDeps(Target target, Collection<Target> rawFwdDeps)
474 throws InterruptedException {
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000475 if (!(target instanceof Rule)) {
Janak Ramakrishnan36858732015-06-17 16:45:47 +0000476 return rawFwdDeps;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000477 }
478 final Set<Label> allowedLabels = getAllowedDeps((Rule) target);
Janak Ramakrishnan36858732015-06-17 16:45:47 +0000479 return Collections2.filter(rawFwdDeps,
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000480 new Predicate<Target>() {
481 @Override
482 public boolean apply(Target target) {
483 return allowedLabels.contains(target.getLabel());
484 }
485 });
486 }
487
nharmatabf2e2d82017-06-21 23:12:51 +0200488 @Override
shreyax159a6112018-06-12 15:34:09 -0700489 public ThreadSafeMutableSet<Target> getFwdDeps(
490 Iterable<Target> targets, QueryExpressionContext<Target> context)
nharmatabf2e2d82017-06-21 23:12:51 +0200491 throws InterruptedException {
nharmata523b5752017-08-10 21:00:52 +0200492 Map<SkyKey, Target> targetsByKey = Maps.newHashMapWithExpectedSize(Iterables.size(targets));
nharmatabf2e2d82017-06-21 23:12:51 +0200493 for (Target target : targets) {
494 targetsByKey.put(TARGET_TO_SKY_KEY.apply(target), target);
495 }
496 Map<SkyKey, Collection<Target>> directDeps = targetifyValues(
497 graph.getDirectDeps(targetsByKey.keySet()));
498 if (targetsByKey.keySet().size() != directDeps.keySet().size()) {
499 Iterable<Label> missingTargets = Iterables.transform(
500 Sets.difference(targetsByKey.keySet(), directDeps.keySet()),
501 SKYKEY_TO_LABEL);
Janak Ramakrishnan3533ab52016-01-14 18:14:09 +0000502 eventHandler.handle(Event.warn("Targets were missing from graph: " + missingTargets));
503 }
nharmatabf2e2d82017-06-21 23:12:51 +0200504 ThreadSafeMutableSet<Target> result = createThreadSafeMutableSet();
505 for (Map.Entry<SkyKey, Collection<Target>> entry : directDeps.entrySet()) {
506 result.addAll(filterFwdDeps(targetsByKey.get(entry.getKey()), entry.getValue()));
Janak Ramakrishnan73dd2302015-06-16 17:04:25 +0000507 }
508 return result;
509 }
510
nharmata398e6dab2018-04-12 15:31:26 -0700511 /**
512 * Returns deps in the form of {@link SkyKey}s.
513 *
nharmatab6bf51d2018-07-27 13:49:45 -0700514 * <p>The implementation of this method does not filter out deps due to disallowed edges,
515 * therefore callers are responsible for doing the right thing themselves.
nharmata398e6dab2018-04-12 15:31:26 -0700516 */
nharmatab6bf51d2018-07-27 13:49:45 -0700517 public Multimap<SkyKey, SkyKey> getUnfilteredDirectDepsOfSkyKeys(Iterable<SkyKey> keys)
nharmata398e6dab2018-04-12 15:31:26 -0700518 throws InterruptedException {
nharmata398e6dab2018-04-12 15:31:26 -0700519 ImmutableMultimap.Builder<SkyKey, SkyKey> builder = ImmutableMultimap.builder();
520 graph.getDirectDeps(keys).forEach(builder::putAll);
521 return builder.build();
522 }
523
Janak Ramakrishnan36858732015-06-17 16:45:47 +0000524 @Override
shreyax159a6112018-06-12 15:34:09 -0700525 public Collection<Target> getReverseDeps(
526 Iterable<Target> targets, QueryExpressionContext<Target> context)
527 throws InterruptedException {
Nathan Harmatabe597992016-10-10 15:59:00 +0000528 return getReverseDepsOfTransitiveTraversalKeys(Iterables.transform(targets, TARGET_TO_SKY_KEY));
529 }
Miguel Alcon Pintob45e2622015-08-21 18:31:23 +0000530
janakrdc8b2e9a2017-08-18 22:52:37 +0200531 private Collection<Target> getReverseDepsOfTransitiveTraversalKeys(
Nathan Harmatabe597992016-10-10 15:59:00 +0000532 Iterable<SkyKey> transitiveTraversalKeys) throws InterruptedException {
533 Map<SkyKey, Collection<Target>> rawReverseDeps = getRawReverseDeps(transitiveTraversalKeys);
Googlerd1911622016-06-27 15:43:11 +0000534 return processRawReverseDeps(rawReverseDeps);
535 }
536
Googlerb3610d52016-10-24 19:18:36 +0000537 /** Targetify SkyKeys of reverse deps and filter out targets whose deps are not allowed. */
538 Collection<Target> filterRawReverseDepsOfTransitiveTraversalKeys(
Nathan Harmata41b54172016-11-10 18:54:09 +0000539 Map<SkyKey, ? extends Iterable<SkyKey>> rawReverseDeps,
540 Multimap<SkyKey, SkyKey> packageKeyToTargetKeyMap) throws InterruptedException {
541 return processRawReverseDeps(targetifyValues(rawReverseDeps, packageKeyToTargetKeyMap));
Googlerb3610d52016-10-24 19:18:36 +0000542 }
543
Nathan Harmatabe597992016-10-10 15:59:00 +0000544 private Collection<Target> processRawReverseDeps(Map<SkyKey, Collection<Target>> rawReverseDeps)
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000545 throws InterruptedException {
Googlerd1911622016-06-27 15:43:11 +0000546 Set<Target> result = CompactHashSet.create();
Eric Fellheimercfd61cf2016-08-10 21:36:02 +0000547 CompactHashSet<Target> visited =
548 CompactHashSet.createWithExpectedSize(totalSizeOfCollections(rawReverseDeps.values()));
Miguel Alcon Pintob45e2622015-08-21 18:31:23 +0000549
550 Set<Label> keys = CompactHashSet.create(Collections2.transform(rawReverseDeps.keySet(),
Nathan Harmatabe597992016-10-10 15:59:00 +0000551 SKYKEY_TO_LABEL));
Miguel Alcon Pintob45e2622015-08-21 18:31:23 +0000552 for (Collection<Target> parentCollection : rawReverseDeps.values()) {
553 for (Target parent : parentCollection) {
554 if (visited.add(parent)) {
Dmitry Lomov6073eb62016-01-21 21:26:32 +0000555 if (parent instanceof Rule && dependencyFilter != DependencyFilter.ALL_DEPS) {
Miguel Alcon Pintob45e2622015-08-21 18:31:23 +0000556 for (Label label : getAllowedDeps((Rule) parent)) {
557 if (keys.contains(label)) {
558 result.add(parent);
559 }
560 }
561 } else {
562 result.add(parent);
563 }
564 }
565 }
Janak Ramakrishnan73dd2302015-06-16 17:04:25 +0000566 }
567 return result;
568 }
569
Eric Fellheimercfd61cf2016-08-10 21:36:02 +0000570 private static <T> int totalSizeOfCollections(Iterable<Collection<T>> nestedCollections) {
571 int totalSize = 0;
572 for (Collection<T> collection : nestedCollections) {
573 totalSize += collection.size();
574 }
575 return totalSize;
576 }
577
Janak Ramakrishnan73dd2302015-06-16 17:04:25 +0000578 @Override
shreyax159a6112018-06-12 15:34:09 -0700579 public ThreadSafeMutableSet<Target> getTransitiveClosure(
580 ThreadSafeMutableSet<Target> targets, QueryExpressionContext<Target> context)
nharmatabf2e2d82017-06-21 23:12:51 +0200581 throws InterruptedException {
janakrdc8b2e9a2017-08-18 22:52:37 +0200582 return SkyQueryUtils.getTransitiveClosure(
shreyax159a6112018-06-12 15:34:09 -0700583 targets, targets1 -> getFwdDeps(targets1, context), createThreadSafeMutableSet());
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000584 }
585
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000586 @Override
shreyax159a6112018-06-12 15:34:09 -0700587 public ImmutableList<Target> getNodesOnPath(
588 Target from, Target to, QueryExpressionContext<Target> context) throws InterruptedException {
589 return SkyQueryUtils.getNodesOnPath(
590 from, to, targets -> getFwdDeps(targets, context), Target::getLabel);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000591 }
592
Googlerb39486c2019-01-03 08:58:16 -0800593 protected final <R> ListenableFuture<R> safeSubmit(Callable<R> callable) {
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000594 try {
595 return executor.submit(callable);
596 } catch (RejectedExecutionException e) {
597 return Futures.immediateCancelledFuture();
Nathan Harmataf37750a2016-09-07 14:58:14 +0000598 }
Miguel Alcon Pinto42984f32015-11-06 19:05:13 +0000599 }
600
nharmata2ef8de62019-04-23 18:30:55 -0700601 @SuppressWarnings("unchecked")
602 private <R> ListenableFuture<R> safeSubmitAsync(QueryTaskAsyncCallable<R> callable) {
Googlerdb6e13b2017-10-19 17:26:59 +0200603 try {
nharmata2ef8de62019-04-23 18:30:55 -0700604 return Futures.submitAsync(() -> (ListenableFuture<R>) callable.call(), executor);
Googlerdb6e13b2017-10-19 17:26:59 +0200605 } catch (RejectedExecutionException e) {
606 return Futures.immediateCancelledFuture();
607 }
608 }
609
Nathan Harmataf37750a2016-09-07 14:58:14 +0000610 @ThreadSafe
Janak Ramakrishnane933d5e2016-01-08 16:43:54 +0000611 @Override
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000612 public QueryTaskFuture<Void> eval(
613 final QueryExpression expr,
shreyax159a6112018-06-12 15:34:09 -0700614 final QueryExpressionContext<Target> context,
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000615 final Callback<Target> callback) {
616 // TODO(bazel-team): As in here, use concurrency for the async #eval of other QueryEnvironment
617 // implementations.
nharmata2ef8de62019-04-23 18:30:55 -0700618 return executeAsync(() -> expr.eval(SkyQueryEnvironment.this, context, callback));
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000619 }
620
621 @Override
nharmata2ef8de62019-04-23 18:30:55 -0700622 public <R> QueryTaskFuture<R> execute(QueryTaskCallable<R> callable) {
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000623 return QueryTaskFutureImpl.ofDelegate(safeSubmit(callable));
624 }
625
626 @Override
nharmata2ef8de62019-04-23 18:30:55 -0700627 public <R> QueryTaskFuture<R> executeAsync(QueryTaskAsyncCallable<R> callable) {
628 return QueryTaskFutureImpl.ofDelegate(safeSubmitAsync(callable));
629 }
630
631 @Override
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000632 public <T1, T2> QueryTaskFuture<T2> transformAsync(
633 QueryTaskFuture<T1> future,
634 final Function<T1, QueryTaskFuture<T2>> function) {
635 return QueryTaskFutureImpl.ofDelegate(
636 Futures.transformAsync(
637 (QueryTaskFutureImpl<T1>) future,
laurentlb3d2a68c2017-06-30 00:32:04 +0200638 input -> (QueryTaskFutureImpl<T2>) function.apply(input),
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000639 executor));
640 }
641
642 @Override
643 public <R> QueryTaskFuture<R> whenAllSucceedCall(
644 Iterable<? extends QueryTaskFuture<?>> futures, QueryTaskCallable<R> callable) {
645 return QueryTaskFutureImpl.ofDelegate(
646 Futures.whenAllSucceed(cast(futures)).call(callable, executor));
647 }
648
649 @ThreadSafe
650 @Override
nharmatabf2e2d82017-06-21 23:12:51 +0200651 public ThreadSafeMutableSet<Target> createThreadSafeMutableSet() {
652 return new ThreadSafeMutableKeyExtractorBackedSetImpl<>(
nharmatafac7c252018-09-12 15:31:23 -0700653 TargetKeyExtractor.INSTANCE, Target.class, queryEvaluationParallelismLevel);
nharmatabf2e2d82017-06-21 23:12:51 +0200654 }
655
656 @Override
657 public <V> MutableMap<Target, V> createMutableMap() {
shreyax6871cf02018-07-02 09:16:18 -0700658 return new MutableKeyExtractorBackedMapImpl<>(TargetKeyExtractor.INSTANCE);
nharmatabf2e2d82017-06-21 23:12:51 +0200659 }
660
661 @ThreadSafe
nharmatac49e8742018-09-27 11:27:41 -0700662 protected NonExceptionalUniquifier<Target> createUniquifierForOuterBatchStreamedCallback(
663 QueryExpression expr) {
664 return createUniquifier();
665 }
666
667 @ThreadSafe
nharmatabf2e2d82017-06-21 23:12:51 +0200668 @Override
nharmatac49e8742018-09-27 11:27:41 -0700669 public NonExceptionalUniquifier<Target> createUniquifier() {
nharmatab9f08022019-04-23 20:36:10 -0700670 return new UniquifierImpl<>(TargetKeyExtractor.INSTANCE, queryEvaluationParallelismLevel);
Nathan Harmata593dc522016-09-28 23:35:46 +0000671 }
672
673 @ThreadSafe
Nathan Harmatae9826b42017-03-07 18:05:21 +0000674 @Override
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000675 public MinDepthUniquifier<Target> createMinDepthUniquifier() {
nharmatafac7c252018-09-12 15:31:23 -0700676 return new MinDepthUniquifierImpl<>(
677 TargetKeyExtractor.INSTANCE, queryEvaluationParallelismLevel);
Nathan Harmatae9826b42017-03-07 18:05:21 +0000678 }
679
680 @ThreadSafe
nharmatafac7c252018-09-12 15:31:23 -0700681 public MinDepthUniquifier<SkyKey> createMinDepthSkyKeyUniquifier() {
682 return new MinDepthUniquifierImpl<>(
683 SkyKeyKeyExtractor.INSTANCE, queryEvaluationParallelismLevel);
nharmata398e6dab2018-04-12 15:31:26 -0700684 }
685
686 @ThreadSafe
shreyax2643d4b2018-05-25 11:12:11 -0700687 public Uniquifier<SkyKey> createSkyKeyUniquifier() {
nharmatab9f08022019-04-23 20:36:10 -0700688 return new UniquifierImpl<>(SkyKeyKeyExtractor.INSTANCE, queryEvaluationParallelismLevel);
Nathan Harmata593dc522016-09-28 23:35:46 +0000689 }
690
nharmatade0c5352017-07-25 17:39:09 +0200691 private ImmutableSet<PathFragment> getBlacklistedExcludes(TargetPatternKey targetPatternKey)
692 throws InterruptedException {
693 return targetPatternKey.getAllBlacklistedSubdirectoriesToExclude(blacklistPatternsSupplier);
Nathan Harmata5bd26b22016-11-14 19:55:50 +0000694 }
695
Googlerb3610d52016-10-24 19:18:36 +0000696 @ThreadSafe
Miguel Alcon Pinto42984f32015-11-06 19:05:13 +0000697 @Override
nharmata50f72492017-08-11 21:31:03 +0200698 public Collection<Target> getSiblingTargetsInPackage(Target target) {
699 return target.getPackage().getTargets().values();
700 }
701
702 @ThreadSafe
703 @Override
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000704 public QueryTaskFuture<Void> getTargetsMatchingPattern(
nharmatade0c5352017-07-25 17:39:09 +0200705 QueryExpression owner, String pattern, Callback<Target> callback) {
706 TargetPatternKey targetPatternKey;
Mark Schaller77612fd2016-06-21 21:04:45 +0000707 try {
ulfjacke83775d2019-05-14 08:58:46 -0700708 targetPatternKey = TargetPatternValue.key(pattern, FilteringPolicies.NO_FILTER, parserPrefix);
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000709 } catch (TargetParsingException tpe) {
710 try {
711 reportBuildFileError(owner, tpe.getMessage());
712 } catch (QueryException qe) {
713 return immediateFailedFuture(qe);
714 }
715 return immediateSuccessfulFuture(null);
nharmatade0c5352017-07-25 17:39:09 +0200716 }
717 return evalTargetPatternKey(owner, targetPatternKey, callback);
718 }
719
720 @ThreadSafe
721 public QueryTaskFuture<Void> evalTargetPatternKey(
722 QueryExpression owner, TargetPatternKey targetPatternKey, Callback<Target> callback) {
723 ImmutableSet<PathFragment> blacklistedSubdirectoriesToExclude;
724 try {
725 blacklistedSubdirectoriesToExclude = getBlacklistedExcludes(targetPatternKey);
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000726 } catch (InterruptedException ie) {
727 return immediateCancelledFuture();
Nathan Harmata5bd26b22016-11-14 19:55:50 +0000728 }
nharmatade0c5352017-07-25 17:39:09 +0200729 TargetPattern patternToEval = targetPatternKey.getParsedPattern();
730 ImmutableSet<PathFragment> additionalSubdirectoriesToExclude =
731 targetPatternKey.getExcludedSubdirectories();
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000732 AsyncFunction<TargetParsingException, Void> reportBuildFileErrorAsyncFunction =
laurentlb3d2a68c2017-06-30 00:32:04 +0200733 exn -> {
734 reportBuildFileError(owner, exn.getMessage());
735 return Futures.immediateFuture(null);
736 };
shreyax432b2532019-01-23 11:16:07 -0800737 Callback<Target> filteredCallback = callback;
738 if (!targetPatternKey.getPolicy().equals(NO_FILTER)) {
739 filteredCallback =
740 targets ->
741 callback.process(
742 Iterables.filter(
743 targets,
744 target ->
745 targetPatternKey.getPolicy().shouldRetain(target, /*explicit=*/ false)));
746 }
747 ListenableFuture<Void> evalFuture =
748 patternToEval.evalAsync(
749 resolver,
750 blacklistedSubdirectoriesToExclude,
751 additionalSubdirectoriesToExclude,
752 filteredCallback,
753 QueryException.class,
754 executor);
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000755 return QueryTaskFutureImpl.ofDelegate(
756 Futures.catchingAsync(
757 evalFuture,
758 TargetParsingException.class,
Googler73b7b2e2017-03-23 17:20:58 +0000759 reportBuildFileErrorAsyncFunction,
760 directExecutor()));
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000761 }
762
Nathan Harmataf37750a2016-09-07 14:58:14 +0000763 @ThreadSafe
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000764 @Override
nharmatabf2e2d82017-06-21 23:12:51 +0200765 public ThreadSafeMutableSet<Target> getBuildFiles(
shreyax159a6112018-06-12 15:34:09 -0700766 QueryExpression caller,
767 ThreadSafeMutableSet<Target> nodes,
768 boolean buildFiles,
769 boolean loads,
770 QueryExpressionContext<Target> context)
shreyaxdac4d512018-05-02 16:26:13 -0700771 throws QueryException, InterruptedException {
nharmatabf2e2d82017-06-21 23:12:51 +0200772 ThreadSafeMutableSet<Target> dependentFiles = createThreadSafeMutableSet();
773 Set<PackageIdentifier> seenPackages = new HashSet<>();
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000774 // Keep track of seen labels, to avoid adding a fake subinclude label that also exists as a
775 // real target.
776 Set<Label> seenLabels = new HashSet<>();
777
778 // Adds all the package definition files (BUILD files and build
779 // extensions) for package "pkg", to "buildfiles".
780 for (Target x : nodes) {
781 Package pkg = x.getPackage();
nharmatabf2e2d82017-06-21 23:12:51 +0200782 if (seenPackages.add(pkg.getPackageIdentifier())) {
Han-Wen Nienhuysc13c0022015-12-15 19:08:38 +0000783 if (buildFiles) {
784 addIfUniqueLabel(pkg.getBuildFile(), seenLabels, dependentFiles);
785 }
786
787 List<Label> extensions = new ArrayList<>();
Han-Wen Nienhuysc13c0022015-12-15 19:08:38 +0000788 if (loads) {
789 extensions.addAll(pkg.getSkylarkFileDependencies());
790 }
791
nharmata51cb8ff2018-03-26 10:40:50 -0700792 for (Label extension : extensions) {
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000793
nharmata51cb8ff2018-03-26 10:40:50 -0700794 Target loadTarget = getLoadTarget(extension, pkg);
795 addIfUniqueLabel(loadTarget, seenLabels, dependentFiles);
John Catere5fb5f02017-12-04 07:53:19 -0800796
nharmata51cb8ff2018-03-26 10:40:50 -0700797 // Also add the BUILD file of the extension.
Han-Wen Nienhuysc13c0022015-12-15 19:08:38 +0000798 if (buildFiles) {
shreyaxd7829b12018-04-05 09:30:46 -0700799 Label buildFileLabel = getBuildFileLabel(loadTarget.getLabel().getPackageIdentifier());
John Catere5fb5f02017-12-04 07:53:19 -0800800 addIfUniqueLabel(new FakeLoadTarget(buildFileLabel, pkg), seenLabels, dependentFiles);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000801 }
802 }
803 }
804 }
805 return dependentFiles;
806 }
807
shreyaxd7829b12018-04-05 09:30:46 -0700808 protected Label getBuildFileLabel(PackageIdentifier packageIdentifier) throws QueryException {
809 // TODO(bazel-team): Try avoid filesystem access here.
810 Path buildFileForLoad = null;
811 try {
812 buildFileForLoad = pkgPath.getPackageBuildFile(packageIdentifier);
813 } catch (NoSuchPackageException e) {
814 throw new QueryException(packageIdentifier + " does not exist in graph");
815 }
816 return Label.createUnvalidated(packageIdentifier, buildFileForLoad.getBaseName());
817 }
818
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000819 private static void addIfUniqueLabel(Target node, Set<Label> labels, Set<Target> nodes) {
820 if (labels.add(node.getLabel())) {
821 nodes.add(node);
822 }
823 }
824
shreyax76e4e422019-06-13 12:15:45 -0700825 protected int getVisitBatchSizeForParallelVisitation() {
826 return ParallelSkyQueryUtils.VISIT_BATCH_SIZE;
827 }
828
nharmata51cb8ff2018-03-26 10:40:50 -0700829 private Target getLoadTarget(Label label, Package pkg) {
juliexxia93a37632017-10-26 00:55:59 +0200830 return new FakeLoadTarget(label, pkg);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000831 }
832
nharmatab9f08022019-04-23 20:36:10 -0700833 int getQueryEvaluationParallelismLevel() {
834 return queryEvaluationParallelismLevel;
835 }
836
Nathan Harmataf37750a2016-09-07 14:58:14 +0000837 @ThreadSafe
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000838 @Override
839 public TargetAccessor<Target> getAccessor() {
840 return accessor;
841 }
842
Nathan Harmataf37750a2016-09-07 14:58:14 +0000843 @ThreadSafe
John Catere5fb5f02017-12-04 07:53:19 -0800844 private Package getPackage(PackageIdentifier packageIdentifier)
845 throws InterruptedException, QueryException, NoSuchPackageException {
846 SkyKey packageKey = PackageValue.key(packageIdentifier);
shreyaxde6e9a82019-02-19 10:53:17 -0800847 PackageValue packageValue = (PackageValue) graph.getValue(packageKey);
848 if (packageValue != null) {
849 Package pkg = packageValue.getPackage();
850 if (pkg.containsErrors()) {
John Catere5fb5f02017-12-04 07:53:19 -0800851 throw new BuildFileContainsErrorsException(packageIdentifier);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000852 }
shreyaxde6e9a82019-02-19 10:53:17 -0800853 return pkg;
854 } else {
855 NoSuchPackageException exception = (NoSuchPackageException) graph.getException(packageKey);
856 if (exception != null) {
857 throw exception;
858 }
859 if (graph.isCycle(packageKey)) {
860 throw new NoSuchPackageException(packageIdentifier, "Package depends on a cycle");
861 } else {
862 throw new QueryException(packageKey + " does not exist in graph");
863 }
864 }
John Catere5fb5f02017-12-04 07:53:19 -0800865 }
866
867 @ThreadSafe
868 @Override
869 public Target getTarget(Label label)
870 throws TargetNotFoundException, QueryException, InterruptedException {
871 try {
872 Package pkg = getPackage(label.getPackageIdentifier());
873 return pkg.getTarget(label.getName());
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000874 } catch (NoSuchThingException e) {
875 throw new TargetNotFoundException(e);
876 }
877 }
878
nharmata2ef8de62019-04-23 18:30:55 -0700879 @Override
880 public Map<Label, Target> getTargets(Iterable<Label> labels) throws InterruptedException {
881 Multimap<PackageIdentifier, Label> packageIdToLabelMap = ArrayListMultimap.create();
882 labels.forEach(label -> packageIdToLabelMap.put(label.getPackageIdentifier(), label));
883 Map<PackageIdentifier, Package> packageIdToPackageMap =
884 bulkGetPackages(packageIdToLabelMap.keySet());
885 ImmutableMap.Builder<Label, Target> resultBuilder = ImmutableMap.builder();
shreyax76e4e422019-06-13 12:15:45 -0700886 packageSemaphore.acquireAll(packageIdToLabelMap.keySet());
887 try {
888 for (PackageIdentifier pkgId : packageIdToLabelMap.keySet()) {
889 Package pkg = packageIdToPackageMap.get(pkgId);
890 if (pkg == null) {
nharmata2ef8de62019-04-23 18:30:55 -0700891 continue;
892 }
shreyax76e4e422019-06-13 12:15:45 -0700893 for (Label label : packageIdToLabelMap.get(pkgId)) {
894 Target target;
895 try {
896 target = pkg.getTarget(label.getName());
897 } catch (NoSuchTargetException e) {
898 continue;
899 }
900 resultBuilder.put(label, target);
901 }
nharmata2ef8de62019-04-23 18:30:55 -0700902 }
shreyax76e4e422019-06-13 12:15:45 -0700903 return resultBuilder.build();
904 } finally {
905 packageSemaphore.releaseAll(packageIdToLabelMap.keySet());
nharmata2ef8de62019-04-23 18:30:55 -0700906 }
nharmata2ef8de62019-04-23 18:30:55 -0700907 }
908
Nathan Harmataf37750a2016-09-07 14:58:14 +0000909 @ThreadSafe
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000910 public Map<PackageIdentifier, Package> bulkGetPackages(Iterable<PackageIdentifier> pkgIds)
911 throws InterruptedException {
Nathan Harmata64543472016-06-30 18:33:40 +0000912 Set<SkyKey> pkgKeys = ImmutableSet.copyOf(PackageValue.keys(pkgIds));
913 ImmutableMap.Builder<PackageIdentifier, Package> pkgResults = ImmutableMap.builder();
914 Map<SkyKey, SkyValue> packages = graph.getSuccessfulValues(pkgKeys);
915 for (Map.Entry<SkyKey, SkyValue> pkgEntry : packages.entrySet()) {
916 PackageIdentifier pkgId = (PackageIdentifier) pkgEntry.getKey().argument();
917 PackageValue pkgValue = (PackageValue) pkgEntry.getValue();
918 pkgResults.put(pkgId, Preconditions.checkNotNull(pkgValue.getPackage(), pkgId));
919 }
920 return pkgResults.build();
921 }
922
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000923 @Override
nharmatabf2e2d82017-06-21 23:12:51 +0200924 public void buildTransitiveClosure(
925 QueryExpression caller,
926 ThreadSafeMutableSet<Target> targets,
927 int maxDepth) throws QueryException, InterruptedException {
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000928 // Everything has already been loaded, so here we just check for errors so that we can
929 // pre-emptively throw/report if needed.
Mark Schallerc031a002015-10-21 18:17:32 +0000930 Iterable<SkyKey> transitiveTraversalKeys = makeTransitiveTraversalKeys(targets);
931 ImmutableList.Builder<String> errorMessagesBuilder = ImmutableList.builder();
932
933 // First, look for errors in the successfully evaluated TransitiveTraversalValues. They may
934 // have encountered errors that they were able to recover from.
jcater94b87022018-05-02 09:08:52 -0700935 Set<Map.Entry<SkyKey, SkyValue>> successfulEntries =
Mark Schallerc031a002015-10-21 18:17:32 +0000936 graph.getSuccessfulValues(transitiveTraversalKeys).entrySet();
jcater96d3c912018-04-20 04:04:06 -0700937 ImmutableSet.Builder<SkyKey> successfulKeysBuilder = ImmutableSet.builder();
jcater94b87022018-05-02 09:08:52 -0700938 for (Map.Entry<SkyKey, SkyValue> successfulEntry : successfulEntries) {
Mark Schallerc031a002015-10-21 18:17:32 +0000939 successfulKeysBuilder.add(successfulEntry.getKey());
940 TransitiveTraversalValue value = (TransitiveTraversalValue) successfulEntry.getValue();
janakrf091f9c2019-03-25 13:42:18 -0700941 String errorMessage = value.getErrorMessage();
942 if (errorMessage != null) {
943 errorMessagesBuilder.add(errorMessage);
Mark Schallerc031a002015-10-21 18:17:32 +0000944 }
945 }
946 ImmutableSet<SkyKey> successfulKeys = successfulKeysBuilder.build();
947
948 // Next, look for errors from the unsuccessfully evaluated TransitiveTraversal skyfunctions.
949 Iterable<SkyKey> unsuccessfulKeys =
950 Iterables.filter(transitiveTraversalKeys, Predicates.not(Predicates.in(successfulKeys)));
jcater94b87022018-05-02 09:08:52 -0700951 Set<Map.Entry<SkyKey, Exception>> errorEntries =
Mark Schallerc031a002015-10-21 18:17:32 +0000952 graph.getMissingAndExceptions(unsuccessfulKeys).entrySet();
953 for (Map.Entry<SkyKey, Exception> entry : errorEntries) {
Janak Ramakrishnanf6f0fcc2015-06-19 20:24:52 +0000954 if (entry.getValue() == null) {
Janak Ramakrishnan3533ab52016-01-14 18:14:09 +0000955 // Targets may be in the graph because they are not in the universe or depend on cycles.
956 eventHandler.handle(Event.warn(entry.getKey().argument() + " does not exist in graph"));
957 } else {
958 errorMessagesBuilder.add(entry.getValue().getMessage());
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000959 }
Mark Schallerc031a002015-10-21 18:17:32 +0000960 }
961
962 // Lastly, report all found errors.
963 ImmutableList<String> errorMessages = errorMessagesBuilder.build();
964 for (String errorMessage : errorMessages) {
965 reportBuildFileError(caller, errorMessage);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000966 }
967 }
968
Nathan Harmata3fae3662015-04-22 20:10:48 +0000969 @Override
Janak Ramakrishnanee6208b2016-01-07 20:17:41 +0000970 protected void preloadOrThrow(QueryExpression caller, Collection<String> patterns)
Janak Ramakrishnancbe26342015-08-17 18:57:57 +0000971 throws QueryException, TargetParsingException {
Mark Schaller77612fd2016-06-21 21:04:45 +0000972 // SkyQueryEnvironment directly evaluates target patterns in #getTarget and similar methods
Mark Schaller6cebed62016-06-27 18:05:39 +0000973 // using its graph, which is prepopulated using the universeScope (see #beforeEvaluateQuery),
974 // so no preloading of target patterns is necessary.
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000975 }
976
shreyax2643d4b2018-05-25 11:12:11 -0700977 public ExtendedEventHandler getEventHandler() {
978 return eventHandler;
979 }
nharmata398e6dab2018-04-12 15:31:26 -0700980
shreyax2643d4b2018-05-25 11:12:11 -0700981 public static final Predicate<SkyKey> IS_TTV =
982 SkyFunctionName.functionIs(Label.TRANSITIVE_TRAVERSAL);
983
984 public static final Function<SkyKey, Label> SKYKEY_TO_LABEL =
nharmata398e6dab2018-04-12 15:31:26 -0700985 skyKey -> IS_TTV.apply(skyKey) ? (Label) skyKey.argument() : null;
986
Nathan Harmata41b54172016-11-10 18:54:09 +0000987 static final Function<SkyKey, PackageIdentifier> PACKAGE_SKYKEY_TO_PACKAGE_IDENTIFIER =
laurentlb3d2a68c2017-06-30 00:32:04 +0200988 skyKey -> (PackageIdentifier) skyKey.argument();
Nathan Harmata41b54172016-11-10 18:54:09 +0000989
nharmata7c56dce2018-08-16 10:50:26 -0700990 public static Multimap<SkyKey, SkyKey> makePackageKeyToTargetKeyMap(Iterable<SkyKey> keys) {
Janak Ramakrishnane933d5e2016-01-08 16:43:54 +0000991 Multimap<SkyKey, SkyKey> packageKeyToTargetKeyMap = ArrayListMultimap.create();
992 for (SkyKey key : keys) {
993 Label label = SKYKEY_TO_LABEL.apply(key);
Janak Ramakrishnanb5a541a2015-06-19 20:55:01 +0000994 if (label == null) {
Janak Ramakrishnan36858732015-06-17 16:45:47 +0000995 continue;
996 }
Mark Schaller4b801f22016-06-21 22:26:12 +0000997 packageKeyToTargetKeyMap.put(PackageValue.key(label.getPackageIdentifier()), key);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000998 }
Nathan Harmata41b54172016-11-10 18:54:09 +0000999 return packageKeyToTargetKeyMap;
1000 }
1001
nharmata7c56dce2018-08-16 10:50:26 -07001002 public static Set<PackageIdentifier> getPkgIdsNeededForTargetification(
1003 Multimap<SkyKey, SkyKey> packageKeyToTargetKeyMap) {
1004 return packageKeyToTargetKeyMap
1005 .keySet()
1006 .stream()
1007 .map(SkyQueryEnvironment.PACKAGE_SKYKEY_TO_PACKAGE_IDENTIFIER)
1008 .collect(toImmutableSet());
Nathan Harmata41b54172016-11-10 18:54:09 +00001009 }
1010
1011 @ThreadSafe
nharmata7c56dce2018-08-16 10:50:26 -07001012 public Map<SkyKey, Target> getTargetKeyToTargetMapForPackageKeyToTargetKeyMap(
Nathan Harmata41b54172016-11-10 18:54:09 +00001013 Multimap<SkyKey, SkyKey> packageKeyToTargetKeyMap) throws InterruptedException {
nharmata641db6d2018-08-16 14:31:57 -07001014 ImmutableMap.Builder<SkyKey, Target> resultBuilder = ImmutableMap.builder();
1015 getTargetsForPackageKeyToTargetKeyMapHelper(packageKeyToTargetKeyMap, resultBuilder::put);
1016 return resultBuilder.build();
1017 }
1018
1019 @ThreadSafe
1020 public Multimap<PackageIdentifier, Target> getPkgIdToTargetMultimapForPackageKeyToTargetKeyMap(
1021 Multimap<SkyKey, SkyKey> packageKeyToTargetKeyMap) throws InterruptedException {
1022 Multimap<PackageIdentifier, Target> result = ArrayListMultimap.create();
1023 getTargetsForPackageKeyToTargetKeyMapHelper(
1024 packageKeyToTargetKeyMap,
1025 (k, t) -> result.put(t.getLabel().getPackageIdentifier(), t));
1026 return result;
1027 }
1028
1029 private void getTargetsForPackageKeyToTargetKeyMapHelper(
1030 Multimap<SkyKey, SkyKey> packageKeyToTargetKeyMap,
1031 BiConsumer<SkyKey, Target> targetKeyAndTargetConsumer) throws InterruptedException {
Googler2b503882016-11-28 21:54:43 +00001032 Set<SkyKey> processedTargets = new HashSet<>();
Miguel Alcon Pinto45820872015-09-11 19:57:47 +00001033 Map<SkyKey, SkyValue> packageMap = graph.getSuccessfulValues(packageKeyToTargetKeyMap.keySet());
Janak Ramakrishnan36858732015-06-17 16:45:47 +00001034 for (Map.Entry<SkyKey, SkyValue> entry : packageMap.entrySet()) {
nharmata641db6d2018-08-16 14:31:57 -07001035 Package pkg = ((PackageValue) entry.getValue()).getPackage();
Janak Ramakrishnane933d5e2016-01-08 16:43:54 +00001036 for (SkyKey targetKey : packageKeyToTargetKeyMap.get(entry.getKey())) {
Googler2b503882016-11-28 21:54:43 +00001037 if (processedTargets.add(targetKey)) {
1038 try {
nharmata641db6d2018-08-16 14:31:57 -07001039 Target target = pkg.getTarget(SKYKEY_TO_LABEL.apply(targetKey).getName());
1040 targetKeyAndTargetConsumer.accept(targetKey, target);
Googler2b503882016-11-28 21:54:43 +00001041 } catch (NoSuchTargetException e) {
1042 // Skip missing target.
1043 }
Janak Ramakrishnan36858732015-06-17 16:45:47 +00001044 }
1045 }
1046 }
Janak Ramakrishnan36858732015-06-17 16:45:47 +00001047 }
1048
Nathan Harmataf44211c2016-10-10 16:31:18 +00001049 static final Function<Target, SkyKey> TARGET_TO_SKY_KEY =
laurentlb3d2a68c2017-06-30 00:32:04 +02001050 target -> TransitiveTraversalValue.key(target.getLabel());
Janak Ramakrishnana40e7b72015-08-20 20:06:16 +00001051
Nathan Harmata39900802016-09-20 21:06:59 +00001052 /** A strict (i.e. non-lazy) variant of {@link #makeTransitiveTraversalKeys}. */
1053 public static Iterable<SkyKey> makeTransitiveTraversalKeysStrict(Iterable<Target> targets) {
1054 return ImmutableList.copyOf(makeTransitiveTraversalKeys(targets));
1055 }
1056
Mark Schallerc031a002015-10-21 18:17:32 +00001057 private static Iterable<SkyKey> makeTransitiveTraversalKeys(Iterable<Target> targets) {
Janak Ramakrishnana40e7b72015-08-20 20:06:16 +00001058 return Iterables.transform(targets, TARGET_TO_SKY_KEY);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +00001059 }
1060
Janak Ramakrishnane72d5222015-02-26 17:09:18 +00001061 @Override
1062 public Target getOrCreate(Target target) {
1063 return target;
1064 }
Janak Ramakrishnan643063d2015-06-25 16:21:49 +00001065
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001066 /**
Nathan Harmatac686fd62016-04-26 17:41:20 +00001067 * Returns package lookup keys for looking up the package root for which there may be a relevant
nharmatafa9b01e2017-11-27 08:16:38 -08001068 * (from the perspective of {@link #getRBuildFiles}) {@link FileStateValue} node in the graph for
Nathan Harmatac686fd62016-04-26 17:41:20 +00001069 * {@code originalFileFragment}, which is assumed to be a file path.
1070 *
nharmatafa9b01e2017-11-27 08:16:38 -08001071 * <p>This is a helper function for {@link #getFileStateKeysForFileFragments}.
Nathan Harmatac686fd62016-04-26 17:41:20 +00001072 */
1073 private static Iterable<SkyKey> getPkgLookupKeysForFile(PathFragment originalFileFragment,
1074 PathFragment currentPathFragment) {
1075 if (originalFileFragment.equals(currentPathFragment)
dannarkbe3cefc2018-12-13 11:52:45 -08001076 && originalFileFragment.equals(LabelConstants.WORKSPACE_FILE_NAME)) {
mschaller391c4cf2018-05-16 12:17:14 -07001077 // TODO(mschaller): this should not be checked at runtime. These are constants!
Nathan Harmatac686fd62016-04-26 17:41:20 +00001078 Preconditions.checkState(
dannarkbe3cefc2018-12-13 11:52:45 -08001079 LabelConstants.WORKSPACE_FILE_NAME
1080 .getParentDirectory()
1081 .equals(PathFragment.EMPTY_FRAGMENT),
1082 LabelConstants.WORKSPACE_FILE_NAME);
Nathan Harmatac686fd62016-04-26 17:41:20 +00001083 return ImmutableList.of(
dannarkbe3cefc2018-12-13 11:52:45 -08001084 PackageLookupValue.key(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER),
Nathan Harmatac686fd62016-04-26 17:41:20 +00001085 PackageLookupValue.key(PackageIdentifier.createInMainRepo(PathFragment.EMPTY_FRAGMENT)));
1086 }
1087 PathFragment parentPathFragment = currentPathFragment.getParentDirectory();
1088 return parentPathFragment == null
mschaller391c4cf2018-05-16 12:17:14 -07001089 ? ImmutableList.of()
1090 : ImmutableList.of(
1091 PackageLookupValue.key(PackageIdentifier.createInMainRepo(parentPathFragment)));
Nathan Harmatac686fd62016-04-26 17:41:20 +00001092 }
1093
1094 /**
nharmatafa9b01e2017-11-27 08:16:38 -08001095 * Returns FileStateValue keys for which there may be relevant (from the perspective of {@link
Googlerb39486c2019-01-03 08:58:16 -08001096 * #getRBuildFiles}) FileStateValues in the graph corresponding to the given {@code
1097 * pathFragments}, which are assumed to be file paths.
Nathan Harmatac686fd62016-04-26 17:41:20 +00001098 *
1099 * <p>To do this, we emulate the {@link ContainingPackageLookupFunction} logic: for each given
1100 * file path, we look for the nearest ancestor directory (starting with its parent directory), if
1101 * any, that has a package. The {@link PackageLookupValue} for this package tells us the package
nharmatafa9b01e2017-11-27 08:16:38 -08001102 * root that we should use for the {@link RootedPath} for the {@link FileStateValue} key.
Googlerd1911622016-06-27 15:43:11 +00001103 *
1104 * <p>Note that there may not be nodes in the graph corresponding to the returned SkyKeys.
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001105 */
Googlerb39486c2019-01-03 08:58:16 -08001106 protected Collection<SkyKey> getFileStateKeysForFileFragments(
1107 Iterable<PathFragment> pathFragments) throws InterruptedException {
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001108 Set<SkyKey> result = new HashSet<>();
1109 Multimap<PathFragment, PathFragment> currentToOriginal = ArrayListMultimap.create();
1110 for (PathFragment pathFragment : pathFragments) {
1111 currentToOriginal.put(pathFragment, pathFragment);
1112 }
1113 while (!currentToOriginal.isEmpty()) {
Nathan Harmatac686fd62016-04-26 17:41:20 +00001114 Multimap<SkyKey, PathFragment> packageLookupKeysToOriginal = ArrayListMultimap.create();
1115 Multimap<SkyKey, PathFragment> packageLookupKeysToCurrent = ArrayListMultimap.create();
jcater94b87022018-05-02 09:08:52 -07001116 for (Map.Entry<PathFragment, PathFragment> entry : currentToOriginal.entries()) {
Nathan Harmatac686fd62016-04-26 17:41:20 +00001117 PathFragment current = entry.getKey();
1118 PathFragment original = entry.getValue();
1119 for (SkyKey packageLookupKey : getPkgLookupKeysForFile(original, current)) {
1120 packageLookupKeysToOriginal.put(packageLookupKey, original);
1121 packageLookupKeysToCurrent.put(packageLookupKey, current);
1122 }
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001123 }
Nathan Harmatac686fd62016-04-26 17:41:20 +00001124 Map<SkyKey, SkyValue> lookupValues =
1125 graph.getSuccessfulValues(packageLookupKeysToOriginal.keySet());
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001126 for (Map.Entry<SkyKey, SkyValue> entry : lookupValues.entrySet()) {
Nathan Harmatac686fd62016-04-26 17:41:20 +00001127 SkyKey packageLookupKey = entry.getKey();
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001128 PackageLookupValue packageLookupValue = (PackageLookupValue) entry.getValue();
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001129 if (packageLookupValue.packageExists()) {
Nathan Harmatac686fd62016-04-26 17:41:20 +00001130 Collection<PathFragment> originalFiles =
1131 packageLookupKeysToOriginal.get(packageLookupKey);
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001132 Preconditions.checkState(!originalFiles.isEmpty(), entry);
1133 for (PathFragment fileName : originalFiles) {
nharmatafa9b01e2017-11-27 08:16:38 -08001134 result.add(FileStateValue.key(
1135 RootedPath.toRootedPath(packageLookupValue.getRoot(), fileName)));
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001136 }
Nathan Harmatac686fd62016-04-26 17:41:20 +00001137 for (PathFragment current : packageLookupKeysToCurrent.get(packageLookupKey)) {
1138 currentToOriginal.removeAll(current);
1139 }
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001140 }
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001141 }
1142 Multimap<PathFragment, PathFragment> newCurrentToOriginal = ArrayListMultimap.create();
1143 for (PathFragment pathFragment : currentToOriginal.keySet()) {
1144 PathFragment parent = pathFragment.getParentDirectory();
1145 if (parent != null) {
1146 newCurrentToOriginal.putAll(parent, currentToOriginal.get(pathFragment));
1147 }
1148 }
1149 currentToOriginal = newCurrentToOriginal;
1150 }
1151 return result;
1152 }
nharmata1bd4aaf2017-10-31 11:23:04 -04001153
shreyax76e4e422019-06-13 12:15:45 -07001154 protected Iterable<Target> getBuildFileTargetsForPackageKeys(
1155 Set<PackageIdentifier> pkgIds, QueryExpressionContext<Target> context)
nharmata1bd4aaf2017-10-31 11:23:04 -04001156 throws QueryException, InterruptedException {
nharmata1bd4aaf2017-10-31 11:23:04 -04001157 packageSemaphore.acquireAll(pkgIds);
1158 try {
shreyax76e4e422019-06-13 12:15:45 -07001159 return Iterables.transform(
1160 graph.getSuccessfulValues(PackageValue.keys(pkgIds)).values(),
1161 skyValue -> ((PackageValue) skyValue).getPackage().getBuildFile());
nharmata1bd4aaf2017-10-31 11:23:04 -04001162 } finally {
1163 packageSemaphore.releaseAll(pkgIds);
1164 }
1165 }
1166
mschaller096b7072018-05-01 14:49:22 -07001167 /**
nharmata20efb2a2018-09-28 12:54:12 -07001168 * Calculates the set of packages whose evaluation transitively depends on (e.g. via 'load'
1169 * statements) the contents of the specified paths. The emitted {@link Target}s are BUILD file
1170 * targets.
mschaller096b7072018-05-01 14:49:22 -07001171 */
Nathan Harmata593dc522016-09-28 23:35:46 +00001172 @ThreadSafe
mschaller096b7072018-05-01 14:49:22 -07001173 QueryTaskFuture<Void> getRBuildFiles(
nharmata20efb2a2018-09-28 12:54:12 -07001174 Collection<PathFragment> fileIdentifiers,
1175 QueryExpressionContext<Target> context,
1176 Callback<Target> callback) {
laurentlb3d2a68c2017-06-30 00:32:04 +02001177 return QueryTaskFutureImpl.ofDelegate(
1178 safeSubmit(
1179 () -> {
1180 ParallelSkyQueryUtils.getRBuildFilesParallel(
nharmata20efb2a2018-09-28 12:54:12 -07001181 SkyQueryEnvironment.this, fileIdentifiers, context, callback);
laurentlb3d2a68c2017-06-30 00:32:04 +02001182 return null;
1183 }));
Nathan Harmata593dc522016-09-28 23:35:46 +00001184 }
1185
Janak Ramakrishnan643063d2015-06-25 16:21:49 +00001186 @Override
1187 public Iterable<QueryFunction> getFunctions() {
1188 return ImmutableList.<QueryFunction>builder()
Janak Ramakrishnand802d5b2015-08-20 21:05:46 +00001189 .addAll(super.getFunctions())
1190 .add(new AllRdepsFunction())
1191 .add(new RBuildFilesFunction())
1192 .build();
Janak Ramakrishnan643063d2015-06-25 16:21:49 +00001193 }
Miguel Alcon Pinto47ea9482015-11-18 16:05:17 +00001194
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +00001195 private static class BlacklistSupplier
1196 implements InterruptibleSupplier<ImmutableSet<PathFragment>> {
Mark Schaller6cebed62016-06-27 18:05:39 +00001197 private final WalkableGraph graph;
1198
Googler5e65c982017-08-17 05:21:54 +02001199 private BlacklistSupplier(WalkableGraph graph) {
Mark Schaller6cebed62016-06-27 18:05:39 +00001200 this.graph = graph;
1201 }
1202
1203 @Override
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +00001204 public ImmutableSet<PathFragment> get() throws InterruptedException {
Mark Schaller6cebed62016-06-27 18:05:39 +00001205 return ((BlacklistedPackagePrefixesValue)
1206 graph.getValue(BlacklistedPackagePrefixesValue.key()))
1207 .getPatterns();
1208 }
1209 }
1210
Nathan Harmatae9826b42017-03-07 18:05:21 +00001211 private static class SkyKeyKeyExtractor implements KeyExtractor<SkyKey, SkyKey> {
1212 private static final SkyKeyKeyExtractor INSTANCE = new SkyKeyKeyExtractor();
1213
1214 private SkyKeyKeyExtractor() {
Nathan Harmata29bc3fb2016-09-09 16:11:12 +00001215 }
Mark Schaller20c75012016-06-21 22:51:14 +00001216
1217 @Override
Nathan Harmatae9826b42017-03-07 18:05:21 +00001218 public SkyKey extractKey(SkyKey element) {
Nathan Harmata29bc3fb2016-09-09 16:11:12 +00001219 return element;
Mark Schaller20c75012016-06-21 22:51:14 +00001220 }
1221 }
1222
Mark Schaller4d8baf82016-06-21 18:56:04 +00001223 /**
1224 * Wraps a {@link Callback} and guarantees that all calls to the original will have at least
1225 * {@code batchThreshold} {@link Target}s, except for the final such call.
1226 *
1227 * <p>Retains fewer than {@code batchThreshold} {@link Target}s at a time.
1228 *
1229 * <p>After this object's {@link #process} has been called for the last time, {#link
1230 * #processLastPending} must be called to "flush" any remaining {@link Target}s through to the
1231 * original.
Mark Schaller20c75012016-06-21 22:51:14 +00001232 *
Googlerb3610d52016-10-24 19:18:36 +00001233 * <p>This callback may be called from multiple threads concurrently. At most one thread will call
1234 * the wrapped {@code callback} concurrently.
Mark Schaller4d8baf82016-06-21 18:56:04 +00001235 */
Nathan Harmata7a5a2362017-03-08 22:42:01 +00001236 // TODO(nharmata): For queries with less than {@code batchThreshold} results, this batching
1237 // strategy probably hurts performance since we can only start formatting results once the entire
1238 // query is finished.
nharmata1bd4aaf2017-10-31 11:23:04 -04001239 // TODO(nharmata): This batching strategy is also potentially harmful from a memory perspective
1240 // since when the Targets being output are backed by Package instances, we're delaying GC of the
1241 // Package instances until the output batch size is met.
Nathan Harmata7a5a2362017-03-08 22:42:01 +00001242 private static class BatchStreamedCallback extends ThreadSafeOutputFormatterCallback<Target>
1243 implements Callback<Target> {
Miguel Alcon Pinto47ea9482015-11-18 16:05:17 +00001244
Nathan Harmata7a5a2362017-03-08 22:42:01 +00001245 // TODO(nharmata): Now that we know the wrapped callback is ThreadSafe, there's no correctness
1246 // concern that requires the prohibition of concurrent uses of the callback; the only concern is
1247 // memory. We should have a threshold for when to invoke the callback with a batch, and also a
Mark Schaller4f48f1b2017-03-10 20:38:43 +00001248 // separate, larger, bound on the number of targets being processed at the same time.
Nathan Harmata7a5a2362017-03-08 22:42:01 +00001249 private final ThreadSafeOutputFormatterCallback<Target> callback;
nharmatac49e8742018-09-27 11:27:41 -07001250 private final NonExceptionalUniquifier<Target> uniquifier;
Mark Schaller20c75012016-06-21 22:51:14 +00001251 private final Object pendingLock = new Object();
Miguel Alcon Pinto47ea9482015-11-18 16:05:17 +00001252 private List<Target> pending = new ArrayList<>();
1253 private int batchThreshold;
1254
Nathan Harmata7a5a2362017-03-08 22:42:01 +00001255 private BatchStreamedCallback(
1256 ThreadSafeOutputFormatterCallback<Target> callback,
nharmatafac7c252018-09-12 15:31:23 -07001257 int batchThreshold,
nharmatac49e8742018-09-27 11:27:41 -07001258 NonExceptionalUniquifier<Target> uniquifier) {
Miguel Alcon Pinto47ea9482015-11-18 16:05:17 +00001259 this.callback = callback;
1260 this.batchThreshold = batchThreshold;
nharmatafac7c252018-09-12 15:31:23 -07001261 this.uniquifier = uniquifier;
Miguel Alcon Pinto47ea9482015-11-18 16:05:17 +00001262 }
1263
1264 @Override
Nathan Harmata5bb9cc92016-09-30 21:28:30 +00001265 public void start() throws IOException {
1266 callback.start();
1267 }
1268
1269 @Override
1270 public void processOutput(Iterable<Target> partialResult)
1271 throws IOException, InterruptedException {
Mark Schaller20c75012016-06-21 22:51:14 +00001272 ImmutableList<Target> uniquifiedTargets = uniquifier.unique(partialResult);
nharmata2e8d43d2019-01-15 10:21:14 -08001273 Iterable<Target> toProcess = null;
Mark Schaller20c75012016-06-21 22:51:14 +00001274 synchronized (pendingLock) {
1275 Preconditions.checkNotNull(pending, "Reuse of the callback is not allowed");
1276 pending.addAll(uniquifiedTargets);
1277 if (pending.size() >= batchThreshold) {
nharmata2e8d43d2019-01-15 10:21:14 -08001278 toProcess = pending;
Mark Schaller20c75012016-06-21 22:51:14 +00001279 pending = new ArrayList<>();
1280 }
Miguel Alcon Pinto47ea9482015-11-18 16:05:17 +00001281 }
nharmata2e8d43d2019-01-15 10:21:14 -08001282 if (toProcess != null) {
1283 callback.processOutput(toProcess);
1284 }
Miguel Alcon Pinto47ea9482015-11-18 16:05:17 +00001285 }
1286
Nathan Harmata5bb9cc92016-09-30 21:28:30 +00001287 @Override
Nathan Harmataa2565aa2016-11-17 22:37:33 +00001288 public void close(boolean failFast) throws IOException, InterruptedException {
1289 if (!failFast) {
1290 processLastPending();
1291 }
1292 callback.close(failFast);
Nathan Harmata5bb9cc92016-09-30 21:28:30 +00001293 }
1294
1295 private void processLastPending() throws IOException, InterruptedException {
Mark Schaller20c75012016-06-21 22:51:14 +00001296 synchronized (pendingLock) {
1297 if (!pending.isEmpty()) {
Nathan Harmata5bb9cc92016-09-30 21:28:30 +00001298 callback.processOutput(pending);
Mark Schaller20c75012016-06-21 22:51:14 +00001299 pending = null;
1300 }
Miguel Alcon Pinto47ea9482015-11-18 16:05:17 +00001301 }
1302 }
1303 }
Googlerd1911622016-06-27 15:43:11 +00001304
Nathan Harmataf37750a2016-09-07 14:58:14 +00001305 @ThreadSafe
Googlerd1911622016-06-27 15:43:11 +00001306 @Override
Nathan Harmata7a5a2362017-03-08 22:42:01 +00001307 public QueryTaskFuture<Void> getAllRdepsUnboundedParallel(
Nathan Harmata593dc522016-09-28 23:35:46 +00001308 QueryExpression expression,
shreyax159a6112018-06-12 15:34:09 -07001309 QueryExpressionContext<Target> context,
Nathan Harmata7a5a2362017-03-08 22:42:01 +00001310 Callback<Target> callback) {
shreyax76e4e422019-06-13 12:15:45 -07001311 return ParallelSkyQueryUtils.getAllRdepsUnboundedParallel(this, expression, context, callback);
Nathan Harmata593dc522016-09-28 23:35:46 +00001312 }
1313
nharmata398e6dab2018-04-12 15:31:26 -07001314 @ThreadSafe
Googler96f95cc2017-09-02 00:54:18 +02001315 @Override
nharmata398e6dab2018-04-12 15:31:26 -07001316 public QueryTaskFuture<Void> getAllRdepsBoundedParallel(
Googler96f95cc2017-09-02 00:54:18 +02001317 QueryExpression expression,
nharmata398e6dab2018-04-12 15:31:26 -07001318 int depth,
shreyax159a6112018-06-12 15:34:09 -07001319 QueryExpressionContext<Target> context,
Googler96f95cc2017-09-02 00:54:18 +02001320 Callback<Target> callback) {
nharmata398e6dab2018-04-12 15:31:26 -07001321 return ParallelSkyQueryUtils.getAllRdepsBoundedParallel(
shreyax76e4e422019-06-13 12:15:45 -07001322 this, expression, depth, context, callback);
nharmata398e6dab2018-04-12 15:31:26 -07001323 }
1324
nharmatab6bf51d2018-07-27 13:49:45 -07001325 protected QueryTaskFuture<Predicate<SkyKey>> getUnfilteredUniverseDTCSkyKeyPredicateFuture(
shreyax159a6112018-06-12 15:34:09 -07001326 QueryExpression universe, QueryExpressionContext<Target> context) {
nharmata398e6dab2018-04-12 15:31:26 -07001327 return ParallelSkyQueryUtils.getDTCSkyKeyPredicateFuture(
1328 this,
1329 universe,
1330 context,
1331 BATCH_CALLBACK_SIZE,
nharmatafac7c252018-09-12 15:31:23 -07001332 queryEvaluationParallelismLevel);
Googler96f95cc2017-09-02 00:54:18 +02001333 }
1334
Nathan Harmata593dc522016-09-28 23:35:46 +00001335 @ThreadSafe
1336 @Override
nharmata398e6dab2018-04-12 15:31:26 -07001337 public QueryTaskFuture<Void> getRdepsUnboundedParallel(
Googlerd1911622016-06-27 15:43:11 +00001338 QueryExpression expression,
nharmata398e6dab2018-04-12 15:31:26 -07001339 QueryExpression universe,
shreyax159a6112018-06-12 15:34:09 -07001340 QueryExpressionContext<Target> context,
nharmata398e6dab2018-04-12 15:31:26 -07001341 Callback<Target> callback) {
1342 return transformAsync(
nharmata10911f12018-08-08 07:58:21 -07001343 // Even if we need to do edge filtering, it's fine to construct the rdeps universe via an
1344 // unfiltered DTC visitation; the subsequent rdeps visitation will perform the edge
1345 // filtering.
nharmatab6bf51d2018-07-27 13:49:45 -07001346 getUnfilteredUniverseDTCSkyKeyPredicateFuture(universe, context),
shreyax76e4e422019-06-13 12:15:45 -07001347 unfilteredUniversePredicate ->
1348 ParallelSkyQueryUtils.getRdepsInUniverseUnboundedParallel(
1349 this, expression, unfilteredUniversePredicate, context, callback));
Googlerd1911622016-06-27 15:43:11 +00001350 }
1351
shreyax2643d4b2018-05-25 11:12:11 -07001352 @Override
1353 public QueryTaskFuture<Void> getDepsUnboundedParallel(
1354 QueryExpression expression,
shreyax159a6112018-06-12 15:34:09 -07001355 QueryExpressionContext<Target> context,
nharmataf59022b2018-07-30 10:37:48 -07001356 Callback<Target> callback) {
shreyax2643d4b2018-05-25 11:12:11 -07001357 return ParallelSkyQueryUtils.getDepsUnboundedParallel(
1358 SkyQueryEnvironment.this,
1359 expression,
1360 context,
1361 callback,
nharmataf59022b2018-07-30 10:37:48 -07001362 /*depsNeedFiltering=*/ !dependencyFilter.equals(DependencyFilter.ALL_DEPS));
shreyax2643d4b2018-05-25 11:12:11 -07001363 }
1364
nharmata398e6dab2018-04-12 15:31:26 -07001365 @ThreadSafe
1366 @Override
1367 public QueryTaskFuture<Void> getRdepsBoundedParallel(
Googlerd1911622016-06-27 15:43:11 +00001368 QueryExpression expression,
Nathan Harmatabc47f402016-07-13 16:22:30 +00001369 int depth,
nharmata398e6dab2018-04-12 15:31:26 -07001370 QueryExpression universe,
shreyax159a6112018-06-12 15:34:09 -07001371 QueryExpressionContext<Target> context,
nharmata398e6dab2018-04-12 15:31:26 -07001372 Callback<Target> callback) {
1373 return transformAsync(
nharmata10911f12018-08-08 07:58:21 -07001374 // Even if we need to do edge filtering, it's fine to construct the rdeps universe via an
1375 // unfiltered DTC visitation; the subsequent rdeps visitation will perform the edge
1376 // filtering.
nharmatab6bf51d2018-07-27 13:49:45 -07001377 getUnfilteredUniverseDTCSkyKeyPredicateFuture(universe, context),
shreyax76e4e422019-06-13 12:15:45 -07001378 universePredicate ->
1379 ParallelSkyQueryUtils.getRdepsInUniverseBoundedParallel(
1380 this, expression, depth, universePredicate, context, callback));
Googlerd1911622016-06-27 15:43:11 +00001381 }
Mark Schaller4f48f1b2017-03-10 20:38:43 +00001382
1383 /**
1384 * Query evaluation behavior is specified with respect to errors it emits. (Or at least it should
1385 * be. Tools rely on it.) Notably, errors that occur during evaluation of a query's universe must
1386 * not be emitted during query command evaluation. Consider the case of a simple single target
1387 * query when {@code //...} is the universe: errors in far flung parts of the workspace should not
1388 * be emitted when that query command is evaluated.
1389 *
1390 * <p>Non-error message events are not specified. For instance, it's useful (and expected by some
1391 * unit tests that should know better) for query commands to emit {@link EventKind#PROGRESS}
1392 * events during package loading.
1393 *
1394 * <p>Therefore, this class is used to forward only non-{@link EventKind#ERROR} events during
1395 * universe loading to the {@link SkyQueryEnvironment}'s {@link ExtendedEventHandler}.
1396 */
1397 protected static class ErrorBlockingForwardingEventHandler extends DelegatingEventHandler {
1398
1399 public ErrorBlockingForwardingEventHandler(ExtendedEventHandler delegate) {
1400 super(delegate);
1401 }
1402
1403 @Override
1404 public void handle(Event e) {
1405 if (!e.getKind().equals(EventKind.ERROR)) {
1406 super.handle(e);
1407 }
1408 }
1409 }
Janak Ramakrishnane72d5222015-02-26 17:09:18 +00001410}