use of com.google.devtools.build.lib.actions.MissingInputFileException in project bazel by bazelbuild.
the class ArtifactFunction method compute.
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws ArtifactFunctionException, InterruptedException {
OwnedArtifact ownedArtifact = (OwnedArtifact) skyKey.argument();
Artifact artifact = ownedArtifact.getArtifact();
if (artifact.isSourceArtifact()) {
try {
return createSourceValue(artifact, ownedArtifact.isMandatory(), env);
} catch (MissingInputFileException e) {
// is potentially used to report root causes.
throw new ArtifactFunctionException(e, Transience.TRANSIENT);
}
}
ActionAnalysisMetadata actionMetadata = extractActionFromArtifact(artifact, env);
if (actionMetadata == null) {
return null;
}
// actions, execute those actions in parallel and then aggregate the action execution results.
if (artifact.isTreeArtifact() && actionMetadata instanceof ActionTemplate) {
// Create the directory structures for the output TreeArtifact first.
try {
FileSystemUtils.createDirectoryAndParents(artifact.getPath());
} catch (IOException e) {
env.getListener().handle(Event.error(String.format("Failed to create output directory for TreeArtifact %s: %s", artifact, e.getMessage())));
throw new ArtifactFunctionException(e, Transience.TRANSIENT);
}
return createTreeArtifactValueFromActionTemplate((ActionTemplate) actionMetadata, artifact, env);
} else {
Preconditions.checkState(actionMetadata instanceof Action, "%s is not a proper Action object and therefore cannot be executed", actionMetadata);
Action action = (Action) actionMetadata;
ActionExecutionValue actionValue = (ActionExecutionValue) env.getValue(ActionExecutionValue.key(action));
if (actionValue == null) {
return null;
}
if (artifact.isTreeArtifact()) {
// TreeArtifactValue.
return Preconditions.checkNotNull(actionValue.getTreeArtifactValue(artifact), artifact);
} else if (isAggregatingValue(action)) {
return createAggregatingValue(artifact, action, actionValue.getArtifactValue(artifact), env);
} else {
return createSimpleFileArtifactValue(artifact, action, actionValue, env);
}
}
}
use of com.google.devtools.build.lib.actions.MissingInputFileException in project bazel by bazelbuild.
the class ActionExecutionFunction method checkInputs.
/**
* Declare dependency on all known inputs of action. Throws exception if any are known to be
* missing. Some inputs may not yet be in the graph, in which case the builder should abort.
*/
private Pair<Map<Artifact, FileArtifactValue>, Map<Artifact, Collection<Artifact>>> checkInputs(Environment env, Action action, Map<SkyKey, ValueOrException2<MissingInputFileException, ActionExecutionException>> inputDeps) throws ActionExecutionException {
int missingCount = 0;
int actionFailures = 0;
boolean catastrophe = false;
// Only populate input data if we have the input values, otherwise they'll just go unused.
// We still want to loop through the inputs to collect missing deps errors. During the
// evaluator "error bubbling", we may get one last chance at reporting errors even though
// some deps are still missing.
boolean populateInputData = !env.valuesMissing();
NestedSetBuilder<Cause> rootCauses = NestedSetBuilder.stableOrder();
Map<Artifact, FileArtifactValue> inputArtifactData = new HashMap<>(populateInputData ? inputDeps.size() : 0);
Map<Artifact, Collection<Artifact>> expandedArtifacts = new HashMap<>(populateInputData ? 128 : 0);
ActionExecutionException firstActionExecutionException = null;
for (Map.Entry<SkyKey, ValueOrException2<MissingInputFileException, ActionExecutionException>> depsEntry : inputDeps.entrySet()) {
Artifact input = ArtifactSkyKey.artifact(depsEntry.getKey());
try {
SkyValue value = depsEntry.getValue().get();
if (populateInputData) {
if (value instanceof AggregatingArtifactValue) {
AggregatingArtifactValue aggregatingValue = (AggregatingArtifactValue) value;
for (Pair<Artifact, FileArtifactValue> entry : aggregatingValue.getInputs()) {
inputArtifactData.put(entry.first, entry.second);
}
// We have to cache the "digest" of the aggregating value itself,
// because the action cache checker may want it.
inputArtifactData.put(input, aggregatingValue.getSelfData());
ImmutableList.Builder<Artifact> expansionBuilder = ImmutableList.builder();
for (Pair<Artifact, FileArtifactValue> pair : aggregatingValue.getInputs()) {
expansionBuilder.add(pair.first);
}
expandedArtifacts.put(input, expansionBuilder.build());
} else if (value instanceof TreeArtifactValue) {
TreeArtifactValue treeValue = (TreeArtifactValue) value;
expandedArtifacts.put(input, ImmutableSet.<Artifact>copyOf(treeValue.getChildren()));
inputArtifactData.putAll(treeValue.getChildValues());
// Again, we cache the "digest" of the value for cache checking.
inputArtifactData.put(input, treeValue.getSelfData());
} else {
Preconditions.checkState(value instanceof FileArtifactValue, depsEntry);
inputArtifactData.put(input, (FileArtifactValue) value);
}
}
} catch (MissingInputFileException e) {
missingCount++;
if (input.getOwner() != null) {
rootCauses.add(new LabelCause(input.getOwner()));
}
} catch (ActionExecutionException e) {
actionFailures++;
if (firstActionExecutionException == null) {
firstActionExecutionException = e;
}
catastrophe = catastrophe || e.isCatastrophe();
rootCauses.addTransitive(e.getRootCauses());
}
}
// We need to rethrow first exception because it can contain useful error message
if (firstActionExecutionException != null) {
if (missingCount == 0 && actionFailures == 1) {
// having to copy the root causes to the upwards transitive closure.
throw firstActionExecutionException;
}
throw new ActionExecutionException(firstActionExecutionException.getMessage(), firstActionExecutionException.getCause(), action, rootCauses.build(), catastrophe, firstActionExecutionException.getExitCode());
}
if (missingCount > 0) {
for (Cause missingInput : rootCauses.build()) {
env.getListener().handle(Event.error(action.getOwner().getLocation(), String.format("%s: missing input file '%s'", action.getOwner().getLabel(), missingInput.getLabel())));
}
throw new ActionExecutionException(missingCount + " input file(s) do not exist", action, rootCauses.build(), /*catastrophe=*/
false);
}
return Pair.of(inputArtifactData, expandedArtifacts);
}
use of com.google.devtools.build.lib.actions.MissingInputFileException in project bazel by bazelbuild.
the class TreeArtifactMetadataTest method testIOExceptionEndToEnd.
/**
* Tests that ArtifactFunction rethrows transitive {@link IOException}s as
* {@link MissingInputFileException}s.
*/
@Test
public void testIOExceptionEndToEnd() throws Throwable {
final IOException exception = new IOException("boop");
setupRoot(new CustomInMemoryFs() {
@Override
public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
if (path.getBaseName().equals("one")) {
throw exception;
}
return super.stat(path, followSymlinks);
}
});
try {
Artifact artifact = createTreeArtifact("outOne");
TreeArtifactValue value = evaluateTreeArtifact(artifact, ImmutableList.of(new PathFragment("one")));
fail("MissingInputFileException expected, got " + value);
} catch (Exception e) {
assertThat(Throwables.getRootCause(e).getMessage()).contains(exception.getMessage());
}
}
use of com.google.devtools.build.lib.actions.MissingInputFileException in project bazel by bazelbuild.
the class SkyframeBuilder method rethrow.
/** Figure out why an action's execution failed and rethrow the right kind of exception. */
@VisibleForTesting
public static void rethrow(Throwable cause) throws BuildFailedException, TestExecException {
Throwable innerCause = cause.getCause();
if (innerCause instanceof TestExecException) {
throw (TestExecException) innerCause;
}
if (cause instanceof ActionExecutionException) {
ActionExecutionException actionExecutionCause = (ActionExecutionException) cause;
// Sometimes ActionExecutionExceptions are caused by Actions with no owner.
String message = (actionExecutionCause.getLocation() != null) ? (actionExecutionCause.getLocation().print() + " " + cause.getMessage()) : cause.getMessage();
throw new BuildFailedException(message, actionExecutionCause.isCatastrophe(), actionExecutionCause.getAction(), actionExecutionCause.getRootCauses(), /*errorAlreadyShown=*/
!actionExecutionCause.showError(), actionExecutionCause.getExitCode());
} else if (cause instanceof MissingInputFileException) {
throw new BuildFailedException(cause.getMessage());
} else if (cause instanceof BuildFileNotFoundException) {
// Sadly, this can happen because we may load new packages during input discovery. Any
// failures reading those packages shouldn't terminate the build, but in Skyframe they do.
LoggingUtil.logToRemote(Level.WARNING, "undesirable loading exception", cause);
throw new BuildFailedException(cause.getMessage());
} else if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
} else {
// expectations in this method.
throw new IllegalArgumentException("action terminated with " + "unexpected exception: " + cause.getMessage(), cause);
}
}
use of com.google.devtools.build.lib.actions.MissingInputFileException in project bazel by bazelbuild.
the class CompletionFunction method compute.
@Nullable
@Override
public SkyValue compute(SkyKey skyKey, Environment env) throws CompletionFunctionException, InterruptedException {
TValue value = completor.getValueFromSkyKey(skyKey, env);
TopLevelArtifactContext topLevelContext = completor.getTopLevelArtifactContext(skyKey);
if (env.valuesMissing()) {
return null;
}
Map<SkyKey, ValueOrException2<MissingInputFileException, ActionExecutionException>> inputDeps = env.getValuesOrThrow(ArtifactSkyKey.mandatoryKeys(completor.getAllArtifactsToBuild(value, topLevelContext).getAllArtifacts()), MissingInputFileException.class, ActionExecutionException.class);
int missingCount = 0;
ActionExecutionException firstActionExecutionException = null;
MissingInputFileException missingInputException = null;
NestedSetBuilder<Cause> rootCausesBuilder = NestedSetBuilder.stableOrder();
for (Map.Entry<SkyKey, ValueOrException2<MissingInputFileException, ActionExecutionException>> depsEntry : inputDeps.entrySet()) {
Artifact input = ArtifactSkyKey.artifact(depsEntry.getKey());
try {
depsEntry.getValue().get();
} catch (MissingInputFileException e) {
missingCount++;
final Label inputOwner = input.getOwner();
if (inputOwner != null) {
Cause cause = new LabelCause(inputOwner);
rootCausesBuilder.add(cause);
env.getListener().handle(completor.getRootCauseError(value, cause));
}
} catch (ActionExecutionException e) {
rootCausesBuilder.addTransitive(e.getRootCauses());
if (firstActionExecutionException == null) {
firstActionExecutionException = e;
}
}
}
if (missingCount > 0) {
missingInputException = completor.getMissingFilesException(value, missingCount);
}
NestedSet<Cause> rootCauses = rootCausesBuilder.build();
if (!rootCauses.isEmpty()) {
eventBusRef.get().post(completor.createFailed(value, rootCauses));
if (firstActionExecutionException != null) {
throw new CompletionFunctionException(firstActionExecutionException);
} else {
throw new CompletionFunctionException(missingInputException);
}
}
return env.valuesMissing() ? null : completor.createResult(value);
}
Aggregations