Add threadpool injectability to invalidator
--
MOS_MIGRATED_REVID=99961435
diff --git a/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java b/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java
index fc2a2c7..cfe03e2 100644
--- a/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/EagerInvalidator.java
@@ -13,11 +13,17 @@
// limitations under the License.
package com.google.devtools.build.skyframe;
-import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.devtools.build.lib.concurrent.AbstractQueueVisitor;
+import com.google.devtools.build.lib.concurrent.AbstractQueueVisitor.ThreadPoolExecutorParams;
import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DeletingNodeVisitor;
import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.DirtyingNodeVisitor;
import com.google.devtools.build.skyframe.InvalidatingNodeVisitor.InvalidationState;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import javax.annotation.Nullable;
+
/**
* Utility class for performing eager invalidation on Skyframe graphs.
*
@@ -39,29 +45,61 @@
EvaluationProgressReceiver invalidationReceiver, InvalidationState state,
boolean traverseGraph, DirtyKeyTracker dirtyKeyTracker) throws InterruptedException {
InvalidatingNodeVisitor visitor =
- createVisitor(/*delete=*/true, graph, diff, invalidationReceiver, state, traverseGraph,
+ createDeletingVisitorIfNeeded(graph, diff, invalidationReceiver, state, traverseGraph,
dirtyKeyTracker);
if (visitor != null) {
visitor.run();
}
}
- /**
- * Creates an invalidation visitor that is ready to run. Caller should call #run() on the visitor.
- * Allows test classes to keep a reference to the visitor, and await exceptions/interrupts.
- */
- @VisibleForTesting
- static InvalidatingNodeVisitor createVisitor(boolean delete, DirtiableGraph graph,
+ @Nullable
+ static InvalidatingNodeVisitor createDeletingVisitorIfNeeded(DirtiableGraph graph,
Iterable<SkyKey> diff, EvaluationProgressReceiver invalidationReceiver,
InvalidationState state, boolean traverseGraph, DirtyKeyTracker dirtyKeyTracker) {
state.update(diff);
- if (state.isEmpty()) {
- return null;
+ return state.isEmpty() ? null
+ : new DeletingNodeVisitor(graph, invalidationReceiver, state, traverseGraph,
+ dirtyKeyTracker);
+ }
+
+ @Nullable
+ static InvalidatingNodeVisitor createInvalidatingVisitorIfNeeded(DirtiableGraph graph,
+ Iterable<SkyKey> diff, EvaluationProgressReceiver invalidationReceiver,
+ InvalidationState state, DirtyKeyTracker dirtyKeyTracker,
+ Function<ThreadPoolExecutorParams, ThreadPoolExecutor> executorFactory) {
+ state.update(diff);
+ return state.isEmpty() ? null
+ : new DirtyingNodeVisitor(graph, invalidationReceiver, state, dirtyKeyTracker,
+ executorFactory);
+ }
+
+ @Nullable
+ static InvalidatingNodeVisitor createInvalidatingVisitorIfNeeded(DirtiableGraph graph,
+ Iterable<SkyKey> diff, EvaluationProgressReceiver invalidationReceiver,
+ InvalidationState state, DirtyKeyTracker dirtyKeyTracker) {
+ return createInvalidatingVisitorIfNeeded(graph, diff, invalidationReceiver, state,
+ dirtyKeyTracker, AbstractQueueVisitor.EXECUTOR_FACTORY);
+ }
+
+ /**
+ * Invalidates given values and their upward transitive closure in the graph, using an executor
+ * constructed with the provided factory, if necessary.
+ */
+ public static void invalidate(DirtiableGraph graph, Iterable<SkyKey> diff,
+ EvaluationProgressReceiver invalidationReceiver, InvalidationState state,
+ DirtyKeyTracker dirtyKeyTracker,
+ Function<ThreadPoolExecutorParams, ThreadPoolExecutor> executorFactory)
+ throws InterruptedException {
+ // If we are invalidating, we must be in an incremental build by definition, so we must
+ // maintain a consistent graph state by traversing the graph and invalidating transitive
+ // dependencies. If edges aren't present, it would be impossible to check the dependencies of
+ // a dirty node in any case.
+ InvalidatingNodeVisitor visitor =
+ createInvalidatingVisitorIfNeeded(graph, diff, invalidationReceiver, state,
+ dirtyKeyTracker, executorFactory);
+ if (visitor != null) {
+ visitor.run();
}
- return delete
- ? new DeletingNodeVisitor(graph, invalidationReceiver, state, traverseGraph,
- dirtyKeyTracker)
- : new DirtyingNodeVisitor(graph, invalidationReceiver, state, dirtyKeyTracker);
}
/**
@@ -70,16 +108,9 @@
public static void invalidate(DirtiableGraph graph, Iterable<SkyKey> diff,
EvaluationProgressReceiver invalidationReceiver, InvalidationState state,
DirtyKeyTracker dirtyKeyTracker)
- throws InterruptedException {
- // If we are invalidating, we must be in an incremental build by definition, so we must
- // maintain a consistent graph state by traversing the graph and invalidating transitive
- // dependencies. If edges aren't present, it would be impossible to check the dependencies of
- // a dirty node in any case.
- InvalidatingNodeVisitor visitor =
- createVisitor(/*delete=*/false, graph, diff, invalidationReceiver, state,
- /*traverseGraph=*/true, dirtyKeyTracker);
- if (visitor != null) {
- visitor.run();
- }
+ throws InterruptedException {
+ invalidate(graph, diff, invalidationReceiver, state, dirtyKeyTracker,
+ AbstractQueueVisitor.EXECUTOR_FACTORY);
}
+
}