blob: a9ef7b92045f71b8f34c96d6aa7bfde37b60ed24 [file] [log] [blame]
// Copyright 2015 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.skyframe;
import com.google.common.collect.ImmutableList;
import com.google.common.graph.ImmutableGraph;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.skyframe.SkyFunction.Environment;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyframeLookupResult;
/**
* Interface of an Action that is Skyframe-aware.
*
* <p><b>IMPORTANT</b>: actions that implement this interface should override {@code
* Action.executeUnconditionally} and return true. See below for details.
*
* <p>Implementors of this interface can request Skyframe dependencies to perform arbitrary
* computation or establish desired dependencies before they are executed but after their inputs
* have been built.
*
* <p>The {@link ActionExecutionFunction} will make sure that all requested SkyValues are built and
* that the {@link #processSkyframeValues} function completed successfully before attempting to
* execute the action.
*
* <p><b>It is crucial to correct action reexecution that implementors override {@code
* Action.executeUnconditionally} to always return true.</b> Skyframe tracks changes in both the
* input files and in dependencies established through {@link #processSkyframeValues}, but the
* action cache only knows about the input files. So if only the extra "skyframe dependencies"
* change, the action cache will believe the action to be up-to-date and skip actual execution.
* Therefore it's crucial to bypass action cache checking by marking the action as unconditionally
* executed.
*/
public interface SkyframeAwareAction {
/** Wrapper and/or base class for exceptions raised in {@link #processSkyframeValues}. */
class ExceptionBase extends Exception {
private final FailureDetail failureDetail;
public ExceptionBase(Throwable cause, FailureDetail failureDetail) {
super(cause.getMessage(), cause);
this.failureDetail = failureDetail;
}
public FailureDetail getFailureDetail() {
return failureDetail;
}
}
/** Returns the complete list of skyframe dependencies that this action needs. */
ImmutableList<? extends SkyKey> getDirectSkyframeDependencies();
/**
* Processes the skyframe dependencies requested in {@link #getDirectSkyframeDependencies}.
*
* <p><b>IMPORTANT</b>: actions that implement this interface should override {@code
* Action.executeUnconditionally} and return true. See {@link SkyframeAwareAction} why.
*
* <p>This method should perform as little computation as possible: ideally it should set some
* state somewhere and return. If this method needs to perform anything more complicated than
* that, including perhaps some non-trivial computation, you should implement that as a
* SkyFunction and request the corresponding SkyValue in this method.
*
* <p>Because the requested SkyValues may not yet be present in the graph, this method must be
* safe to call multiple times, and should always leave the action object in a consistent state.
*
* <p>This method should not attempt to handle errors or missing dependencies (other than wrapping
* exceptions); that is the responsibility of the caller. It should return as soon as possible,
* ready to be called again at a later time if need be.
*
* <p>The return value will be incorporated into the {@link
* com.google.devtools.build.lib.actions.ActionExecutionContext}.
*
* @param keys the keys requested in {@link #getDirectSkyframeDependencies}, with order preserved
* @param values the map of values from skyframe
* @param valuesMissing the return value of {@link Environment#valuesMissing} after requesting
* {@code keys}
*/
Object processSkyframeValues(
ImmutableList<? extends SkyKey> keys, SkyframeLookupResult values, boolean valuesMissing)
throws ExceptionBase;
/**
* Returns the Skyframe nodes which need to be rewound if a consumer of this action's output finds
* out that output has been lost.
*/
ImmutableGraph<SkyKey> getSkyframeDependenciesForRewinding(SkyKey self);
}