blob: 0605f22ec3101a7a984eae0165791167732ce1b0 [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
shahan21e26002018-10-01 08:25:02 -070016import com.google.common.base.Predicates;
17import com.google.common.collect.Iterables;
Nathan Harmatae9552872015-04-01 21:53:06 +000018import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
shahan5de60f12018-12-07 17:06:38 -080019import com.google.devtools.build.lib.util.GroupedList;
shreyax26e72802018-03-26 09:04:48 -070020import com.google.errorprone.annotations.CanIgnoreReturnValue;
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000021import java.util.Map;
shahan21e26002018-10-01 08:25:02 -070022import java.util.Set;
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000023import javax.annotation.Nullable;
24
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000025/**
26 * A graph that exposes its entries and structure, for use by classes that must traverse it.
27 *
28 * <p>Certain graph implementations can throw {@link InterruptedException} when trying to retrieve
29 * node entries. Such exceptions should not be caught locally -- they should be allowed to propagate
30 * up.
31 */
Nathan Harmatae9552872015-04-01 21:53:06 +000032@ThreadSafe
Janak Ramakrishnancc7712f2016-07-08 17:38:27 +000033public interface QueryableGraph {
Nathan Harmata3b47b1f2016-07-26 18:41:41 +000034 /**
35 * Returns the node with the given {@code key}, or {@code null} if the node does not exist.
36 *
37 * @param requestor if non-{@code null}, the node on behalf of which {@code key} is being
38 * requested.
39 * @param reason the reason the node is being requested.
40 */
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000041 @Nullable
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000042 NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key) throws InterruptedException;
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000043
44 /**
Janak Ramakrishnan2553c842016-07-08 18:43:37 +000045 * Fetches all the given nodes. Returns a map {@code m} such that, for all {@code k} in {@code
46 * keys}, {@code m.get(k).equals(e)} iff {@code get(k) == e} and {@code e != null}, and {@code
Nathan Harmatac55fe152016-08-02 18:13:28 +000047 * !m.containsKey(k)} iff {@code get(k) == null}.
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000048 *
Nathan Harmata3b47b1f2016-07-26 18:41:41 +000049 * @param requestor if non-{@code null}, the node on behalf of which the given {@code keys} are
50 * being requested.
51 * @param reason the reason the nodes are being requested.
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000052 */
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000053 Map<SkyKey, ? extends NodeEntry> getBatch(
ulfjackbe83f132017-07-18 18:12:09 +020054 @Nullable SkyKey requestor, Reason reason, Iterable<? extends SkyKey> keys)
55 throws InterruptedException;
Nathan Harmata3b47b1f2016-07-26 18:41:41 +000056
57 /**
shreyax26e72802018-03-26 09:04:48 -070058 * A version of {@link #getBatch} that returns an {@link InterruptibleSupplier} to possibly
59 * retrieve the results later.
shreyaxa6679ae2018-03-02 15:59:46 -080060 */
shreyax26e72802018-03-26 09:04:48 -070061 @CanIgnoreReturnValue
62 default InterruptibleSupplier<Map<SkyKey, ? extends NodeEntry>> getBatchAsync(
shreyaxa6679ae2018-03-02 15:59:46 -080063 @Nullable SkyKey requestor, Reason reason, Iterable<? extends SkyKey> keys) {
shreyax26e72802018-03-26 09:04:48 -070064 return InterruptibleSupplier.Memoize.of(() -> getBatch(requestor, reason, keys));
shreyaxa6679ae2018-03-02 15:59:46 -080065 }
66
shahan21e26002018-10-01 08:25:02 -070067 /**
68 * Optimistically prefetches dependencies.
69 *
shahan5de60f12018-12-07 17:06:38 -080070 * @see PrefetchDepsRequest
shahan21e26002018-10-01 08:25:02 -070071 */
shahan5de60f12018-12-07 17:06:38 -080072 default void prefetchDeps(PrefetchDepsRequest request) throws InterruptedException {
73 if (request.oldDeps.isEmpty()) {
74 return;
75 }
76 request.excludedKeys = request.depKeys.toSet();
shahan21e26002018-10-01 08:25:02 -070077 getBatchAsync(
shahan5de60f12018-12-07 17:06:38 -080078 request.requestor,
shahan21e26002018-10-01 08:25:02 -070079 Reason.PREFETCH,
shahan5de60f12018-12-07 17:06:38 -080080 Iterables.filter(request.oldDeps, Predicates.not(Predicates.in(request.excludedKeys))));
shahan52339932018-09-16 10:33:59 -070081 }
82
Googler039630a2018-12-26 09:41:12 -080083 /** Checks whether this graph stores reverse dependencies. */
84 default boolean storesReverseDeps() {
85 return true;
86 }
87
shreyaxa6679ae2018-03-02 15:59:46 -080088 /**
Nathan Harmata3b47b1f2016-07-26 18:41:41 +000089 * The reason that a node is being looked up in the Skyframe graph.
90 *
91 * <p>Alternate graph implementations may wish to make use of this information.
92 */
93 enum Reason {
94 /**
Nathan Harmatac55fe152016-08-02 18:13:28 +000095 * The node is being fetched in order to see if it needs to be evaluated or because it was just
96 * evaluated, but *not* because it was just requested during evaluation of a SkyFunction
97 * (see {@link #DEP_REQUESTED}).
98 */
99 PRE_OR_POST_EVALUATION,
100
101 /**
Nathan Harmata3b47b1f2016-07-26 18:41:41 +0000102 * The node is being looked up as part of the prefetch step before evaluation of a SkyFunction.
103 */
104 PREFETCH,
105
106 /**
Nathan Harmatac55fe152016-08-02 18:13:28 +0000107 * The node is being fetched because it is about to be evaluated, but *not* because it was just
108 * requested during evaluation of a SkyFunction (see {@link #DEP_REQUESTED}).
Nathan Harmata3b47b1f2016-07-26 18:41:41 +0000109 */
110 EVALUATION,
111
112 /** The node is being looked up because it was requested during evaluation of a SkyFunction. */
113 DEP_REQUESTED,
114
115 /** The node is being looked up during the invalidation phase of Skyframe evaluation. */
116 INVALIDATION,
117
118 /** The node is being looked up during the cycle checking phase of Skyframe evaluation. */
119 CYCLE_CHECKING,
120
121 /** The node is being looked up so that an rdep can be added to it. */
122 RDEP_ADDITION,
123
124 /** The node is being looked up so that an rdep can be removed from it. */
125 RDEP_REMOVAL,
126
Shreya Bhattarai7fd3f2c52017-02-09 01:59:28 +0000127 /** The node is being looked up for any graph clean-up effort that may be necessary. */
128 CLEAN_UP,
129
Nathan Harmata3b47b1f2016-07-26 18:41:41 +0000130 /** The node is being looked up so it can be enqueued for evaluation or change pruning. */
131 ENQUEUING_CHILD,
132
133 /**
134 * The node is being looked up so that it can be signaled that a dependency is now complete.
135 */
136 SIGNAL_DEP,
137
138 /**
139 * The node is being looking up as part of the error bubbling phase of fail-fast Skyframe
140 * evaluation.
141 */
142 ERROR_BUBBLING,
143
Nathan Harmatac55fe152016-08-02 18:13:28 +0000144 /** The node is being looked up merely for an existence check. */
145 EXISTENCE_CHECKING,
146
shreyax26e72802018-03-26 09:04:48 -0700147 /** The node is being looked up merely to see if it is done or not. */
148 DONE_CHECKING,
149
Nathan Harmatac55fe152016-08-02 18:13:28 +0000150 /**
151 * The node is being looked up to service {@link WalkableGraph#getValue},
152 * {@link WalkableGraph#getException}, {@link WalkableGraph#getMissingAndExceptions}, or
153 * {@link WalkableGraph#getSuccessfulValues}.
154 */
155 WALKABLE_GRAPH_VALUE,
156
157 /** The node is being looked up to service {@link WalkableGraph#getDirectDeps}. */
158 WALKABLE_GRAPH_DEPS,
159
160 /** The node is being looked up to service {@link WalkableGraph#getReverseDeps}. */
161 WALKABLE_GRAPH_RDEPS,
162
Nathan Harmata3b47b1f2016-07-26 18:41:41 +0000163 /** Some other reason than one of the above. */
164 OTHER,
165 }
shahan5de60f12018-12-07 17:06:38 -0800166
167 /** Parameters for {@link QueryableGraph#prefetchDeps}. */
168 static class PrefetchDepsRequest {
169 public final SkyKey requestor;
170
171 /**
172 * Old dependencies to prefetch.
173 *
174 * <p>The implementation might ignore this if it has another way to determine the dependencies.
175 */
176 public final Set<SkyKey> oldDeps;
177
178 /**
179 * Direct deps that will be subsequently fetched and therefore should be excluded from
180 * prefetching.
181 */
182 public final GroupedList<SkyKey> depKeys;
183
184 /**
185 * Output parameter: {@code depKeys} as a set.
186 *
187 * <p>The implementation might set this, in which case, the caller could reuse it.
188 */
189 @Nullable public Set<SkyKey> excludedKeys = null;
190
191 public PrefetchDepsRequest(SkyKey requestor, Set<SkyKey> oldDeps, GroupedList<SkyKey> depKeys) {
192 this.requestor = requestor;
193 this.oldDeps = oldDeps;
194 this.depKeys = depKeys;
195 }
196 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100197}