Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2015 The Bazel Authors. All rights reserved. |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 2 | // |
| 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. |
| 14 | package com.google.devtools.build.lib.skyframe; |
| 15 | |
Googler | 3d37b4c | 2017-04-25 04:19:01 +0200 | [diff] [blame] | 16 | import static com.google.common.util.concurrent.MoreExecutors.directExecutor; |
Eric Fellheimer | 8c40daa | 2016-01-11 17:31:26 +0000 | [diff] [blame] | 17 | import static com.google.devtools.build.lib.pkgcache.FilteringPolicies.NO_FILTER; |
| 18 | |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 19 | import com.google.common.base.Function; |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 20 | import com.google.common.base.Throwables; |
Mark Schaller | d9d390a | 2016-06-21 22:01:28 +0000 | [diff] [blame] | 21 | import com.google.common.collect.ImmutableList; |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 22 | import com.google.common.collect.ImmutableMap; |
Mark Schaller | f6e32d6 | 2015-05-19 20:27:43 +0000 | [diff] [blame] | 23 | import com.google.common.collect.ImmutableSet; |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 24 | import com.google.common.collect.Iterables; |
Eric Fellheimer | fb60143 | 2016-03-07 21:14:44 +0000 | [diff] [blame] | 25 | import com.google.common.collect.Sets; |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 26 | import com.google.common.util.concurrent.Futures; |
| 27 | import com.google.common.util.concurrent.ListenableFuture; |
| 28 | import com.google.common.util.concurrent.ListeningExecutorService; |
Nathan Harmata | 5bd26b2 | 2016-11-14 19:55:50 +0000 | [diff] [blame] | 29 | import com.google.common.util.concurrent.MoreExecutors; |
Lukacs Berki | 6e91eb9 | 2015-09-21 09:12:37 +0000 | [diff] [blame] | 30 | import com.google.devtools.build.lib.cmdline.Label; |
Kristina Chodorow | 73fa203 | 2015-08-28 17:57:46 +0000 | [diff] [blame] | 31 | import com.google.devtools.build.lib.cmdline.PackageIdentifier; |
Kristina Chodorow | ec5c07a | 2016-01-25 17:12:29 +0000 | [diff] [blame] | 32 | import com.google.devtools.build.lib.cmdline.RepositoryName; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 33 | import com.google.devtools.build.lib.cmdline.ResolvedTargets; |
| 34 | import com.google.devtools.build.lib.cmdline.TargetParsingException; |
| 35 | import com.google.devtools.build.lib.cmdline.TargetPatternResolver; |
Nathan Harmata | 41b5417 | 2016-11-10 18:54:09 +0000 | [diff] [blame] | 36 | import com.google.devtools.build.lib.concurrent.MultisetSemaphore; |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 37 | import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 38 | import com.google.devtools.build.lib.events.Event; |
Klaus Aehlig | 777b30d | 2017-02-24 16:30:15 +0000 | [diff] [blame] | 39 | import com.google.devtools.build.lib.events.ExtendedEventHandler; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 40 | import com.google.devtools.build.lib.packages.NoSuchPackageException; |
| 41 | import com.google.devtools.build.lib.packages.NoSuchThingException; |
| 42 | import com.google.devtools.build.lib.packages.Package; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 43 | import com.google.devtools.build.lib.packages.Target; |
| 44 | import com.google.devtools.build.lib.pkgcache.FilteringPolicies; |
| 45 | import com.google.devtools.build.lib.pkgcache.FilteringPolicy; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 46 | import com.google.devtools.build.lib.pkgcache.RecursivePackageProvider; |
| 47 | import com.google.devtools.build.lib.pkgcache.TargetPatternResolverUtil; |
Janak Ramakrishnan | 5b5f22a | 2016-01-07 17:07:29 +0000 | [diff] [blame] | 48 | import com.google.devtools.build.lib.util.BatchCallback; |
Googler | 77ba65e | 2017-06-26 19:55:09 +0200 | [diff] [blame] | 49 | import com.google.devtools.build.lib.util.Preconditions; |
Nathan Harmata | 5bd26b2 | 2016-11-14 19:55:50 +0000 | [diff] [blame] | 50 | import com.google.devtools.build.lib.util.ThreadSafeBatchCallback; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 51 | import com.google.devtools.build.lib.vfs.PathFragment; |
Janak Ramakrishnan | 5b5f22a | 2016-01-07 17:07:29 +0000 | [diff] [blame] | 52 | import java.util.ArrayList; |
| 53 | import java.util.List; |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 54 | import java.util.Map; |
Nathan Harmata | 2e2b459 | 2016-09-21 17:17:33 +0000 | [diff] [blame] | 55 | import java.util.concurrent.Callable; |
Mark Schaller | d9d390a | 2016-06-21 22:01:28 +0000 | [diff] [blame] | 56 | import java.util.concurrent.ExecutionException; |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 57 | import java.util.concurrent.atomic.AtomicBoolean; |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 58 | |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 59 | /** |
| 60 | * A {@link TargetPatternResolver} backed by a {@link RecursivePackageProvider}. |
| 61 | */ |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 62 | @ThreadCompatible |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 63 | public class RecursivePackageProviderBackedTargetPatternResolver |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 64 | extends TargetPatternResolver<Target> { |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 65 | |
Janak Ramakrishnan | 5b5f22a | 2016-01-07 17:07:29 +0000 | [diff] [blame] | 66 | // TODO(janakr): Move this to a more generic place and unify with SkyQueryEnvironment's value? |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 67 | private static final int MAX_PACKAGES_BULK_GET = 1000; |
Janak Ramakrishnan | 5b5f22a | 2016-01-07 17:07:29 +0000 | [diff] [blame] | 68 | |
Googler | 77ba65e | 2017-06-26 19:55:09 +0200 | [diff] [blame] | 69 | protected final FilteringPolicy policy; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 70 | private final RecursivePackageProvider recursivePackageProvider; |
Klaus Aehlig | 777b30d | 2017-02-24 16:30:15 +0000 | [diff] [blame] | 71 | private final ExtendedEventHandler eventHandler; |
Nathan Harmata | 41b5417 | 2016-11-10 18:54:09 +0000 | [diff] [blame] | 72 | private final MultisetSemaphore<PackageIdentifier> packageSemaphore; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 73 | |
| 74 | public RecursivePackageProviderBackedTargetPatternResolver( |
Mark Schaller | 8ca9131 | 2015-06-22 22:04:02 +0000 | [diff] [blame] | 75 | RecursivePackageProvider recursivePackageProvider, |
Klaus Aehlig | 777b30d | 2017-02-24 16:30:15 +0000 | [diff] [blame] | 76 | ExtendedEventHandler eventHandler, |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 77 | FilteringPolicy policy, |
Nathan Harmata | 41b5417 | 2016-11-10 18:54:09 +0000 | [diff] [blame] | 78 | MultisetSemaphore<PackageIdentifier> packageSemaphore) { |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 79 | this.recursivePackageProvider = recursivePackageProvider; |
| 80 | this.eventHandler = eventHandler; |
| 81 | this.policy = policy; |
Nathan Harmata | 41b5417 | 2016-11-10 18:54:09 +0000 | [diff] [blame] | 82 | this.packageSemaphore = packageSemaphore; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | @Override |
| 86 | public void warn(String msg) { |
| 87 | eventHandler.handle(Event.warn(msg)); |
| 88 | } |
| 89 | |
| 90 | /** |
| 91 | * Gets a {@link Package} from the {@link RecursivePackageProvider}. May return a {@link Package} |
| 92 | * that has errors. |
| 93 | */ |
| 94 | private Package getPackage(PackageIdentifier pkgIdentifier) |
| 95 | throws NoSuchPackageException, InterruptedException { |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 96 | return recursivePackageProvider.getPackage(eventHandler, pkgIdentifier); |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 97 | } |
| 98 | |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 99 | private Map<PackageIdentifier, Package> bulkGetPackages(Iterable<PackageIdentifier> pkgIds) |
| 100 | throws NoSuchPackageException, InterruptedException { |
Mark Schaller | fb2d38b | 2017-03-10 23:01:45 +0000 | [diff] [blame] | 101 | return recursivePackageProvider.bulkGetPackages(pkgIds); |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 102 | } |
| 103 | |
Googler | 77ba65e | 2017-06-26 19:55:09 +0200 | [diff] [blame] | 104 | /** Optionally convert a {@link Target} before including it in returns. */ |
| 105 | protected Target maybeConvertTargetBeforeReturn(Target target) { |
| 106 | return target; |
| 107 | } |
| 108 | |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 109 | @Override |
Lukacs Berki | 960dc27 | 2015-09-24 07:48:36 +0000 | [diff] [blame] | 110 | public Target getTargetOrNull(Label label) throws InterruptedException { |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 111 | try { |
Lukacs Berki | 10e3b2b | 2015-09-22 07:58:20 +0000 | [diff] [blame] | 112 | if (!isPackage(label.getPackageIdentifier())) { |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 113 | return null; |
| 114 | } |
Googler | 77ba65e | 2017-06-26 19:55:09 +0200 | [diff] [blame] | 115 | return maybeConvertTargetBeforeReturn( |
| 116 | recursivePackageProvider.getTarget(eventHandler, label)); |
Lukacs Berki | 960dc27 | 2015-09-24 07:48:36 +0000 | [diff] [blame] | 117 | } catch (NoSuchThingException e) { |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 118 | return null; |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | @Override |
Lukacs Berki | 960dc27 | 2015-09-24 07:48:36 +0000 | [diff] [blame] | 123 | public ResolvedTargets<Target> getExplicitTarget(Label label) |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 124 | throws TargetParsingException, InterruptedException { |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 125 | try { |
| 126 | Target target = recursivePackageProvider.getTarget(eventHandler, label); |
| 127 | return policy.shouldRetain(target, true) |
Googler | 77ba65e | 2017-06-26 19:55:09 +0200 | [diff] [blame] | 128 | ? ResolvedTargets.of(maybeConvertTargetBeforeReturn(target)) |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 129 | : ResolvedTargets.<Target>empty(); |
| 130 | } catch (NoSuchThingException e) { |
| 131 | throw new TargetParsingException(e.getMessage(), e); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | @Override |
Lukacs Berki | 10e3b2b | 2015-09-22 07:58:20 +0000 | [diff] [blame] | 136 | public ResolvedTargets<Target> getTargetsInPackage( |
| 137 | String originalPattern, PackageIdentifier packageIdentifier, boolean rulesOnly) |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 138 | throws TargetParsingException, InterruptedException { |
| 139 | FilteringPolicy actualPolicy = rulesOnly |
| 140 | ? FilteringPolicies.and(FilteringPolicies.RULES_ONLY, policy) |
| 141 | : policy; |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 142 | try { |
Lukacs Berki | 10e3b2b | 2015-09-22 07:58:20 +0000 | [diff] [blame] | 143 | Package pkg = getPackage(packageIdentifier); |
Googler | 77ba65e | 2017-06-26 19:55:09 +0200 | [diff] [blame] | 144 | return TargetPatternResolverUtil.resolvePackageTargets( |
| 145 | pkg, |
| 146 | actualPolicy, |
| 147 | new Function<Target, Target>() { |
| 148 | @Override |
| 149 | public Target apply(Target target) { |
| 150 | return maybeConvertTargetBeforeReturn(Preconditions.checkNotNull(target)); |
| 151 | } |
| 152 | }); |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 153 | } catch (NoSuchThingException e) { |
| 154 | String message = TargetPatternResolverUtil.getParsingErrorMessage( |
Lukacs Berki | 10e3b2b | 2015-09-22 07:58:20 +0000 | [diff] [blame] | 155 | e.getMessage(), originalPattern); |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 156 | throw new TargetParsingException(message, e); |
| 157 | } |
| 158 | } |
| 159 | |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 160 | private Map<PackageIdentifier, ResolvedTargets<Target>> bulkGetTargetsInPackage( |
| 161 | String originalPattern, |
| 162 | Iterable<PackageIdentifier> pkgIds, FilteringPolicy policy) |
Nathan Harmata | 2e2b459 | 2016-09-21 17:17:33 +0000 | [diff] [blame] | 163 | throws InterruptedException { |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 164 | try { |
| 165 | Map<PackageIdentifier, Package> pkgs = bulkGetPackages(pkgIds); |
Eric Fellheimer | fb60143 | 2016-03-07 21:14:44 +0000 | [diff] [blame] | 166 | if (pkgs.size() != Iterables.size(pkgIds)) { |
| 167 | throw new IllegalStateException("Bulk package retrieval missing results: " |
| 168 | + Sets.difference(ImmutableSet.copyOf(pkgIds), pkgs.keySet())); |
| 169 | } |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 170 | ImmutableMap.Builder<PackageIdentifier, ResolvedTargets<Target>> result = |
| 171 | ImmutableMap.builder(); |
| 172 | for (PackageIdentifier pkgId : pkgIds) { |
| 173 | Package pkg = pkgs.get(pkgId); |
| 174 | result.put(pkgId, TargetPatternResolverUtil.resolvePackageTargets(pkg, policy)); |
| 175 | } |
| 176 | return result.build(); |
| 177 | } catch (NoSuchThingException e) { |
| 178 | String message = TargetPatternResolverUtil.getParsingErrorMessage( |
| 179 | e.getMessage(), originalPattern); |
Eric Fellheimer | fb60143 | 2016-03-07 21:14:44 +0000 | [diff] [blame] | 180 | throw new IllegalStateException( |
| 181 | "Mismatch: Expected given pkgIds to correspond to valid Packages. " + message, e); |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 182 | } |
| 183 | } |
| 184 | |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 185 | @Override |
Janak Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 186 | public boolean isPackage(PackageIdentifier packageIdentifier) throws InterruptedException { |
Lukacs Berki | 10e3b2b | 2015-09-22 07:58:20 +0000 | [diff] [blame] | 187 | return recursivePackageProvider.isPackage(eventHandler, packageIdentifier); |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | @Override |
| 191 | public String getTargetKind(Target target) { |
| 192 | return target.getTargetKind(); |
| 193 | } |
| 194 | |
Nathan Harmata | ad5d9c3 | 2017-03-11 00:03:18 +0000 | [diff] [blame] | 195 | /** |
| 196 | * A {@link ThreadSafeBatchCallback} that trivially delegates to a {@link BatchCallback} in a |
| 197 | * synchronized manner. |
| 198 | */ |
| 199 | private static class SynchronizedBatchCallback<T, E extends Exception> |
| 200 | implements ThreadSafeBatchCallback<T, E> { |
| 201 | private final BatchCallback<T, E> delegate; |
| 202 | |
| 203 | public SynchronizedBatchCallback(BatchCallback<T, E> delegate) { |
| 204 | this.delegate = delegate; |
| 205 | } |
| 206 | |
| 207 | @Override |
| 208 | public synchronized void process(Iterable<T> partialResult) throws E, InterruptedException { |
| 209 | delegate.process(partialResult); |
| 210 | } |
| 211 | } |
| 212 | |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 213 | @Override |
Janak Ramakrishnan | 5b5f22a | 2016-01-07 17:07:29 +0000 | [diff] [blame] | 214 | public <E extends Exception> void findTargetsBeneathDirectory( |
| 215 | final RepositoryName repository, |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 216 | final String originalPattern, |
Janak Ramakrishnan | 5b5f22a | 2016-01-07 17:07:29 +0000 | [diff] [blame] | 217 | String directory, |
| 218 | boolean rulesOnly, |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 219 | ImmutableSet<PathFragment> blacklistedSubdirectories, |
Janak Ramakrishnan | 3d9441b | 2016-01-13 17:38:29 +0000 | [diff] [blame] | 220 | ImmutableSet<PathFragment> excludedSubdirectories, |
Nathan Harmata | 5bd26b2 | 2016-11-14 19:55:50 +0000 | [diff] [blame] | 221 | BatchCallback<Target, E> callback, |
| 222 | Class<E> exceptionClass) |
| 223 | throws TargetParsingException, E, InterruptedException { |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 224 | try { |
| 225 | findTargetsBeneathDirectoryAsyncImpl( |
| 226 | repository, |
| 227 | originalPattern, |
| 228 | directory, |
| 229 | rulesOnly, |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 230 | blacklistedSubdirectories, |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 231 | excludedSubdirectories, |
| 232 | new SynchronizedBatchCallback<Target, E>(callback), |
| 233 | MoreExecutors.newDirectExecutorService()).get(); |
| 234 | } catch (ExecutionException e) { |
| 235 | Throwable cause = e.getCause(); |
| 236 | Throwables.propagateIfPossible(cause, TargetParsingException.class, exceptionClass); |
| 237 | throw new IllegalStateException(e.getCause()); |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | @Override |
| 242 | public <E extends Exception> ListenableFuture<Void> findTargetsBeneathDirectoryAsync( |
| 243 | RepositoryName repository, |
| 244 | String originalPattern, |
| 245 | String directory, |
| 246 | boolean rulesOnly, |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 247 | ImmutableSet<PathFragment> blacklistedSubdirectories, |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 248 | ImmutableSet<PathFragment> excludedSubdirectories, |
| 249 | ThreadSafeBatchCallback<Target, E> callback, |
| 250 | Class<E> exceptionClass, |
| 251 | ListeningExecutorService executor) { |
| 252 | return findTargetsBeneathDirectoryAsyncImpl( |
Nathan Harmata | 5bd26b2 | 2016-11-14 19:55:50 +0000 | [diff] [blame] | 253 | repository, |
| 254 | originalPattern, |
| 255 | directory, |
| 256 | rulesOnly, |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 257 | blacklistedSubdirectories, |
Nathan Harmata | 5bd26b2 | 2016-11-14 19:55:50 +0000 | [diff] [blame] | 258 | excludedSubdirectories, |
Nathan Harmata | ad5d9c3 | 2017-03-11 00:03:18 +0000 | [diff] [blame] | 259 | callback, |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 260 | executor); |
Nathan Harmata | 5bd26b2 | 2016-11-14 19:55:50 +0000 | [diff] [blame] | 261 | } |
| 262 | |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 263 | private <E extends Exception> ListenableFuture<Void> findTargetsBeneathDirectoryAsyncImpl( |
Nathan Harmata | 5bd26b2 | 2016-11-14 19:55:50 +0000 | [diff] [blame] | 264 | final RepositoryName repository, |
| 265 | final String originalPattern, |
| 266 | String directory, |
| 267 | boolean rulesOnly, |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 268 | ImmutableSet<PathFragment> blacklistedSubdirectories, |
Nathan Harmata | 5bd26b2 | 2016-11-14 19:55:50 +0000 | [diff] [blame] | 269 | ImmutableSet<PathFragment> excludedSubdirectories, |
| 270 | final ThreadSafeBatchCallback<Target, E> callback, |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 271 | ListeningExecutorService executor) { |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 272 | final FilteringPolicy actualPolicy = rulesOnly |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 273 | ? FilteringPolicies.and(FilteringPolicies.RULES_ONLY, policy) |
| 274 | : policy; |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 275 | final PathFragment pathFragment; |
| 276 | Iterable<PathFragment> packagesUnderDirectory; |
| 277 | try { |
| 278 | pathFragment = TargetPatternResolverUtil.getPathFragment(directory); |
Mark Schaller | fb2d38b | 2017-03-10 23:01:45 +0000 | [diff] [blame] | 279 | packagesUnderDirectory = |
| 280 | recursivePackageProvider.getPackagesUnderDirectory( |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 281 | eventHandler, |
| 282 | repository, |
| 283 | pathFragment, |
| 284 | blacklistedSubdirectories, |
| 285 | excludedSubdirectories); |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 286 | } catch (TargetParsingException e) { |
| 287 | return Futures.immediateFailedFuture(e); |
| 288 | } catch (InterruptedException e) { |
| 289 | return Futures.immediateCancelledFuture(); |
| 290 | } |
Eric Fellheimer | 7b8dbeb | 2015-12-30 15:21:43 +0000 | [diff] [blame] | 291 | |
| 292 | Iterable<PackageIdentifier> pkgIds = Iterables.transform(packagesUnderDirectory, |
| 293 | new Function<PathFragment, PackageIdentifier>() { |
| 294 | @Override |
| 295 | public PackageIdentifier apply(PathFragment path) { |
| 296 | return PackageIdentifier.create(repository, path); |
| 297 | } |
| 298 | }); |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 299 | final AtomicBoolean foundTarget = new AtomicBoolean(false); |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 300 | |
Janak Ramakrishnan | 5b5f22a | 2016-01-07 17:07:29 +0000 | [diff] [blame] | 301 | // For very large sets of packages, we may not want to process all of them at once, so we split |
| 302 | // into batches. |
Mark Schaller | d9d390a | 2016-06-21 22:01:28 +0000 | [diff] [blame] | 303 | List<List<PackageIdentifier>> partitions = |
| 304 | ImmutableList.copyOf(Iterables.partition(pkgIds, MAX_PACKAGES_BULK_GET)); |
Nathan Harmata | 7a5a236 | 2017-03-08 22:42:01 +0000 | [diff] [blame] | 305 | ArrayList<ListenableFuture<Void>> futures = new ArrayList<>(partitions.size()); |
Mark Schaller | d9d390a | 2016-06-21 22:01:28 +0000 | [diff] [blame] | 306 | for (final Iterable<PackageIdentifier> pkgIdBatch : partitions) { |
Googler | 77ba65e | 2017-06-26 19:55:09 +0200 | [diff] [blame] | 307 | futures.add( |
| 308 | executor.submit( |
| 309 | new Callable<Void>() { |
| 310 | @Override |
| 311 | public Void call() throws E, TargetParsingException, InterruptedException { |
| 312 | ImmutableSet<PackageIdentifier> pkgIdBatchSet = ImmutableSet.copyOf(pkgIdBatch); |
| 313 | packageSemaphore.acquireAll(pkgIdBatchSet); |
| 314 | try { |
| 315 | Iterable<ResolvedTargets<Target>> resolvedTargets = |
| 316 | bulkGetTargetsInPackage(originalPattern, pkgIdBatch, NO_FILTER).values(); |
| 317 | List<Target> filteredTargets = new ArrayList<>(calculateSize(resolvedTargets)); |
| 318 | for (ResolvedTargets<Target> targets : resolvedTargets) { |
| 319 | for (Target target : targets.getTargets()) { |
| 320 | // Perform the no-targets-found check before applying the filtering policy |
| 321 | // so we only return the error if the input directory's subtree really |
| 322 | // contains no targets. |
| 323 | foundTarget.set(true); |
| 324 | if (actualPolicy.shouldRetain(target, false)) { |
| 325 | filteredTargets.add(maybeConvertTargetBeforeReturn(target)); |
| 326 | } |
| 327 | } |
| 328 | } |
| 329 | callback.process(filteredTargets); |
| 330 | } finally { |
| 331 | packageSemaphore.releaseAll(pkgIdBatchSet); |
Nathan Harmata | 41b5417 | 2016-11-10 18:54:09 +0000 | [diff] [blame] | 332 | } |
Googler | 77ba65e | 2017-06-26 19:55:09 +0200 | [diff] [blame] | 333 | return null; |
Eric Fellheimer | 6f8b7ce | 2016-01-29 00:15:44 +0000 | [diff] [blame] | 334 | } |
Googler | 77ba65e | 2017-06-26 19:55:09 +0200 | [diff] [blame] | 335 | })); |
Mark Schaller | d9d390a | 2016-06-21 22:01:28 +0000 | [diff] [blame] | 336 | } |
Googler | 3d37b4c | 2017-04-25 04:19:01 +0200 | [diff] [blame] | 337 | return Futures.whenAllSucceed(futures) |
| 338 | .call( |
| 339 | new Callable<Void>() { |
| 340 | @Override |
| 341 | public Void call() throws TargetParsingException { |
| 342 | if (!foundTarget.get()) { |
| 343 | throw new TargetParsingException( |
| 344 | "no targets found beneath '" + pathFragment + "'"); |
| 345 | } |
| 346 | return null; |
| 347 | } |
| 348 | }, |
| 349 | directExecutor()); |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 350 | } |
Eric Fellheimer | 8c40daa | 2016-01-11 17:31:26 +0000 | [diff] [blame] | 351 | |
| 352 | private static <T> int calculateSize(Iterable<ResolvedTargets<T>> resolvedTargets) { |
| 353 | int size = 0; |
| 354 | for (ResolvedTargets<T> targets : resolvedTargets) { |
| 355 | size += targets.getTargets().size(); |
| 356 | } |
| 357 | return size; |
| 358 | } |
Mark Schaller | b889cf3 | 2015-03-17 20:55:30 +0000 | [diff] [blame] | 359 | } |
| 360 | |