blob: 92738b0ac03c4d6f771d31105166949e18667e14 [file] [log] [blame]
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001// Copyright 2014 Google Inc. All rights reserved.
2//
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
16import com.google.common.base.Objects;
17import com.google.common.base.Preconditions;
18import com.google.common.collect.ImmutableMap;
19import com.google.common.collect.Iterables;
20import com.google.common.collect.Lists;
21
22import java.util.Collection;
23import java.util.Collections;
24import java.util.HashMap;
25import java.util.Map;
26
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000027import javax.annotation.Nullable;
28
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029/**
30 * The result of a Skyframe {@link Evaluator#eval} call. Will contain all the
31 * successfully evaluated values, retrievable through {@link #get}. As well, the {@link ErrorInfo}
32 * for the first value that failed to evaluate (in the non-keep-going case), or any remaining values
33 * that failed to evaluate (in the keep-going case) will be retrievable.
34 *
35 * @param <T> The type of the values that the caller has requested.
36 */
37public class EvaluationResult<T extends SkyValue> {
38
39 private final boolean hasError;
40
41 private final Map<SkyKey, T> resultMap;
42 private final Map<SkyKey, ErrorInfo> errorMap;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000043 private final WalkableGraph walkableGraph;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010044
45 /**
46 * Constructor for the "completed" case. Used only by {@link Builder}.
47 */
48 private EvaluationResult(Map<SkyKey, T> result, Map<SkyKey, ErrorInfo> errorMap,
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000049 boolean hasError, @Nullable WalkableGraph walkableGraph) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010050 Preconditions.checkState(errorMap.isEmpty() || hasError,
51 "result=%s, errorMap=%s", result, errorMap);
52 this.resultMap = Preconditions.checkNotNull(result);
53 this.errorMap = Preconditions.checkNotNull(errorMap);
54 this.hasError = hasError;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000055 this.walkableGraph = walkableGraph;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010056 }
57
58 /**
59 * Get a successfully evaluated value.
60 */
61 public T get(SkyKey key) {
62 Preconditions.checkNotNull(resultMap, key);
63 return resultMap.get(key);
64 }
65
66 /**
67 * @return Whether or not the eval successfully evaluated all requested values. Note that this
68 * may return true even if all values returned are available in get(). This happens if a top-level
69 * value depends transitively on some value that recovered from a {@link SkyFunctionException}.
70 */
71 public boolean hasError() {
72 return hasError;
73 }
74
75 /**
76 * @return All successfully evaluated {@link SkyValue}s.
77 */
78 public Collection<T> values() {
79 return Collections.unmodifiableCollection(resultMap.values());
80 }
81
82 /**
83 * Returns {@link Map} of {@link SkyKey}s to {@link ErrorInfo}. Note that currently some
84 * of the returned SkyKeys may not be the ones requested by the user. Moreover, the SkyKey
85 * is not necessarily the cause of the error -- it is just the value that was being evaluated
86 * when the error was discovered. For the cause of the error, use
87 * {@link ErrorInfo#getRootCauses()} on each ErrorInfo.
88 */
89 public Map<SkyKey, ErrorInfo> errorMap() {
90 return ImmutableMap.copyOf(errorMap);
91 }
92
93 /**
94 * @param key {@link SkyKey} to get {@link ErrorInfo} for.
95 */
96 public ErrorInfo getError(SkyKey key) {
97 return Preconditions.checkNotNull(errorMap, key).get(key);
98 }
99
100 /**
101 * @return Names of all values that were successfully evaluated.
102 */
103 public <S> Collection<? extends S> keyNames() {
104 return this.<S>getNames(resultMap.keySet());
105 }
106
107 @SuppressWarnings("unchecked")
108 private <S> Collection<? extends S> getNames(Collection<SkyKey> keys) {
109 Collection<S> names = Lists.newArrayListWithCapacity(keys.size());
110 for (SkyKey key : keys) {
111 names.add((S) key.argument());
112 }
113 return names;
114 }
115
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000116 @Nullable
117 public WalkableGraph getWalkableGraph() {
118 return walkableGraph;
119 }
120
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100121 /**
122 * Returns some error info. Convenience method equivalent to
123 * Iterables.getFirst({@link #errorMap()}, null).getValue().
124 */
125 public ErrorInfo getError() {
126 return Iterables.getFirst(errorMap.entrySet(), null).getValue();
127 }
128
129 @Override
130 @SuppressWarnings("deprecation")
131 public String toString() {
132 return Objects.toStringHelper(this) // MoreObjects is not in Guava
133 .add("hasError", hasError)
134 .add("errorMap", errorMap)
135 .add("resultMap", resultMap)
136 .toString();
137 }
138
139 public static <T extends SkyValue> Builder<T> builder() {
140 return new Builder<>();
141 }
142
143 /**
144 * Builder for {@link EvaluationResult}.
145 *
146 * <p>This is intended only for use in alternative {@code MemoizingEvaluator} implementations.
147 */
148 public static class Builder<T extends SkyValue> {
149 private final Map<SkyKey, T> result = new HashMap<>();
150 private final Map<SkyKey, ErrorInfo> errors = new HashMap<>();
151 private boolean hasError = false;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000152 private WalkableGraph walkableGraph = null;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100153
154 @SuppressWarnings("unchecked")
155 public Builder<T> addResult(SkyKey key, SkyValue value) {
156 result.put(key, Preconditions.checkNotNull((T) value, key));
157 return this;
158 }
159
160 public Builder<T> addError(SkyKey key, ErrorInfo error) {
161 errors.put(key, Preconditions.checkNotNull(error, key));
162 return this;
163 }
164
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000165 public Builder<T> setWalkableGraph(WalkableGraph walkableGraph) {
166 this.walkableGraph = walkableGraph;
167 return this;
168 }
169
170 public Builder<T> mergeFrom(EvaluationResult<T> otherResult) {
171 result.putAll(otherResult.resultMap);
172 errors.putAll(otherResult.errorMap);
173 hasError |= otherResult.hasError;
174 return this;
175 }
176
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100177 public EvaluationResult<T> build() {
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000178 return new EvaluationResult<>(result, errors, hasError, walkableGraph);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100179 }
180
181 public void setHasError(boolean hasError) {
182 this.hasError = hasError;
183 }
184 }
185}