Convert SkyQueryEnvironment#buildTransitiveClosure to use batch operations.

--
MOS_MIGRATED_REVID=96433497
diff --git a/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java b/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java
index b88b8903..0e4e86b 100644
--- a/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java
+++ b/src/main/java/com/google/devtools/build/skyframe/DelegatingWalkableGraph.java
@@ -19,6 +19,7 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import javax.annotation.Nullable;
@@ -70,11 +71,29 @@
       };
 
   @Override
-  public Map<SkyKey, SkyValue> getValuesMaybe(Iterable<SkyKey> keys) {
+  public Map<SkyKey, SkyValue> getDoneValues(Iterable<SkyKey> keys) {
     return Maps.filterValues(Maps.transformValues(graph.getBatch(keys), GET_SKY_VALUE_FUNCTION),
         Predicates.notNull());
   }
 
+  @Override
+  public Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys) {
+    Map<SkyKey, Exception> result = new HashMap<>();
+    Map<SkyKey, NodeEntry> graphResult = graph.getBatch(keys);
+    for (SkyKey key : keys) {
+      NodeEntry nodeEntry = graphResult.get(key);
+      if (nodeEntry == null || !nodeEntry.isDone()) {
+        result.put(key, null);
+      } else {
+        ErrorInfo errorInfo = nodeEntry.getErrorInfo();
+        if (errorInfo != null) {
+          result.put(key, errorInfo.getException());
+        }
+      }
+    }
+    return result;
+  }
+
   @Nullable
   @Override
   public Exception getException(SkyKey key) {
diff --git a/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java b/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java
index be68248..181b7dc 100644
--- a/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java
+++ b/src/main/java/com/google/devtools/build/skyframe/WalkableGraph.java
@@ -44,7 +44,16 @@
    * Returns a map giving the values of the given keys for done keys. Keys not present in the graph
    * or whose nodes are not done will not be present in the returned map.
    */
-  Map<SkyKey, SkyValue> getValuesMaybe(Iterable<SkyKey> keys);
+  Map<SkyKey, SkyValue> getDoneValues(Iterable<SkyKey> keys);
+
+  /**
+   * Returns a map giving exceptions associated to the given keys for done keys. Keys not present in
+   * the graph or whose nodes are not done will be present in the returned map, with null value. In
+   * other words, if {@code key} is in {@param keys}, then the returned map will contain an entry
+   * for {@code key} if and only if the node for {@code key} did <i>not</i> evaluate successfully
+   * without error.
+   */
+  Map<SkyKey, Exception> getMissingAndExceptions(Iterable<SkyKey> keys);
 
   /**
    * Returns the exception thrown when computing the node with the given key, if any. If the node