in src/com/facebook/buck/cli/CacheCommand.java [115:311]
public ExitCode runWithoutHelp(CommandRunnerParams params) throws Exception {
params.getBuckEventBus().post(ConsoleEvent.fine("cache command start"));
if (isNoCache()) {
params.getBuckEventBus().post(ConsoleEvent.severe("Caching is disabled."));
return ExitCode.NOTHING_TO_DO;
}
List<String> arguments = getArguments();
// Lack of arguments implicitly means fetch now. The old behaviour will be deprecated soon.
// TODO(nga): Remove old behaviour of buck cache.
if (!arguments.isEmpty() && arguments.get(0).equals("fetch")) {
arguments = arguments.subList(1, arguments.size());
} else {
if (!MUTE_FETCH_SUBCOMMAND_WARNING) {
params
.getConsole()
.printErrorText(
"Using `cache` without a command is deprecated, use `cache fetch` instead");
}
}
if (arguments.isEmpty() && targetsWithRuleKeys.isEmpty()) {
throw new CommandLineException("no cache keys specified");
}
if (outputDir != null) {
outputPath = Optional.of(Paths.get(outputDir));
Files.createDirectories(outputPath.get());
}
ImmutableList<RuleKey> rawRuleKeys =
arguments.stream().map(RuleKey::new).collect(ImmutableList.toImmutableList());
ImmutableList<Pair<BuildTarget, RuleKey>> pairedRuleKeys =
targetsWithRuleKeys.stream()
.map(pair -> parseTargetRuleKeyPair(params, pair))
.collect(ImmutableList.toImmutableList());
Path tmpDir = Files.createTempDirectory("buck-cache-command");
BuildEvent.Started started = BuildEvent.started(getArguments());
List<ArtifactRunner> results = null;
try (ArtifactCache cache = params.getArtifactCacheFactory().newInstance();
CommandThreadManager pool =
new CommandThreadManager("Build", getConcurrencyLimit(params.getBuckConfig()))) {
WeightedListeningExecutorService executor = pool.getWeightedListeningExecutorService();
fakeOutParseEvents(params.getBuckEventBus());
params.getBuckEventBus().post(started);
// Fetch all artifacts
List<ListenableFuture<ArtifactRunner>> futures = new ArrayList<>();
for (RuleKey ruleKey : rawRuleKeys) {
futures.add(
executor.submit(
new ArtifactRunner(
params.getProjectFilesystemFactory(), null, ruleKey, tmpDir, cache)));
}
for (Pair<BuildTarget, RuleKey> targetRuleKeyPair : pairedRuleKeys) {
futures.add(
executor.submit(
new ArtifactRunner(
params.getProjectFilesystemFactory(),
targetRuleKeyPair.getFirst(),
targetRuleKeyPair.getSecond(),
tmpDir,
cache)));
}
// Wait for all executions to complete or fail.
try {
results = Futures.allAsList(futures).get();
} catch (ExecutionException ex) {
params.getConsole().printBuildFailure("Failed");
ex.printStackTrace(params.getConsole().getStdErr());
}
}
int totalRuns = results.size();
StringBuilder resultString = new StringBuilder();
int goodRuns = 0;
HashMap<ArtifactCacheMode, AtomicInteger> cacheHitsPerMode = new HashMap<>();
HashMap<ArtifactCacheMode, AtomicInteger> cacheErrorsPerMode = new HashMap<>();
HashMap<ArtifactCacheMode, AtomicLong> cacheBytesPerMode = new HashMap<>();
for (ArtifactCacheMode mode : ArtifactCacheMode.values()) {
cacheHitsPerMode.put(mode, new AtomicInteger(0));
cacheErrorsPerMode.put(mode, new AtomicInteger(0));
cacheBytesPerMode.put(mode, new AtomicLong(0L));
}
int cacheHits = 0;
int cacheMisses = 0;
int cacheErrors = 0;
int cacheIgnored = 0;
int localKeyUnchanged = 0;
long cacheBytes = 0L;
for (ArtifactRunner r : results) {
if (r.completed) {
goodRuns++;
}
resultString.append(r.resultString);
ArtifactCacheMode artifactCacheMode = r.cacheResultMode.orElse(ArtifactCacheMode.unknown);
switch (r.cacheResultType) {
case ERROR:
case SOFT_ERROR:
if (cacheErrorsPerMode.containsKey(artifactCacheMode)) {
cacheErrorsPerMode.get(artifactCacheMode).incrementAndGet();
}
++cacheErrors;
break;
case CONTAINS:
// Ignore it since it will be counted as a hit later.
break;
case HIT:
if (cacheHitsPerMode.containsKey(artifactCacheMode)) {
cacheHitsPerMode.get(artifactCacheMode).incrementAndGet();
}
AtomicLong bytes = cacheBytesPerMode.get(artifactCacheMode);
if (bytes != null) {
bytes.addAndGet(r.artifactSize);
}
++cacheHits;
cacheBytes += r.artifactSize;
break;
case MISS:
++cacheMisses;
break;
case IGNORED:
++cacheIgnored;
break;
case LOCAL_KEY_UNCHANGED_HIT:
++localKeyUnchanged;
break;
case SKIPPED:
break;
}
if (!outputPath.isPresent()) {
// legacy output
if (r.completed) {
params.getConsole().getStdOut().println(resultString);
params
.getConsole()
.printSuccess(
String.format(
"Successfully downloaded artifact with id %s at %s.", r.ruleKey, r.artifact));
} else {
params
.getConsole()
.printErrorText(
String.format(
"Failed to retrieve an artifact with id %s (%s).", r.ruleKey, r.cacheResult));
}
}
}
params
.getBuckEventBus()
.post(
CacheCountersSummaryEvent.newSummary(
CacheCountersSummary.of(
cacheHitsPerMode,
cacheErrorsPerMode,
cacheBytesPerMode,
cacheHits,
cacheErrors,
cacheMisses,
cacheIgnored,
cacheBytes,
localKeyUnchanged,
new AtomicInteger(0),
new AtomicInteger(0))));
ExitCode exitCode = (totalRuns == goodRuns) ? ExitCode.SUCCESS : ExitCode.BUILD_ERROR;
params.getBuckEventBus().post(BuildEvent.finished(started, exitCode));
if (outputPath.isPresent()) {
if (totalRuns == goodRuns) {
params.getConsole().printSuccess("Successfully downloaded all artifacts.");
} else {
params
.getConsole()
.printErrorText(String.format("Downloaded %d of %d artifacts", goodRuns, totalRuns));
}
params.getConsole().getStdOut().println(resultString);
}
return exitCode;
}