Close file handles in ActionCache before bazel clean

Fixed https://github.com/bazelbuild/bazel/issues/3043

Change-Id: Ibbe6ba945bbd439cd84676fcb7fd7ecbbb99e5f0
PiperOrigin-RevId: 159261292
diff --git a/src/main/java/com/google/devtools/build/lib/actions/cache/ActionCache.java b/src/main/java/com/google/devtools/build/lib/actions/cache/ActionCache.java
index 1e123e5..59eb31f 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/cache/ActionCache.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/cache/ActionCache.java
@@ -187,6 +187,9 @@
    */
   long save() throws IOException;
 
+  /** Clear the action cache, closing all opened file handle. */
+  void clear();
+
   /**
    * Dumps action cache content into the given PrintStream.
    */
diff --git a/src/main/java/com/google/devtools/build/lib/actions/cache/CompactPersistentActionCache.java b/src/main/java/com/google/devtools/build/lib/actions/cache/CompactPersistentActionCache.java
index 1dee811..95a9860 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/cache/CompactPersistentActionCache.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/cache/CompactPersistentActionCache.java
@@ -293,6 +293,12 @@
   }
 
   @Override
+  public void clear() {
+    indexer.clear();
+    map.clear();
+  }
+
+  @Override
   public synchronized String toString() {
     StringBuilder builder = new StringBuilder();
     // map.size() - 1 to avoid counting the validation key.
diff --git a/src/main/java/com/google/devtools/build/lib/actions/cache/PersistentStringIndexer.java b/src/main/java/com/google/devtools/build/lib/actions/cache/PersistentStringIndexer.java
index bf8d438..28970bf 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/cache/PersistentStringIndexer.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/cache/PersistentStringIndexer.java
@@ -77,11 +77,6 @@
       throw new UnsupportedOperationException();
     }
 
-    @Override
-    public void clear() {
-      throw new UnsupportedOperationException();
-    }
-
     public void flush() {
       super.forceFlush();
     }
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeWorkspace.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeWorkspace.java
index 1f54096..d5b05da 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeWorkspace.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeWorkspace.java
@@ -208,10 +208,19 @@
   }
 
   /**
+   * Reinitializes the Skyframe evaluator.
+   */
+  public void resetEvaluator() throws IOException {
+    skyframeExecutor.resetEvaluator();
+  }
+
+  /**
    * Removes in-memory caches.
    */
   public void clearCaches() throws IOException {
-    skyframeExecutor.resetEvaluator();
+    if (actionCache != null) {
+      actionCache.clear();
+    }
     actionCache = null;
     FileSystemUtils.deleteTree(getCacheDirectory());
   }
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
index 352c196..ef10788 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
@@ -227,6 +227,7 @@
     if (env.getOutputService() != null) {
       env.getOutputService().clean();
     }
+    env.getBlazeWorkspace().clearCaches();
     if (expunge) {
       LOG.info("Expunging...");
       env.getRuntime().prepareForAbruptShutdown();
@@ -255,7 +256,7 @@
       asyncClean(env, outputBase, "Output base");
     } else {
       LOG.info("Output cleaning...");
-      env.getBlazeWorkspace().clearCaches();
+      env.getBlazeWorkspace().resetEvaluator();
       // In order to be sure that we delete everything, delete the workspace directory both for
       // --deep_execroot and for --nodeep_execroot.
       for (String directory : new String[] {workspaceDirectory, "execroot"}) {
diff --git a/src/test/java/com/google/devtools/build/lib/actions/util/ActionCacheTestHelper.java b/src/test/java/com/google/devtools/build/lib/actions/util/ActionCacheTestHelper.java
index 5ade36e..1415c81 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/util/ActionCacheTestHelper.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/util/ActionCacheTestHelper.java
@@ -42,6 +42,9 @@
         }
 
         @Override
+        public void clear() {}
+
+        @Override
         public void dump(PrintStream out) {}
       };
 }
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java b/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java
index 2104ec5..1713e7e 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java
@@ -443,6 +443,11 @@
     }
 
     @Override
+    public void clear() {
+      // safe to ignore
+    }
+
+    @Override
     public void dump(PrintStream out) {
       out.println("In-memory action cache has " + actionCache.size() + " records");
     }