| // Copyright 2017 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.exec; | |
| import com.google.devtools.build.lib.actions.ActionContext; | |
| import com.google.devtools.build.lib.actions.ExecException; | |
| import com.google.devtools.build.lib.actions.Spawn; | |
| import com.google.devtools.build.lib.actions.SpawnResult; | |
| import com.google.devtools.build.lib.exec.SpawnRunner.SpawnExecutionContext; | |
| import java.io.Closeable; | |
| import java.io.IOException; | |
| import java.util.NoSuchElementException; | |
| /** | |
| * A cache that can lookup a {@link SpawnResult} given a {@link Spawn}, and can also upload the | |
| * results of an executed spawn to the cache. | |
| * | |
| * <p>This is an experimental interface to implement caching with sandboxed local execution. | |
| */ | |
| public interface SpawnCache extends ActionContext { | |
| /** A no-op implementation that has no result, and performs no upload. */ | |
| public static CacheHandle NO_RESULT_NO_STORE = | |
| new CacheHandle() { | |
| @Override | |
| public boolean hasResult() { | |
| return false; | |
| } | |
| @Override | |
| public SpawnResult getResult() { | |
| throw new NoSuchElementException(); | |
| } | |
| @Override | |
| public boolean willStore() { | |
| return false; | |
| } | |
| @Override | |
| public void store(SpawnResult result) throws InterruptedException, IOException { | |
| // Do nothing. | |
| } | |
| @Override | |
| public void close() {} | |
| }; | |
| /** | |
| * Helper method to create a {@link CacheHandle} from a successful {@link SpawnResult} instance. | |
| */ | |
| public static CacheHandle success(final SpawnResult result) { | |
| return new CacheHandle() { | |
| @Override | |
| public boolean hasResult() { | |
| return true; | |
| } | |
| @Override | |
| public SpawnResult getResult() { | |
| return result; | |
| } | |
| @Override | |
| public boolean willStore() { | |
| return false; | |
| } | |
| @Override | |
| public void store(SpawnResult result) throws InterruptedException, IOException { | |
| throw new IllegalStateException(); | |
| } | |
| @Override | |
| public void close() {} | |
| }; | |
| } | |
| /** A no-op spawn cache. */ | |
| public static class NoSpawnCache implements SpawnCache { | |
| @Override | |
| public CacheHandle lookup(Spawn spawn, SpawnExecutionContext context) { | |
| return SpawnCache.NO_RESULT_NO_STORE; | |
| } | |
| } | |
| /** A no-op implementation that has no results and performs no stores. */ | |
| public static SpawnCache NO_CACHE = new NoSpawnCache(); | |
| /** | |
| * This object represents both a successful and an unsuccessful cache lookup. If | |
| * {@link #hasResult} returns true, then {@link #getResult} must successfully return a non-null | |
| * instance (use the {@link #success} helper method). Otherwise {@link #getResult} should throw an | |
| * {@link IllegalStateException}. | |
| * | |
| * <p>If {@link #hasResult} returns false, then {@link #store} may upload the result to the cache | |
| * after successful execution. | |
| * | |
| * <p>Note that this interface extends {@link Closeable}, and callers must guarantee that | |
| * {@link #close} is called on this entry (e.g., by using try-with-resources) to free up any | |
| * acquired resources. | |
| */ | |
| interface CacheHandle extends Closeable { | |
| /** Returns whether the cache lookup was successful. */ | |
| boolean hasResult(); | |
| /** | |
| * Returns the cached result. | |
| * | |
| * @throws NoSuchElementException if there is no result in this cache entry | |
| */ | |
| SpawnResult getResult(); | |
| /** | |
| * Returns true if the store call will actually do work. Use this to avoid unnecessary work | |
| * before store if it won't do anything. | |
| */ | |
| boolean willStore(); | |
| /** | |
| * Called after successful {@link Spawn} execution, which may or may not store the result in the | |
| * cache. | |
| * | |
| * <p>A cache may silently return from a failed store operation. We recommend to err on the side | |
| * of raising an exception rather than returning silently, and to offer command-line flags to | |
| * tweak this default policy as needed. | |
| * | |
| * <p>If the current thread is interrupted, then this method should return as quickly as | |
| * possible with an {@link InterruptedException}. | |
| */ | |
| void store(SpawnResult result) throws ExecException, InterruptedException, IOException; | |
| } | |
| /** | |
| * Perform a spawn lookup. This method is similar to {@link SpawnRunner#exec}, taking the same | |
| * parameters and being allowed to throw the same exceptions. The intent for this method is to | |
| * compute a cache lookup key for the given spawn, looking it up in an implementation-dependent | |
| * cache (can be either on the local or remote machine), and returning a non-null {@link | |
| * CacheHandle} instance. | |
| * | |
| * <p>If the lookup was successful, this method should write the cached outputs to their | |
| * corresponding output locations in the output tree, as well as stdout and stderr, after | |
| * notifying {@link SpawnExecutionContext#lockOutputFiles}. | |
| * | |
| * <p>If the lookup was unsuccessful, this method can return a {@link CacheHandle} instance that | |
| * has no result, but uploads the results of the execution to the cache. The reason for a callback | |
| * object is for the cache to store expensive intermediate values (such as the cache key) that are | |
| * needed both for the lookup and the subsequent store operation. | |
| * | |
| * <p>The lookup must not succeed for non-cachable spawns. See {@link Spawns#mayBeCached()} and | |
| * {@link Spawns#mayBeCachedRemotely}. | |
| * | |
| * <p>Note that cache stores may be disabled, in which case the returned {@link CacheHandle} | |
| * instance's {@link CacheHandle#store} is a no-op. | |
| */ | |
| CacheHandle lookup(Spawn spawn, SpawnExecutionContext context) | |
| throws ExecException, IOException, InterruptedException; | |
| } |