Wait prefetcher to shutdown at the end of the build.

PiperOrigin-RevId: 458429934
Change-Id: I117368dc2c66e6fb910712104257cb2325a9ad5e
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TargetCompleteEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/TargetCompleteEvent.java
index 23be281..e0bb390 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/TargetCompleteEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/TargetCompleteEvent.java
@@ -314,6 +314,10 @@
     return outputs.get(outputGroup);
   }
 
+  public ImmutableMap<String, ArtifactsInOutputGroup> getOutputs() {
+    return outputs;
+  }
+
   // TODO(aehlig): remove as soon as we managed to get rid of the deprecated "important_output"
   // field.
 
diff --git a/src/main/java/com/google/devtools/build/lib/remote/AbstractActionInputPrefetcher.java b/src/main/java/com/google/devtools/build/lib/remote/AbstractActionInputPrefetcher.java
index 3165e10..2e79311 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/AbstractActionInputPrefetcher.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/AbstractActionInputPrefetcher.java
@@ -98,15 +98,6 @@
     }
   }
 
-  public void finalizeBuild() {
-    Path tempDir = tempPathGenerator.getTempDir();
-    try {
-      tempDir.deleteTree();
-    } catch (IOException ignored) {
-      // Intentionally left empty.
-    }
-  }
-
   protected abstract boolean shouldDownloadFile(Path path, FileArtifactValue metadata);
 
   /**
@@ -358,4 +349,23 @@
   public AsyncTaskCache.NoResult<Path> getDownloadCache() {
     return downloadCache;
   }
+
+  public void shutdown() {
+    downloadCache.shutdown();
+    while (true) {
+      try {
+        downloadCache.awaitTermination();
+        break;
+      } catch (InterruptedException ignored) {
+        downloadCache.shutdownNow();
+      }
+    }
+
+    Path tempDir = tempPathGenerator.getTempDir();
+    try {
+      tempDir.deleteTree();
+    } catch (IOException ignored) {
+      // Intentionally ignored.
+    }
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java
index d382364..4bec4ab 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java
@@ -49,6 +49,7 @@
   @Nullable private final Path logDir;
   private ImmutableSet<ActionInput> filesToDownload = ImmutableSet.of();
   private RemoteExecutionService remoteExecutionService;
+  @Nullable private RemoteActionInputFetcher actionInputFetcher;
 
   private RemoteActionContextProvider(
       Executor executor,
@@ -125,6 +126,10 @@
     return remotePathResolver;
   }
 
+  public void setActionInputFetcher(RemoteActionInputFetcher actionInputFetcher) {
+    this.actionInputFetcher = actionInputFetcher;
+  }
+
   private RemoteExecutionService getRemoteExecutionService() {
     if (remoteExecutionService == null) {
       Path workingDirectory = env.getWorkingDirectory();
@@ -211,9 +216,10 @@
   }
 
   public void afterCommand() {
+    BlockWaitingModule blockWaitingModule =
+        checkNotNull(env.getRuntime().getBlazeModule(BlockWaitingModule.class));
+
     if (remoteExecutionService != null) {
-      BlockWaitingModule blockWaitingModule =
-          checkNotNull(env.getRuntime().getBlazeModule(BlockWaitingModule.class));
       blockWaitingModule.submit(() -> remoteExecutionService.shutdown());
     } else {
       if (remoteCache != null) {
@@ -223,5 +229,9 @@
         remoteExecutor.close();
       }
     }
+
+    if (actionInputFetcher != null) {
+      blockWaitingModule.submit(() -> actionInputFetcher.shutdown());
+    }
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
index 1931782..7b1180e 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java
@@ -930,6 +930,7 @@
               new TempPathGenerator(tempDir));
       builder.setActionInputPrefetcher(actionInputFetcher);
       remoteOutputService.setActionInputFetcher(actionInputFetcher);
+      actionContextProvider.setActionInputFetcher(actionInputFetcher);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteOutputService.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteOutputService.java
index 7218a68..13994d0 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteOutputService.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteOutputService.java
@@ -86,9 +86,7 @@
 
   @Override
   public void finalizeBuild(boolean buildSuccessful) {
-    if (actionInputFetcher != null) {
-      actionInputFetcher.finalizeBuild();
-    }
+    // Intentionally left empty.
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlockWaitingModule.java b/src/main/java/com/google/devtools/build/lib/runtime/BlockWaitingModule.java
index 408cf73..726ef37 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlockWaitingModule.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlockWaitingModule.java
@@ -15,9 +15,9 @@
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
-import static java.util.concurrent.TimeUnit.SECONDS;
 
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.google.devtools.build.lib.concurrent.ExecutorUtil;
 import com.google.devtools.build.lib.util.AbruptExitException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -47,11 +47,7 @@
   public void afterCommand() throws AbruptExitException {
     checkNotNull(executorService, "executorService must not be null");
 
-    executorService.shutdown();
-    try {
-      executorService.awaitTermination(Long.MAX_VALUE, SECONDS);
-    } catch (InterruptedException e) {
-      executorService.shutdownNow();
+    if (ExecutorUtil.interruptibleShutdown(executorService)) {
       Thread.currentThread().interrupt();
     }