blob: d3a0c4336f2b3b694260aac0446b6d3f9c53efe5 [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;
Googler407d3932019-05-16 15:13:59 -070019import com.google.devtools.build.lib.supplier.InterruptibleSupplier;
20import com.google.devtools.build.lib.supplier.MemoizingInterruptibleSupplier;
shahan5de60f12018-12-07 17:06:38 -080021import com.google.devtools.build.lib.util.GroupedList;
shreyax26e72802018-03-26 09:04:48 -070022import com.google.errorprone.annotations.CanIgnoreReturnValue;
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000023import java.util.Map;
shahan21e26002018-10-01 08:25:02 -070024import java.util.Set;
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000025import javax.annotation.Nullable;
26
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000027/**
28 * A graph that exposes its entries and structure, for use by classes that must traverse it.
29 *
30 * <p>Certain graph implementations can throw {@link InterruptedException} when trying to retrieve
31 * node entries. Such exceptions should not be caught locally -- they should be allowed to propagate
32 * up.
33 */
Nathan Harmatae9552872015-04-01 21:53:06 +000034@ThreadSafe
Janak Ramakrishnancc7712f2016-07-08 17:38:27 +000035public interface QueryableGraph {
Nathan Harmata3b47b1f2016-07-26 18:41:41 +000036 /**
37 * Returns the node with the given {@code key}, or {@code null} if the node does not exist.
38 *
39 * @param requestor if non-{@code null}, the node on behalf of which {@code key} is being
40 * requested.
41 * @param reason the reason the node is being requested.
42 */
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000043 @Nullable
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000044 NodeEntry get(@Nullable SkyKey requestor, Reason reason, SkyKey key) throws InterruptedException;
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000045
46 /**
Janak Ramakrishnan2553c842016-07-08 18:43:37 +000047 * Fetches all the given nodes. Returns a map {@code m} such that, for all {@code k} in {@code
48 * 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 +000049 * !m.containsKey(k)} iff {@code get(k) == null}.
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000050 *
Nathan Harmata3b47b1f2016-07-26 18:41:41 +000051 * @param requestor if non-{@code null}, the node on behalf of which the given {@code keys} are
52 * being requested.
53 * @param reason the reason the nodes are being requested.
Nathan Harmata6fc9fa02015-03-27 17:48:57 +000054 */
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000055 Map<SkyKey, ? extends NodeEntry> getBatch(
ulfjackbe83f132017-07-18 18:12:09 +020056 @Nullable SkyKey requestor, Reason reason, Iterable<? extends SkyKey> keys)
57 throws InterruptedException;
Nathan Harmata3b47b1f2016-07-26 18:41:41 +000058
59 /**
shreyax26e72802018-03-26 09:04:48 -070060 * A version of {@link #getBatch} that returns an {@link InterruptibleSupplier} to possibly
61 * retrieve the results later.
shreyaxa6679ae2018-03-02 15:59:46 -080062 */
shreyax26e72802018-03-26 09:04:48 -070063 @CanIgnoreReturnValue
64 default InterruptibleSupplier<Map<SkyKey, ? extends NodeEntry>> getBatchAsync(
shreyaxa6679ae2018-03-02 15:59:46 -080065 @Nullable SkyKey requestor, Reason reason, Iterable<? extends SkyKey> keys) {
Googler407d3932019-05-16 15:13:59 -070066 return MemoizingInterruptibleSupplier.of(() -> getBatch(requestor, reason, keys));
shreyaxa6679ae2018-03-02 15:59:46 -080067 }
68
shahan21e26002018-10-01 08:25:02 -070069 /**
70 * Optimistically prefetches dependencies.
71 *
shahan5de60f12018-12-07 17:06:38 -080072 * @see PrefetchDepsRequest
shahan21e26002018-10-01 08:25:02 -070073 */
shahan5de60f12018-12-07 17:06:38 -080074 default void prefetchDeps(PrefetchDepsRequest request) throws InterruptedException {
75 if (request.oldDeps.isEmpty()) {
76 return;
77 }
78 request.excludedKeys = request.depKeys.toSet();
shahan21e26002018-10-01 08:25:02 -070079 getBatchAsync(
shahan5de60f12018-12-07 17:06:38 -080080 request.requestor,
shahan21e26002018-10-01 08:25:02 -070081 Reason.PREFETCH,
shahan5de60f12018-12-07 17:06:38 -080082 Iterables.filter(request.oldDeps, Predicates.not(Predicates.in(request.excludedKeys))));
shahan52339932018-09-16 10:33:59 -070083 }
84
Googler039630a2018-12-26 09:41:12 -080085 /** Checks whether this graph stores reverse dependencies. */
86 default boolean storesReverseDeps() {
87 return true;
88 }
89
shreyaxa6679ae2018-03-02 15:59:46 -080090 /**
Nathan Harmata3b47b1f2016-07-26 18:41:41 +000091 * The reason that a node is being looked up in the Skyframe graph.
92 *
93 * <p>Alternate graph implementations may wish to make use of this information.
94 */
95 enum Reason {
96 /**
Nathan Harmatac55fe152016-08-02 18:13:28 +000097 * The node is being fetched in order to see if it needs to be evaluated or because it was just
98 * evaluated, but *not* because it was just requested during evaluation of a SkyFunction
99 * (see {@link #DEP_REQUESTED}).
100 */
101 PRE_OR_POST_EVALUATION,
102
103 /**
Nathan Harmata3b47b1f2016-07-26 18:41:41 +0000104 * The node is being looked up as part of the prefetch step before evaluation of a SkyFunction.
105 */
106 PREFETCH,
107
108 /**
Nathan Harmatac55fe152016-08-02 18:13:28 +0000109 * The node is being fetched because it is about to be evaluated, but *not* because it was just
110 * requested during evaluation of a SkyFunction (see {@link #DEP_REQUESTED}).
Nathan Harmata3b47b1f2016-07-26 18:41:41 +0000111 */
112 EVALUATION,
113
114 /** The node is being looked up because it was requested during evaluation of a SkyFunction. */
115 DEP_REQUESTED,
116
117 /** The node is being looked up during the invalidation phase of Skyframe evaluation. */
118 INVALIDATION,
119
120 /** The node is being looked up during the cycle checking phase of Skyframe evaluation. */
121 CYCLE_CHECKING,
122
123 /** The node is being looked up so that an rdep can be added to it. */
124 RDEP_ADDITION,
125
126 /** The node is being looked up so that an rdep can be removed from it. */
127 RDEP_REMOVAL,
128
Shreya Bhattarai7fd3f2c52017-02-09 01:59:28 +0000129 /** The node is being looked up for any graph clean-up effort that may be necessary. */
130 CLEAN_UP,
131
Nathan Harmata3b47b1f2016-07-26 18:41:41 +0000132 /** The node is being looked up so it can be enqueued for evaluation or change pruning. */
133 ENQUEUING_CHILD,
134
135 /**
136 * The node is being looked up so that it can be signaled that a dependency is now complete.
137 */
138 SIGNAL_DEP,
139
140 /**
141 * The node is being looking up as part of the error bubbling phase of fail-fast Skyframe
142 * evaluation.
143 */
144 ERROR_BUBBLING,
145
Nathan Harmatac55fe152016-08-02 18:13:28 +0000146 /** The node is being looked up merely for an existence check. */
147 EXISTENCE_CHECKING,
148
shreyax26e72802018-03-26 09:04:48 -0700149 /** The node is being looked up merely to see if it is done or not. */
150 DONE_CHECKING,
151
Nathan Harmatac55fe152016-08-02 18:13:28 +0000152 /**
153 * The node is being looked up to service {@link WalkableGraph#getValue},
154 * {@link WalkableGraph#getException}, {@link WalkableGraph#getMissingAndExceptions}, or
155 * {@link WalkableGraph#getSuccessfulValues}.
156 */
157 WALKABLE_GRAPH_VALUE,
158
159 /** The node is being looked up to service {@link WalkableGraph#getDirectDeps}. */
160 WALKABLE_GRAPH_DEPS,
161
162 /** The node is being looked up to service {@link WalkableGraph#getReverseDeps}. */
163 WALKABLE_GRAPH_RDEPS,
164
Nathan Harmata3b47b1f2016-07-26 18:41:41 +0000165 /** Some other reason than one of the above. */
janakrc76eb212019-05-10 10:48:11 -0700166 OTHER;
167
168 public boolean isWalkable() {
169 return this == WALKABLE_GRAPH_VALUE
170 || this == WALKABLE_GRAPH_DEPS
171 || this == WALKABLE_GRAPH_RDEPS;
172 }
Nathan Harmata3b47b1f2016-07-26 18:41:41 +0000173 }
shahan5de60f12018-12-07 17:06:38 -0800174
175 /** Parameters for {@link QueryableGraph#prefetchDeps}. */
176 static class PrefetchDepsRequest {
177 public final SkyKey requestor;
178
179 /**
180 * Old dependencies to prefetch.
181 *
182 * <p>The implementation might ignore this if it has another way to determine the dependencies.
183 */
184 public final Set<SkyKey> oldDeps;
185
186 /**
187 * Direct deps that will be subsequently fetched and therefore should be excluded from
188 * prefetching.
189 */
190 public final GroupedList<SkyKey> depKeys;
191
192 /**
193 * Output parameter: {@code depKeys} as a set.
194 *
195 * <p>The implementation might set this, in which case, the caller could reuse it.
196 */
197 @Nullable public Set<SkyKey> excludedKeys = null;
198
199 public PrefetchDepsRequest(SkyKey requestor, Set<SkyKey> oldDeps, GroupedList<SkyKey> depKeys) {
200 this.requestor = requestor;
201 this.oldDeps = oldDeps;
202 this.depKeys = depKeys;
203 }
204 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100205}