blob: d7b53c8c90e7cc5330bb183a3ed1bab51c7935e3 [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
13package com.google.devtools.build.skyframe;
14
janakr4089f8b2018-05-22 20:08:41 -070015import com.google.common.annotations.VisibleForTesting;
16import com.google.common.base.MoreObjects;
tomlua155b532017-11-08 20:12:47 +010017import com.google.common.base.Preconditions;
janakr4089f8b2018-05-22 20:08:41 -070018import com.google.common.collect.Iterables;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010019import com.google.devtools.build.lib.collect.nestedset.NestedSet;
20import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
21import com.google.devtools.build.lib.collect.nestedset.Order;
Klaus Aehligda0a7012017-06-14 13:40:23 +020022import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010023import java.util.Objects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010024import javax.annotation.Nullable;
25
26/**
27 * Encapsulation of data stored by {@link NodeEntry} when the value has finished building.
28 *
29 * <p>This is intended only for use in alternative {@code MemoizingEvaluator} implementations.
30 */
31public abstract class ValueWithMetadata implements SkyValue {
32 protected final SkyValue value;
33
34 private static final NestedSet<TaggedEvents> NO_EVENTS =
35 NestedSetBuilder.<TaggedEvents>emptySet(Order.STABLE_ORDER);
36
Klaus Aehligda0a7012017-06-14 13:40:23 +020037 private static final NestedSet<Postable> NO_POSTS =
38 NestedSetBuilder.<Postable>emptySet(Order.STABLE_ORDER);
39
janakr4089f8b2018-05-22 20:08:41 -070040 private ValueWithMetadata(SkyValue value) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010041 this.value = value;
42 }
43
Klaus Aehligda0a7012017-06-14 13:40:23 +020044 /**
45 * Builds a value entry value that has an error (and no value value).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010046 *
47 * <p>This is intended only for use in alternative {@code MemoizingEvaluator} implementations.
48 */
Klaus Aehligda0a7012017-06-14 13:40:23 +020049 public static ValueWithMetadata error(
50 ErrorInfo errorInfo,
51 NestedSet<TaggedEvents> transitiveEvents,
52 NestedSet<Postable> transitivePostables) {
janakr4089f8b2018-05-22 20:08:41 -070053 return (ValueWithMetadata) normal(null, errorInfo, transitiveEvents, transitivePostables);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010054 }
55
56 /**
janakr4089f8b2018-05-22 20:08:41 -070057 * Builds a SkyValue that has a value, and possibly an error, and possibly events/postables. If it
58 * has only a value, returns just the value in order to save memory.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059 *
Janak Ramakrishnan91ad93b2015-08-24 17:48:34 +000060 * <p>This is public only for use in alternative {@code MemoizingEvaluator} implementations.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010061 */
Janak Ramakrishnan91ad93b2015-08-24 17:48:34 +000062 public static SkyValue normal(
63 @Nullable SkyValue value,
64 @Nullable ErrorInfo errorInfo,
Klaus Aehligda0a7012017-06-14 13:40:23 +020065 NestedSet<TaggedEvents> transitiveEvents,
66 NestedSet<Postable> transitivePostables) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010067 Preconditions.checkState(value != null || errorInfo != null,
68 "Value and error cannot both be null");
69 if (errorInfo == null) {
Klaus Aehligda0a7012017-06-14 13:40:23 +020070 return (transitiveEvents.isEmpty() && transitivePostables.isEmpty())
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010071 ? value
Klaus Aehligda0a7012017-06-14 13:40:23 +020072 : ValueWithEvents.createValueWithEvents(value, transitiveEvents, transitivePostables);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010073 }
Klaus Aehligda0a7012017-06-14 13:40:23 +020074 return new ErrorInfoValue(errorInfo, value, transitiveEvents, transitivePostables);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010075 }
76
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010077 @Nullable SkyValue getValue() {
78 return value;
79 }
80
81 @Nullable
82 abstract ErrorInfo getErrorInfo();
83
Nathan Harmatacba3d7e2015-03-04 23:10:06 +000084 public abstract NestedSet<TaggedEvents> getTransitiveEvents();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010085
Klaus Aehligda0a7012017-06-14 13:40:23 +020086 public abstract NestedSet<Postable> getTransitivePostables();
87
Nathan Harmatacba3d7e2015-03-04 23:10:06 +000088 /** Implementation of {@link ValueWithMetadata} for the value case. */
janakr4089f8b2018-05-22 20:08:41 -070089 @VisibleForTesting
Eric Fellheimer26b3d852015-11-19 02:16:24 +000090 public static class ValueWithEvents extends ValueWithMetadata {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010091 private final NestedSet<TaggedEvents> transitiveEvents;
Klaus Aehligda0a7012017-06-14 13:40:23 +020092 private final NestedSet<Postable> transitivePostables;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010093
Klaus Aehligda0a7012017-06-14 13:40:23 +020094 private ValueWithEvents(
95 SkyValue value,
96 NestedSet<TaggedEvents> transitiveEvents,
97 NestedSet<Postable> transitivePostables) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010098 super(Preconditions.checkNotNull(value));
99 this.transitiveEvents = Preconditions.checkNotNull(transitiveEvents);
Klaus Aehligda0a7012017-06-14 13:40:23 +0200100 this.transitivePostables = Preconditions.checkNotNull(transitivePostables);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100101 }
102
janakr4089f8b2018-05-22 20:08:41 -0700103 private static ValueWithEvents createValueWithEvents(
Klaus Aehligda0a7012017-06-14 13:40:23 +0200104 SkyValue value,
105 NestedSet<TaggedEvents> transitiveEvents,
106 NestedSet<Postable> transitivePostables) {
Eric Fellheimer26b3d852015-11-19 02:16:24 +0000107 if (value instanceof NotComparableSkyValue) {
Klaus Aehligda0a7012017-06-14 13:40:23 +0200108 return new NotComparableValueWithEvents(value, transitiveEvents, transitivePostables);
Eric Fellheimer26b3d852015-11-19 02:16:24 +0000109 } else {
Klaus Aehligda0a7012017-06-14 13:40:23 +0200110 return new ValueWithEvents(value, transitiveEvents, transitivePostables);
Eric Fellheimer26b3d852015-11-19 02:16:24 +0000111 }
112 }
113
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100114 @Nullable
115 @Override
116 ErrorInfo getErrorInfo() { return null; }
117
118 @Override
Nathan Harmatacba3d7e2015-03-04 23:10:06 +0000119 public NestedSet<TaggedEvents> getTransitiveEvents() { return transitiveEvents; }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100120
Klaus Aehligda0a7012017-06-14 13:40:23 +0200121 @Override
122 public NestedSet<Postable> getTransitivePostables() {
123 return transitivePostables;
124 }
125
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100126 /**
127 * We override equals so that if the same value is written to a {@link NodeEntry} twice, it can
128 * verify that the two values are equal, and avoid incrementing its version.
129 */
130 @Override
131 public boolean equals(Object o) {
132 if (this == o) {
133 return true;
134 }
135 if (o == null || getClass() != o.getClass()) {
136 return false;
137 }
138
139 ValueWithEvents that = (ValueWithEvents) o;
140
141 // Shallow equals is a middle ground between using default equals, which might miss
142 // nested sets with the same elements, and deep equality checking, which would be expensive.
143 // All three choices are sound, since shallow equals and default equals are more
144 // conservative than deep equals. Using shallow equals means that we may unnecessarily
145 // consider some values unequal that are actually equal, but this is still a net win over
146 // deep equals.
Klaus Aehligda0a7012017-06-14 13:40:23 +0200147 return value.equals(that.value)
148 && transitiveEvents.shallowEquals(that.transitiveEvents)
149 && transitivePostables.shallowEquals(that.transitivePostables);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100150 }
151
152 @Override
153 public int hashCode() {
Klaus Aehligda0a7012017-06-14 13:40:23 +0200154 return 31 * value.hashCode()
155 + transitiveEvents.shallowHashCode()
156 + 3 * transitivePostables.shallowHashCode();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100157 }
158
159 @Override
janakr4089f8b2018-05-22 20:08:41 -0700160 public String toString() {
161 return MoreObjects.toStringHelper(this)
162 .add("value", value)
163 .add("transitiveEvents size", Iterables.size(transitiveEvents))
164 .add("transitivePostables size", Iterables.size(transitivePostables))
165 .toString();
166 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100167 }
168
Eric Fellheimer26b3d852015-11-19 02:16:24 +0000169 private static final class NotComparableValueWithEvents extends ValueWithEvents
170 implements NotComparableSkyValue {
Klaus Aehligda0a7012017-06-14 13:40:23 +0200171 private NotComparableValueWithEvents(
172 SkyValue value,
173 NestedSet<TaggedEvents> transitiveEvents,
174 NestedSet<Postable> transitivePostables) {
175 super(value, transitiveEvents, transitivePostables);
Eric Fellheimer26b3d852015-11-19 02:16:24 +0000176 }
177 }
178
179 /**
180 * Implementation of {@link ValueWithMetadata} for the error case.
181 *
janakr9b0b9872018-06-19 09:45:57 -0700182 * <p>Mark NotComparableSkyValue because it's unlikely that re-evaluation gives the same error.
Eric Fellheimer26b3d852015-11-19 02:16:24 +0000183 */
184 private static final class ErrorInfoValue extends ValueWithMetadata
janakr9b0b9872018-06-19 09:45:57 -0700185 implements NotComparableSkyValue {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100186
187 private final ErrorInfo errorInfo;
188 private final NestedSet<TaggedEvents> transitiveEvents;
Klaus Aehligda0a7012017-06-14 13:40:23 +0200189 private final NestedSet<Postable> transitivePostables;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100190
Klaus Aehligda0a7012017-06-14 13:40:23 +0200191 public ErrorInfoValue(
192 ErrorInfo errorInfo,
193 @Nullable SkyValue value,
194 NestedSet<TaggedEvents> transitiveEvents,
195 NestedSet<Postable> transitivePostables) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100196 super(value);
197 this.errorInfo = Preconditions.checkNotNull(errorInfo);
198 this.transitiveEvents = Preconditions.checkNotNull(transitiveEvents);
Klaus Aehligda0a7012017-06-14 13:40:23 +0200199 this.transitivePostables = Preconditions.checkNotNull(transitivePostables);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100200 }
201
202 @Nullable
203 @Override
204 ErrorInfo getErrorInfo() { return errorInfo; }
205
206 @Override
Nathan Harmatacba3d7e2015-03-04 23:10:06 +0000207 public NestedSet<TaggedEvents> getTransitiveEvents() { return transitiveEvents; }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100208
209 @Override
Klaus Aehligda0a7012017-06-14 13:40:23 +0200210 public NestedSet<Postable> getTransitivePostables() {
211 return transitivePostables;
212 }
213
214 @Override
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100215 public boolean equals(Object o) {
216 if (this == o) {
217 return true;
218 }
219 if (o == null || getClass() != o.getClass()) {
220 return false;
221 }
222
223 ErrorInfoValue that = (ErrorInfoValue) o;
224
225 // Shallow equals is a middle ground between using default equals, which might miss
226 // nested sets with the same elements, and deep equality checking, which would be expensive.
227 // All three choices are sound, since shallow equals and default equals are more
228 // conservative than deep equals. Using shallow equals means that we may unnecessarily
229 // consider some values unequal that are actually equal, but this is still a net win over
230 // deep equals.
231 return Objects.equals(this.value, that.value)
232 && Objects.equals(this.errorInfo, that.errorInfo)
Klaus Aehligda0a7012017-06-14 13:40:23 +0200233 && transitiveEvents.shallowEquals(that.transitiveEvents)
234 && transitivePostables.shallowEquals(that.transitivePostables);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100235 }
236
237 @Override
238 public int hashCode() {
Klaus Aehligda0a7012017-06-14 13:40:23 +0200239 return 31 * Objects.hash(value, errorInfo)
240 + transitiveEvents.shallowHashCode()
241 + 3 * transitivePostables.shallowHashCode();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100242 }
243
244 @Override
245 public String toString() {
246 StringBuilder result = new StringBuilder();
247 if (value != null) {
248 result.append("Value: ").append(value);
249 }
250 if (errorInfo != null) {
251 if (result.length() > 0) {
252 result.append("; ");
253 }
254 result.append("Error: ").append(errorInfo);
255 }
256 return result.toString();
257 }
258 }
259
shahanf89e0632018-08-31 11:32:42 -0700260 @Nullable
Nathan Harmatacba3d7e2015-03-04 23:10:06 +0000261 public static SkyValue justValue(SkyValue value) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100262 if (value instanceof ValueWithMetadata) {
263 return ((ValueWithMetadata) value).getValue();
264 }
265 return value;
266 }
267
Nathan Harmatacba3d7e2015-03-04 23:10:06 +0000268 public static ValueWithMetadata wrapWithMetadata(SkyValue value) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100269 if (value instanceof ValueWithMetadata) {
270 return (ValueWithMetadata) value;
271 }
Klaus Aehligda0a7012017-06-14 13:40:23 +0200272 return ValueWithEvents.createValueWithEvents(value, NO_EVENTS, NO_POSTS);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100273 }
274
275 @Nullable
276 public static ErrorInfo getMaybeErrorInfo(SkyValue value) {
277 if (value.getClass() == ErrorInfoValue.class) {
278 return ((ValueWithMetadata) value).getErrorInfo();
279 }
280 return null;
Janak Ramakrishnan1fec40d2016-03-21 19:32:17 +0000281 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100282
janakr7574d842018-08-14 21:38:51 -0700283 @VisibleForTesting
284 public static NestedSet<TaggedEvents> getEvents(SkyValue value) {
Janak Ramakrishnan1fec40d2016-03-21 19:32:17 +0000285 if (value instanceof ValueWithMetadata) {
286 return ((ValueWithMetadata) value).getTransitiveEvents();
287 }
288 return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100289 }
Klaus Aehligda0a7012017-06-14 13:40:23 +0200290
291 static NestedSet<Postable> getPosts(SkyValue value) {
292 if (value instanceof ValueWithMetadata) {
293 return ((ValueWithMetadata) value).getTransitivePostables();
294 }
295 return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
296 }
Nathan Harmatacba3d7e2015-03-04 23:10:06 +0000297}