blob: 585b4e1fea5ecce3f386b27547d61b23d8f1a013 [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
Nathan Harmatab408f9e2015-02-10 02:13:05 +000016import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010017import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper;
18import com.google.devtools.build.lib.util.Pair;
19
20import java.util.Collection;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import java.util.Set;
22
23import javax.annotation.Nullable;
24
25/**
Nathan Harmatab408f9e2015-02-10 02:13:05 +000026 * A node in the graph. All operations on this class are thread-safe.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027 *
Nathan Harmatab408f9e2015-02-10 02:13:05 +000028 * <p>This interface is public only for the benefit of alternative graph implementations outside of
29 * the package.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010030 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +000031public interface NodeEntry {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032 /**
33 * Return code for {@link #addReverseDepAndCheckIfDone(SkyKey)}.
34 */
35 enum DependencyState {
36 /** The node is done. */
37 DONE,
38
39 /**
40 * The node was just created and needs to be scheduled for its first evaluation pass. The
41 * evaluator is responsible for signaling the reverse dependency node.
42 */
43 NEEDS_SCHEDULING,
44
45 /**
46 * The node was already created, but isn't done yet. The evaluator is responsible for
47 * signaling the reverse dependency node.
48 */
49 ADDED_DEP;
50 }
51
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010052 /**
Nathan Harmatab408f9e2015-02-10 02:13:05 +000053 * Return code for {@link #getDirtyState}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010054 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +000055 enum DirtyState {
56 /**
57 * The node's dependencies need to be checked to see if it needs to be rebuilt. The
58 * dependencies must be obtained through calls to {@link #getNextDirtyDirectDeps} and checked.
59 */
60 CHECK_DEPENDENCIES,
61 /**
62 * All of the node's dependencies are unchanged, and the value itself was not marked changed,
63 * so its current value is still valid -- it need not be rebuilt.
64 */
65 VERIFIED_CLEAN,
66 /**
67 * A rebuilding is required or in progress, because either the node itself changed or one of
68 * its dependencies did.
69 */
70 REBUILDING
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010071 }
72
Nathan Harmatab408f9e2015-02-10 02:13:05 +000073 boolean keepEdges();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010074
75 /** Returns whether the entry has been built and is finished evaluating. */
Nathan Harmatab408f9e2015-02-10 02:13:05 +000076 @ThreadSafe
77 boolean isDone();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010078
79 /**
80 * Returns the value stored in this entry. This method may only be called after the evaluation of
81 * this node is complete, i.e., after {@link #setValue} has been called.
82 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +000083 @ThreadSafe
84 SkyValue getValue();
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000085
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010086
87 /**
88 * Returns the {@link SkyValue} for this entry and the metadata associated with it (Like events
89 * and errors). This method may only be called after the evaluation of this node is complete,
90 * i.e., after {@link #setValue} has been called.
91 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +000092 @ThreadSafe
93 ValueWithMetadata getValueWithMetadata();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010094
95 /**
96 * Returns the value, even if dirty or changed. Returns null otherwise.
97 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +000098 @ThreadSafe
99 SkyValue toValue();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100100
101 /**
102 * Returns an immutable iterable of the direct deps of this node. This method may only be called
103 * after the evaluation of this node is complete, i.e., after {@link #setValue} has been called.
104 *
105 * <p>This method is not very efficient, but is only be called in limited circumstances --
106 * when the node is about to be deleted, or when the node is expected to have no direct deps (in
107 * which case the overhead is not so bad). It should not be called repeatedly for the same node,
108 * since each call takes time proportional to the number of direct deps of the node.
109 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000110 @ThreadSafe
111 Iterable<SkyKey> getDirectDeps();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100112
113 /**
114 * Returns the error, if any, associated to this node. This method may only be called after
115 * the evaluation of this node is complete, i.e., after {@link #setValue} has been called.
116 */
117 @Nullable
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000118 @ThreadSafe
119 ErrorInfo getErrorInfo();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100120
121 /**
122 * Returns the set of reverse deps that have been declared so far this build. Only for use in
123 * debugging and when bubbling errors up in the --nokeep_going case, where we need to know what
124 * parents this entry has.
125 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000126 @ThreadSafe
127 Set<SkyKey> getInProgressReverseDeps();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100128
129 /**
130 * Transitions the node from the EVALUATING to the DONE state and simultaneously sets it to the
131 * given value and error state. It then returns the set of reverse dependencies that need to be
132 * signaled.
133 *
134 * <p>This is an atomic operation to avoid a race where two threads work on two nodes, where one
135 * node depends on another (b depends on a). When a finishes, it signals <b>exactly</b> the set
136 * of reverse dependencies that are registered at the time of the {@code setValue} call. If b
137 * comes in before a, it is signaled (and re-scheduled) by a, otherwise it needs to do that
138 * itself.
139 *
140 * <p>{@code version} indicates the graph version at which this node is being written. If the
141 * entry determines that the new value is equal to the previous value, the entry will keep its
142 * current version. Callers can query that version to see if the node considers its value to have
143 * changed.
144 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000145 @ThreadSafe
146 Set<SkyKey> setValue(SkyValue value, Version version);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100147
148 /**
149 * Queries if the node is done and adds the given key as a reverse dependency. The return code
150 * indicates whether a) the node is done, b) the reverse dependency is the first one, so the
151 * node needs to be scheduled, or c) the reverse dependency was added, and the node does not
152 * need to be scheduled.
153 *
154 * <p>This method <b>must</b> be called before any processing of the entry. This encourages
155 * callers to check that the entry is ready to be processed.
156 *
157 * <p>Adding the dependency and checking if the node needs to be scheduled is an atomic operation
158 * to avoid a race where two threads work on two nodes, where one depends on the other (b depends
159 * on a). In that case, we need to ensure that b is re-scheduled exactly once when a is done.
160 * However, a may complete first, in which case b has to re-schedule itself. Also see {@link
161 * #setValue}.
162 *
163 * <p>If the parameter is {@code null}, then no reverse dependency is added, but we still check
164 * if the node needs to be scheduled.
165 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000166 @ThreadSafe
167 DependencyState addReverseDepAndCheckIfDone(SkyKey reverseDep);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100168
169 /**
170 * Removes a reverse dependency.
171 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000172 @ThreadSafe
173 void removeReverseDep(SkyKey reverseDep);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100174
175 /**
176 * Returns a copy of the set of reverse dependencies. Note that this introduces a potential
177 * check-then-act race; {@link #removeReverseDep} may fail for a key that is returned here.
178 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000179 @ThreadSafe
180 Iterable<SkyKey> getReverseDeps();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100181
182 /**
183 * Tell this node that one of its dependencies is now done. Callers must check the return value,
184 * and if true, they must re-schedule this node for evaluation. Equivalent to
185 * {@code #signalDep(Long.MAX_VALUE)}. Since this entry's version is less than
186 * {@link Long#MAX_VALUE}, informing this entry that a child of it has version
187 * {@link Long#MAX_VALUE} will force it to re-evaluate.
188 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000189 @ThreadSafe
190 boolean signalDep();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100191
192 /**
193 * Tell this entry that one of its dependencies is now done. Callers must check the return value,
194 * and if true, they must re-schedule this node for evaluation.
195 *
196 * @param childVersion If this entry {@link #isDirty()} and {@code childVersion} is not at most
197 * {@link #getVersion()}, then this entry records that one of its children has changed since it
198 * was last evaluated (namely, it was last evaluated at version {@link #getVersion()} and the
199 * child was last evaluated at {@code childVersion}. Thus, the next call to
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000200 * {@link #getDirtyState()} will return {@link DirtyState#REBUILDING}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100201 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000202 @ThreadSafe
203 boolean signalDep(Version childVersion);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100204
205 /**
206 * Returns true if the entry is marked dirty, meaning that at least one of its transitive
207 * dependencies is marked changed.
208 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000209 @ThreadSafe
210 boolean isDirty();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100211
212 /**
213 * Returns true if the entry is marked changed, meaning that it must be re-evaluated even if its
214 * dependencies' values have not changed.
215 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000216 @ThreadSafe
217 boolean isChanged();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100218
219 /**
220 * Marks this node dirty, or changed if {@code isChanged} is true. The node is put in the
221 * just-created state. It will be re-evaluated if necessary during the evaluation phase,
222 * but if it has not changed, it will not force a re-evaluation of its parents.
223 *
224 * @return The direct deps and value of this entry, or null if the entry has already been marked
225 * dirty. In the latter case, the caller should abort its handling of this node, since another
226 * thread is already dealing with it.
227 */
228 @Nullable
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000229 @ThreadSafe
230 Pair<? extends Iterable<SkyKey>, ? extends SkyValue> markDirty(boolean isChanged);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100231
232 /**
233 * Marks this entry as up-to-date at this version.
234 *
235 * @return {@link Set} of reverse dependencies to signal that this node is done.
236 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000237 @ThreadSafe
238 Set<SkyKey> markClean();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100239
240 /**
241 * Forces this node to be reevaluated, even if none of its dependencies are known to have
242 * changed.
243 *
244 * <p>Used when an external caller has reason to believe that re-evaluating may yield a new
245 * result. This method should not be used if one of the normal deps of this node has changed,
246 * the usual change-pruning process should work in that case.
247 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000248 @ThreadSafe
249 void forceRebuild();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100250
251 /**
252 * Gets the current version of this entry.
253 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000254 @ThreadSafe
255 Version getVersion();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100256
257 /**
258 * Gets the current state of checking this dirty entry to see if it must be re-evaluated. Must be
259 * called each time evaluation of a dirty entry starts to find the proper action to perform next,
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000260 * as enumerated by {@link NodeEntry.DirtyState}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100261 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000262 @ThreadSafe
263 NodeEntry.DirtyState getDirtyState();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100264
265 /**
266 * Should only be called if the entry is dirty. During the examination to see if the entry must be
267 * re-evaluated, this method returns the next group of children to be checked. Callers should
268 * have already called {@link #getDirtyState} and received a return value of
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000269 * {@link DirtyState#CHECK_DEPENDENCIES} before calling this method -- any other
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100270 * return value from {@link #getDirtyState} means that this method must not be called, since
271 * whether or not the node needs to be rebuilt is already known.
272 *
273 * <p>Deps are returned in groups. The deps in each group were requested in parallel by the
274 * {@code SkyFunction} last build, meaning independently of the values of any other deps in this
275 * group (although possibly depending on deps in earlier groups). Thus the caller may check all
276 * the deps in this group in parallel, since the deps in all previous groups are verified
277 * unchanged. See {@link SkyFunction.Environment#getValues} for more on dependency groups.
278 *
279 * <p>The caller should register these as deps of this entry using {@link #addTemporaryDirectDeps}
280 * before checking them.
281 *
282 * @see BuildingState#getNextDirtyDirectDeps()
283 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000284 @ThreadSafe
285 Collection<SkyKey> getNextDirtyDirectDeps();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100286
287 /**
288 * Returns the set of direct dependencies. This may only be called while the node is being
289 * evaluated, that is, before {@link #setValue} and after {@link #markDirty}.
290 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000291 @ThreadSafe
292 Set<SkyKey> getTemporaryDirectDeps();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100293
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000294 @ThreadSafe
295 boolean noDepsLastBuild();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100296
297 /**
298 * Remove dep from direct deps. This should only be called if this entry is about to be
299 * committed as a cycle node, but some of its children were not checked for cycles, either
300 * because the cycle was discovered before some children were checked; some children didn't have a
301 * chance to finish before the evaluator aborted; or too many cycles were found when it came time
302 * to check the children.
303 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000304 @ThreadSafe
305 void removeUnfinishedDeps(Set<SkyKey> unfinishedDeps);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100306
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000307 @ThreadSafe
308 void addTemporaryDirectDeps(GroupedListHelper<SkyKey> helper);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100309
310 /**
311 * Returns true if the node is ready to be evaluated, i.e., it has been signaled exactly as many
312 * times as it has temporary dependencies. This may only be called while the node is being
313 * evaluated, that is, before {@link #setValue} and after {@link #markDirty}.
314 */
Nathan Harmatab408f9e2015-02-10 02:13:05 +0000315 @ThreadSafe
316 boolean isReady();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100317}