Automated rollback of commit 52bf46b324a6bcc8f90f6b2ffaf6d877ff50ccf6.

*** Reason for rollback ***

b/177552620

*** Original change description ***

Reduce needless contention in the include scanner's fileParseCache. The
computeIfAbsent() function of ConcurrentHashMap is supposed to have a fast
implementation and the map will then allow ~number of processors concurrent
writes. However, reading a file and extracting the include lines can be a costly
IO operation that does not fit this bill. Use futures instead.

RELNOTES: None.
PiperOrigin-RevId: 351846931
diff --git a/src/main/java/com/google/devtools/build/lib/includescanning/LegacyIncludeScanner.java b/src/main/java/com/google/devtools/build/lib/includescanning/LegacyIncludeScanner.java
index 50dfb92..b825655 100644
--- a/src/main/java/com/google/devtools/build/lib/includescanning/LegacyIncludeScanner.java
+++ b/src/main/java/com/google/devtools/build/lib/includescanning/LegacyIncludeScanner.java
@@ -19,8 +19,9 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import com.google.common.flogger.GoogleLogger;
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
 import com.google.devtools.build.lib.actions.ActionExecutionContext;
 import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
@@ -55,7 +56,6 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
 
 /**
  * C include scanner. Quickly scans C/C++ source files to determine the bounding set of transitively
@@ -70,6 +70,9 @@
  * </pre>
  */
 public class LegacyIncludeScanner implements IncludeScanner {
+
+  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
+
   private static final class ArtifactWithInclusionContext {
     private final Artifact artifact;
     private final Kind contextKind;
@@ -764,31 +767,45 @@
       checkForInterrupt("processing", source);
 
       Collection<Inclusion> inclusions;
-      SettableFuture<Collection<Inclusion>> future = SettableFuture.create();
-      Future<Collection<Inclusion>> previous = fileParseCache.putIfAbsent(source, future);
-      if (previous == null) {
-        previous = future;
-        try {
-          future.set(
-              parser.extractInclusions(
-                  source,
-                  actionExecutionMetadata,
-                  actionExecutionContext,
-                  grepIncludes,
-                  spawnIncludeScannerSupplier.get(),
-                  isRealOutputFile(source.getExecPath())));
-        } catch (Throwable t) {
-          future.setException(t);
-          fileParseCache.remove(source);
-          throw t;
-        }
-      }
       try {
-        inclusions = previous.get();
-      } catch (ExecutionException e) {
-        Throwables.propagateIfPossible(e.getCause(), IOException.class, InterruptedException.class);
-        Throwables.throwIfInstanceOf(e.getCause(), ExecException.class);
-        throw new IllegalStateException(e.getCause());
+        inclusions =
+            fileParseCache
+                .computeIfAbsent(
+                    source,
+                    file -> {
+                      try {
+                        return Futures.immediateFuture(
+                            parser.extractInclusions(
+                                file,
+                                actionExecutionMetadata,
+                                actionExecutionContext,
+                                grepIncludes,
+                                spawnIncludeScannerSupplier.get(),
+                                isRealOutputFile(source.getExecPath())));
+                      } catch (IOException e) {
+                        throw new IORuntimeException(e);
+                      } catch (ExecException e) {
+                        throw new ExecRuntimeException(e);
+                      } catch (InterruptedException e) {
+                        throw new InterruptedRuntimeException(e);
+                      }
+                    })
+                .get();
+      } catch (ExecutionException ee) {
+        try {
+          Throwables.throwIfInstanceOf(ee.getCause(), RuntimeException.class);
+          throw new IllegalStateException(ee.getCause());
+        } catch (IORuntimeException e) {
+          throw e.getCauseIOException();
+        } catch (ExecRuntimeException e) {
+          throw e.getRealCause();
+        } catch (InterruptedRuntimeException e) {
+          throw e.getRealCause();
+        }
+      } catch (RuntimeException e) {
+        // TODO(b/175294870): Remove after diagnosing the bug.
+        logger.atSevere().withCause(e).log("Uncaught exception in call to extractInclusions");
+        throw e;
       }
       Preconditions.checkNotNull(inclusions, source);