Add ActionKeyContext to Action#getKey.

This key context can be used by actions to share partial key computations, for instance when computing MD5s for nested sets.

RELNOTES: None
PiperOrigin-RevId: 177359607
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
index 5483581..1ad13c1 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
@@ -23,6 +23,7 @@
 import com.google.common.eventbus.SubscriberExceptionHandler;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.Uninterruptibles;
+import com.google.devtools.build.lib.actions.ActionKeyContext;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
@@ -149,6 +150,7 @@
   private final SubscriberExceptionHandler eventBusExceptionHandler;
   private final String productName;
   private final PathConverter pathToUriConverter;
+  private final ActionKeyContext actionKeyContext;
 
   // Workspace state (currently exactly one workspace per server)
   private BlazeWorkspace workspace;
@@ -162,6 +164,7 @@
       ConfiguredRuleClassProvider ruleClassProvider,
       ImmutableList<ConfigurationFragmentFactory> configurationFragmentFactories,
       ImmutableMap<String, InfoItem> infoItems,
+      ActionKeyContext actionKeyContext,
       Clock clock,
       Runnable abruptShutdownHandler,
       OptionsProvider startupOptionsProvider,
@@ -184,6 +187,7 @@
     this.ruleClassProvider = ruleClassProvider;
     this.configurationFragmentFactories = configurationFragmentFactories;
     this.infoItems = infoItems;
+    this.actionKeyContext = actionKeyContext;
     this.clock = clock;
     this.abruptShutdownHandler = abruptShutdownHandler;
     this.startupOptionsProvider = startupOptionsProvider;
@@ -294,6 +298,10 @@
     return workspace;
   }
 
+  public ActionKeyContext getActionKeyContext() {
+    return actionKeyContext;
+  }
+
   /**
    * The directory in which blaze stores the server state - that is, the socket
    * file and a log.
@@ -440,6 +448,8 @@
       env.getReporter().handle(Event.error("Error while writing profile file: " + e.getMessage()));
     }
     env.getReporter().clearEventBus();
+
+    actionKeyContext.clear();
   }
 
   // Make sure we keep a strong reference to this logger, so that the
@@ -971,6 +981,7 @@
             .setProductName(productName)
             .setFileSystem(fs)
             .setServerDirectories(serverDirectories)
+            .setActionKeyContext(new ActionKeyContext())
             .setStartupOptionsProvider(options)
             .setClock(clock)
             .setAbruptShutdownHandler(abruptShutdownHandler)
@@ -1122,11 +1133,14 @@
     private SubscriberExceptionHandler eventBusExceptionHandler = new RemoteExceptionHandler();
     private UUID instanceId;
     private String productName;
+    private ActionKeyContext actionKeyContext;
 
     public BlazeRuntime build() throws AbruptExitException {
       Preconditions.checkNotNull(productName);
       Preconditions.checkNotNull(serverDirectories);
       Preconditions.checkNotNull(startupOptionsProvider);
+      ActionKeyContext actionKeyContext =
+          this.actionKeyContext != null ? this.actionKeyContext : new ActionKeyContext();
       Clock clock = (this.clock == null) ? BlazeClock.instance() : this.clock;
       UUID instanceId =  (this.instanceId == null) ? UUID.randomUUID() : this.instanceId;
 
@@ -1197,6 +1211,7 @@
           ruleClassProvider,
           ruleClassProvider.getConfigurationFragments(),
           serverBuilder.getInfoItems(),
+          actionKeyContext,
           clock,
           abruptShutdownHandler,
           startupOptionsProvider,
@@ -1255,5 +1270,10 @@
       this.eventBusExceptionHandler = eventBusExceptionHandler;
       return this;
     }
+
+    public Builder setActionKeyContext(ActionKeyContext actionKeyContext) {
+      this.actionKeyContext = actionKeyContext;
+      return this;
+    }
   }
 }