use of com.google.devtools.build.lib.actions.NotifyOnActionCacheHit in project bazel by bazelbuild.
the class SkyframeActionExecutor method checkActionCache.
/**
* Checks the action cache to see if {@code action} needs to be executed, or is up to date.
* Returns a token with the semantics of {@link ActionCacheChecker#getTokenIfNeedToExecute}: null
* if the action is up to date, and non-null if it needs to be executed, in which case that token
* should be provided to the ActionCacheChecker after execution.
*/
Token checkActionCache(Action action, MetadataHandler metadataHandler, long actionStartTime, Iterable<Artifact> resolvedCacheArtifacts, Map<String, String> clientEnv) {
profiler.startTask(ProfilerTask.ACTION_CHECK, action);
Token token = actionCacheChecker.getTokenIfNeedToExecute(action, resolvedCacheArtifacts, clientEnv, explain ? reporter : null, metadataHandler);
profiler.completeTask(ProfilerTask.ACTION_CHECK);
if (token == null) {
boolean eventPosted = false;
// Notify BlazeRuntimeStatistics about the action middleman 'execution'.
if (action.getActionType().isMiddleman()) {
postEvent(new ActionMiddlemanEvent(action, actionStartTime));
eventPosted = true;
}
if (action instanceof NotifyOnActionCacheHit) {
NotifyOnActionCacheHit notify = (NotifyOnActionCacheHit) action;
notify.actionCacheHit(executorEngine);
}
// We still need to check the outputs so that output file data is available to the value.
checkOutputs(action, metadataHandler);
if (!eventPosted) {
postEvent(new CachedActionEvent(action, actionStartTime));
}
}
return token;
}
use of com.google.devtools.build.lib.actions.NotifyOnActionCacheHit in project bazel by bazelbuild.
the class ActionExecutionFunction method compute.
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws ActionExecutionFunctionException, InterruptedException {
Preconditions.checkArgument(skyKey.argument() instanceof Action);
Action action = (Action) skyKey.argument();
// BUILD_ID, forcing invalidation of upward transitive closure on each build.
if ((action.isVolatile() && !(action instanceof SkyframeAwareAction)) || action instanceof NotifyOnActionCacheHit) {
// Volatile build actions may need to execute even if none of their known inputs have changed.
// Depending on the buildID ensure that these actions have a chance to execute.
PrecomputedValue.BUILD_ID.get(env);
}
// Look up the parts of the environment that influence the action.
Map<SkyKey, SkyValue> clientEnvLookup = env.getValues(Iterables.transform(action.getClientEnvironmentVariables(), VAR_TO_SKYKEY));
if (env.valuesMissing()) {
return null;
}
Map<String, String> clientEnv = new HashMap<>();
for (Entry<SkyKey, SkyValue> entry : clientEnvLookup.entrySet()) {
ClientEnvironmentValue envValue = (ClientEnvironmentValue) entry.getValue();
if (envValue.getValue() != null) {
clientEnv.put((String) entry.getKey().argument(), envValue.getValue());
}
}
// For restarts of this ActionExecutionFunction we use a ContinuationState variable, below, to
// avoid redoing work. However, if two actions are shared and the first one executes, when the
// second one goes to execute, we should detect that and short-circuit, even without taking
// ContinuationState into account.
boolean sharedActionAlreadyRan = skyframeActionExecutor.probeActionExecution(action);
ContinuationState state;
if (action.discoversInputs()) {
state = getState(action);
} else {
// Because this is a new state, all conditionals below about whether state has already done
// something will return false, and so we will execute all necessary steps.
state = new ContinuationState();
}
if (!state.hasCollectedInputs()) {
state.allInputs = collectInputs(action, env);
if (state.allInputs == null) {
// Missing deps.
return null;
}
} else if (state.allInputs.keysRequested != null) {
// Preserve the invariant that we ask for the same deps each build.
env.getValues(state.allInputs.keysRequested);
Preconditions.checkState(!env.valuesMissing(), "%s %s", action, state);
}
Pair<Map<Artifact, FileArtifactValue>, Map<Artifact, Collection<Artifact>>> checkedInputs = null;
try {
// Declare deps on known inputs to action. We do this unconditionally to maintain our
// invariant of asking for the same deps each build.
Map<SkyKey, ValueOrException2<MissingInputFileException, ActionExecutionException>> inputDeps = env.getValuesOrThrow(toKeys(state.allInputs.getAllInputs(), action.discoversInputs() ? action.getMandatoryInputs() : null), MissingInputFileException.class, ActionExecutionException.class);
if (!sharedActionAlreadyRan && !state.hasArtifactData()) {
// Do we actually need to find our metadata?
checkedInputs = checkInputs(env, action, inputDeps);
}
} catch (ActionExecutionException e) {
// Remove action from state map in case it's there (won't be unless it discovers inputs).
stateMap.remove(action);
throw new ActionExecutionFunctionException(e);
}
if (env.valuesMissing()) {
// of the action; see establishSkyframeDependencies why.
return null;
}
try {
establishSkyframeDependencies(env, action);
} catch (ActionExecutionException e) {
throw new ActionExecutionFunctionException(e);
}
if (env.valuesMissing()) {
return null;
}
if (checkedInputs != null) {
Preconditions.checkState(!state.hasArtifactData(), "%s %s", state, action);
state.inputArtifactData = checkedInputs.first;
state.expandedArtifacts = checkedInputs.second;
}
ActionExecutionValue result;
try {
result = checkCacheAndExecuteIfNeeded(action, state, env, clientEnv);
} catch (ActionExecutionException e) {
// Remove action from state map in case it's there (won't be unless it discovers inputs).
stateMap.remove(action);
// action. Label can be null in the case of, e.g., the SystemActionOwner (for build-info.txt).
throw new ActionExecutionFunctionException(new AlreadyReportedActionExecutionException(e));
}
if (env.valuesMissing()) {
Preconditions.checkState(stateMap.containsKey(action), action);
return null;
}
// Remove action from state map in case it's there (won't be unless it discovers inputs).
stateMap.remove(action);
return result;
}
Aggregations