blob: 47d6956bbdfcaac046dac34caf0496ec8bcd871f [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.skyframe;
15
janakrfce927f2017-11-03 21:48:32 +010016import com.google.common.base.MoreObjects;
tomlua155b532017-11-08 20:12:47 +010017import com.google.common.base.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010018import com.google.common.collect.ImmutableList;
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000019import com.google.common.collect.Iterables;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010020import com.google.devtools.build.lib.collect.nestedset.NestedSet;
21import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
22import com.google.devtools.build.lib.collect.nestedset.Order;
23import com.google.devtools.build.skyframe.SkyFunctionException.ReifiedSkyFunctionException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010024import java.util.Collection;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025import javax.annotation.Nullable;
26
27/**
28 * Information about why a {@link SkyValue} failed to evaluate successfully.
29 *
30 * <p>This is intended only for use in alternative {@code MemoizingEvaluator} implementations.
31 */
Michajlo Matijkiw4e29c832015-09-30 22:23:25 +000032public class ErrorInfo {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010033
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000034 /** Create an ErrorInfo from a {@link ReifiedSkyFunctionException}. */
Nathan Harmata97731682015-12-09 23:36:22 +000035 public static ErrorInfo fromException(ReifiedSkyFunctionException skyFunctionException,
36 boolean isTransitivelyTransient) {
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000037 SkyKey rootCauseSkyKey = skyFunctionException.getRootCauseSkyKey();
38 Exception rootCauseException = skyFunctionException.getCause();
39 return new ErrorInfo(
40 NestedSetBuilder.create(Order.STABLE_ORDER, rootCauseSkyKey),
41 Preconditions.checkNotNull(rootCauseException, "Cause null %s", rootCauseException),
42 rootCauseSkyKey,
43 /*cycles=*/ ImmutableList.<CycleInfo>of(),
nharmatabea67e92017-06-16 00:26:27 +020044 skyFunctionException.isTransient(),
Nathan Harmata97731682015-12-09 23:36:22 +000045 isTransitivelyTransient || skyFunctionException.isTransient(),
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000046 skyFunctionException.isCatastrophic());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010047 }
48
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000049 /** Create an ErrorInfo from a {@link CycleInfo}. */
Michajlo Matijkiwe8f7f5e2015-09-30 02:39:27 +000050 public static ErrorInfo fromCycle(CycleInfo cycleInfo) {
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000051 return new ErrorInfo(
52 /*rootCauses=*/ NestedSetBuilder.<SkyKey>emptySet(Order.STABLE_ORDER),
53 /*exception=*/ null,
54 /*rootCauseOfException=*/ null,
55 ImmutableList.of(cycleInfo),
nharmatabea67e92017-06-16 00:26:27 +020056 /*isDirectlyTransient=*/ false,
57 /*isTransitivelyTransient=*/ false,
cushon03e70182017-09-15 09:33:27 +020058 /* isCatostrophic= */ false);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059 }
60
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000061 /** Create an ErrorInfo from a collection of existing errors. */
62 public static ErrorInfo fromChildErrors(SkyKey currentValue, Collection<ErrorInfo> childErrors) {
63 Preconditions.checkNotNull(currentValue, "currentValue must not be null");
64 Preconditions.checkState(!childErrors.isEmpty(), "childErrors may not be empty");
65
66 NestedSetBuilder<SkyKey> rootCausesBuilder = NestedSetBuilder.stableOrder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010067 ImmutableList.Builder<CycleInfo> cycleBuilder = ImmutableList.builder();
68 Exception firstException = null;
69 SkyKey firstChildKey = null;
nharmatabea67e92017-06-16 00:26:27 +020070 boolean isTransitivelyTransient = false;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010071 boolean isCatastrophic = false;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010072 for (ErrorInfo child : childErrors) {
73 if (firstException == null) {
Nathan Harmata97731682015-12-09 23:36:22 +000074 // Arbitrarily pick the first error.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010075 firstException = child.getException();
76 firstChildKey = child.getRootCauseOfException();
77 }
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000078 rootCausesBuilder.addTransitive(child.rootCauses);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010079 cycleBuilder.addAll(CycleInfo.prepareCycles(currentValue, child.cycles));
nharmatabea67e92017-06-16 00:26:27 +020080 isTransitivelyTransient |= child.isTransitivelyTransient();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010081 isCatastrophic |= child.isCatastrophic();
82 }
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000083
84 return new ErrorInfo(
85 rootCausesBuilder.build(),
86 firstException,
87 firstChildKey,
88 cycleBuilder.build(),
nharmatabea67e92017-06-16 00:26:27 +020089 /*isDirectlyTransient=*/ false,
90 isTransitivelyTransient,
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000091 isCatastrophic);
92 }
93
Michajlo Matijkiw7241fd62015-10-05 18:08:57 +000094 private final NestedSet<SkyKey> rootCauses;
Michajlo Matijkiwaa058282015-09-28 22:13:27 +000095
96 @Nullable private final Exception exception;
97 private final SkyKey rootCauseOfException;
98
99 private final ImmutableList<CycleInfo> cycles;
100
nharmatabea67e92017-06-16 00:26:27 +0200101 private final boolean isDirectlyTransient;
102 private final boolean isTransitivelyTransient;
Michajlo Matijkiwaa058282015-09-28 22:13:27 +0000103 private final boolean isCatastrophic;
104
nharmatabea67e92017-06-16 00:26:27 +0200105 public ErrorInfo(
106 NestedSet<SkyKey> rootCauses,
107 @Nullable Exception exception,
108 SkyKey rootCauseOfException,
109 ImmutableList<CycleInfo> cycles,
110 boolean isDirectlyTransient,
111 boolean isTransitivelyTransient,
Michajlo Matijkiwaa058282015-09-28 22:13:27 +0000112 boolean isCatostrophic) {
113 Preconditions.checkState(exception != null || !Iterables.isEmpty(cycles),
114 "At least one of exception and cycles must be non-null/empty, respectively");
115 Preconditions.checkState((exception == null) == (rootCauseOfException == null),
116 "exception and rootCauseOfException must both be null or non-null, got %s %s",
117 exception, rootCauseOfException);
118
119 this.rootCauses = rootCauses;
120 this.exception = exception;
121 this.rootCauseOfException = rootCauseOfException;
122 this.cycles = cycles;
nharmatabea67e92017-06-16 00:26:27 +0200123 this.isDirectlyTransient = isDirectlyTransient;
124 this.isTransitivelyTransient = isTransitivelyTransient;
Michajlo Matijkiwaa058282015-09-28 22:13:27 +0000125 this.isCatastrophic = isCatostrophic;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100126 }
127
128 @Override
129 public String toString() {
janakrfce927f2017-11-03 21:48:32 +0100130 return MoreObjects.toStringHelper(this)
131 .add("exception", exception)
132 .add("rootCauses", rootCauses)
133 .add("cycles", cycles)
134 .add("isCatastrophic", isCatastrophic)
135 .add("rootCauseOfException", rootCauseOfException)
136 .add("isDirectlyTransient", isDirectlyTransient)
137 .add("isTransitivelyTransient", isTransitivelyTransient)
138 .toString();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100139 }
140
141 /**
142 * The root causes of a value that failed to build are its descendant values that failed to build.
143 * If a value's descendants all built successfully, but it failed to, its root cause will be
144 * itself. If a value depends on a cycle, but has no other errors, this method will return
145 * the empty set.
146 */
147 public Iterable<SkyKey> getRootCauses() {
148 return rootCauses;
149 }
150
151 /**
152 * The exception thrown when building a value. May be null if value's only error is depending
153 * on a cycle.
Michajlo Matijkiwaa058282015-09-28 22:13:27 +0000154 *
155 * <p>The exception is used for reporting and thus may ultimately be rethrown by the caller.
156 * As well, during a --nokeep_going evaluation, if an error value is encountered from an earlier
157 * --keep_going build, the exception to be thrown is taken from here.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100158 */
159 @Nullable public Exception getException() {
160 return exception;
161 }
162
163 public SkyKey getRootCauseOfException() {
164 return rootCauseOfException;
165 }
166
167 /**
168 * Any cycles found when building this value.
169 *
170 * <p>If there are a large number of cycles, only a limited number are returned here.
171 *
172 * <p>If this value has a child through which there are multiple paths to the same cycle, only one
173 * path is returned here. However, if there are multiple paths to the same cycle, each of which
174 * goes through a different child, each of them is returned here.
175 */
176 public Iterable<CycleInfo> getCycleInfo() {
177 return cycles;
178 }
179
180 /**
nharmatabea67e92017-06-16 00:26:27 +0200181 * Returns true iff the error is directly transient, i.e. if there was a transient error
182 * encountered during the computation itself.
183 */
184 public boolean isDirectlyTransient() {
185 return isDirectlyTransient;
186 }
187
188 /**
Nathan Harmata97731682015-12-09 23:36:22 +0000189 * Returns true iff the error is transitively transient, i.e. if retrying the same computation
190 * could lead to a different result.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100191 */
nharmatabea67e92017-06-16 00:26:27 +0200192 public boolean isTransitivelyTransient() {
193 return isTransitivelyTransient;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100194 }
195
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100196 /**
197 * Returns true iff the error is catastrophic, i.e. it should halt even for a keepGoing update()
198 * call.
199 */
200 public boolean isCatastrophic() {
201 return isCatastrophic;
202 }
Janak Ramakrishnandad0a102015-09-18 20:59:28 +0000203
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100204}