// Copyright 2016 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.devtools.build.lib.query2; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.compacthashset.CompactHashSet; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.query2.engine.Callback; import com.google.devtools.build.lib.query2.engine.QueryException; import com.google.devtools.build.lib.query2.engine.Uniquifier; import com.google.devtools.build.lib.skyframe.PackageValue; import com.google.devtools.build.lib.skyframe.SkyFunctions; import com.google.devtools.build.skyframe.SkyKey; import java.util.Collection; import java.util.Set; /** A helper class that computes 'rbuildfiles()' via BFS. */ class RBuildFilesVisitor extends AbstractSkyKeyParallelVisitor { // Each target in the full output of 'rbuildfiles' corresponds to BUILD file InputFile of a // unique package. So the processResultsBatchSize we choose to pass to the ParallelVisitor ctor // influences how many packages each leaf task doing processPartialResults will have to // deal with at once. A value of 100 was chosen experimentally. private static final int PROCESS_RESULTS_BATCH_SIZE = 100; private static final SkyKey EXTERNAL_PACKAGE_KEY = PackageValue.key(Label.EXTERNAL_PACKAGE_IDENTIFIER); private final SkyQueryEnvironment env; RBuildFilesVisitor( SkyQueryEnvironment env, Uniquifier uniquifier, Callback callback) { super(uniquifier, callback, ParallelSkyQueryUtils.VISIT_BATCH_SIZE, PROCESS_RESULTS_BATCH_SIZE); this.env = env; } @Override protected Visit getVisitResult(Iterable values) throws InterruptedException { Collection> reverseDeps = env.graph.getReverseDeps(values).values(); Set keysToUseForResult = CompactHashSet.create(); Set keysToVisitNext = CompactHashSet.create(); for (SkyKey rdep : Iterables.concat(reverseDeps)) { if (rdep.functionName().equals(SkyFunctions.PACKAGE)) { keysToUseForResult.add(rdep); // Every package has a dep on the external package, so we need to include those edges too. if (rdep.equals(EXTERNAL_PACKAGE_KEY)) { keysToVisitNext.add(rdep); } } else if (!rdep.functionName().equals(SkyFunctions.PACKAGE_LOOKUP) && !rdep.functionName().equals(SkyFunctions.GLOB)) { // Packages may depend on the existence of subpackages, but these edges aren't relevant to // rbuildfiles. They may also depend on files transitively through globs, but these cannot // be included in load statements and so we don't traverse through these either. keysToVisitNext.add(rdep); } } return new Visit(keysToUseForResult, keysToVisitNext); } @Override protected void processPartialResults( Iterable keysToUseForResult, Callback callback) throws QueryException, InterruptedException { env.getBuildFileTargetsForPackageKeysAndProcessViaCallback(keysToUseForResult, callback); } @Override protected Iterable preprocessInitialVisit(Iterable keys) { return keys; } }