ActionOwner references only BuildEvent instead of full BuildConfiguration

This reduces the size of its serialized representation.

PiperOrigin-RevId: 188597127
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionOwner.java b/src/main/java/com/google/devtools/build/lib/actions/ActionOwner.java
index 77c67a81..eaad2df 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionOwner.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionOwner.java
@@ -56,7 +56,7 @@
       @Nullable String mnemonic,
       @Nullable String targetKind,
       String configurationChecksum,
-      @Nullable BuildConfigurationInterface configuration,
+      @Nullable BuildConfigurationEvent configuration,
       @Nullable String additionalProgressInfo,
       @Nullable PlatformInfo executionPlatform) {
     return new AutoValue_ActionOwner(
@@ -94,11 +94,11 @@
   public abstract String getConfigurationChecksum();
 
   /**
-   * Return the configuration of the action owner, if any, as it should be reported in the build
-   * event protocol.
+   * Return the {@link BuildConfigurationEvent} associated with the action owner, if any, as it
+   * should be reported in the build event protocol.
    */
   @Nullable
-  public abstract BuildConfigurationInterface getConfiguration();
+  public abstract BuildConfigurationEvent getConfiguration();
 
   /** Returns the target kind (rule class name) for this ActionOwner, if any; null otherwise. */
   @Nullable
diff --git a/src/main/java/com/google/devtools/build/lib/actions/BuildConfigurationEvent.java b/src/main/java/com/google/devtools/build/lib/actions/BuildConfigurationEvent.java
new file mode 100644
index 0000000..96fd9cb
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/actions/BuildConfigurationEvent.java
@@ -0,0 +1,70 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.actions;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.buildeventstream.BuildEvent;
+import com.google.devtools.build.lib.buildeventstream.BuildEventConverters;
+import com.google.devtools.build.lib.buildeventstream.BuildEventId;
+import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * Encapsulation of {@link BuildEvent} info associated with a {@link
+ * com.google.devtools.build.lib.analysis.config.BuildConfiguration}.
+ */
+@AutoCodec
+public class BuildConfigurationEvent implements BuildEvent {
+
+  private final BuildEventId eventId;
+  private final BuildEventStreamProtos.BuildEvent eventProto;
+
+  public BuildConfigurationEvent(
+      BuildEventId eventId, BuildEventStreamProtos.BuildEvent eventProto) {
+    this.eventId = eventId;
+    this.eventProto = eventProto;
+  }
+
+  @Override
+  public BuildEventStreamProtos.BuildEvent asStreamProto(BuildEventConverters unusedConverters) {
+    return eventProto;
+  }
+
+  @Override
+  public BuildEventId getEventId() {
+    return eventId;
+  }
+
+  @Override
+  public Collection<BuildEventId> getChildrenEvents() {
+    return ImmutableList.of();
+  }
+
+  @Override
+  public boolean equals(Object other) {
+    if (!(other instanceof BuildConfigurationEvent)) {
+      return false;
+    }
+    BuildConfigurationEvent that = (BuildConfigurationEvent) other;
+    return Objects.equals(eventId, that.eventId) && Objects.equals(eventProto, that.eventProto);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(eventId, eventProto);
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/BuildConfigurationInterface.java b/src/main/java/com/google/devtools/build/lib/actions/BuildConfigurationInterface.java
deleted file mode 100644
index f033754..0000000
--- a/src/main/java/com/google/devtools/build/lib/actions/BuildConfigurationInterface.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.actions;
-
-import com.google.devtools.build.lib.buildeventstream.BuildEvent;
-
-/**
- * An interface for {@code BuildConfiguration} that only exists so that {@link ActionOwner} can
- * refer to {@code BuildConfiguration}, which is in a dependent package. {@code BuildConfiguration}
- * must be the only implementation of this interface.
- */
-public interface BuildConfigurationInterface extends BuildEvent {
-}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AspectConfiguredEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/AspectConfiguredEvent.java
index 19e0b58..a4671e9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AspectConfiguredEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectConfiguredEvent.java
@@ -43,7 +43,7 @@
     ImmutableList.Builder<BuildEvent> builder = new ImmutableList.Builder<>();
     for (BuildConfiguration config : configurations) {
       if (config != null) {
-        builder.add(config);
+        builder.add(config.toBuildEvent());
       } else {
         builder.add(new NullConfiguration());
       }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 316791d..075a0ab 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -483,7 +483,7 @@
         configuration.getMnemonic(),
         rule.getTargetKind(),
         configuration.checksum(),
-        configuration,
+        configuration.toBuildEvent(),
         configuration.isHostConfiguration() ? HOST_CONFIGURATION_PROGRESS_TAG : null,
         executionPlatform);
   }
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 5c36d85..eae32b2 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
@@ -254,7 +254,7 @@
   public Collection<BuildEvent> getConfigurations() {
     BuildConfiguration configuration = target.getConfiguration();
     if (configuration != null) {
-      return ImmutableList.of(target.getConfiguration());
+      return ImmutableList.of(target.getConfiguration().toBuildEvent());
     } else {
       return ImmutableList.<BuildEvent>of();
     }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TargetConfiguredEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/TargetConfiguredEvent.java
index db6bea2..daa08d9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/TargetConfiguredEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/TargetConfiguredEvent.java
@@ -45,7 +45,7 @@
     ImmutableList.Builder<BuildEvent> builder = new ImmutableList.Builder<>();
     for (BuildConfiguration config : configurations) {
       if (config != null) {
-        builder.add(config);
+        builder.add(config.toBuildEvent());
       } else {
         builder.add(new NullConfiguration());
       }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
index ce0a75a..dc95254 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
@@ -18,6 +18,7 @@
 import com.google.common.base.Joiner;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
+import com.google.common.base.Suppliers;
 import com.google.common.base.Verify;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ClassToInstanceMap;
@@ -34,16 +35,14 @@
 import com.google.common.collect.MutableClassToInstanceMap;
 import com.google.devtools.build.lib.actions.ActionEnvironment;
 import com.google.devtools.build.lib.actions.ArtifactRoot;
-import com.google.devtools.build.lib.actions.BuildConfigurationInterface;
+import com.google.devtools.build.lib.actions.BuildConfigurationEvent;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
 import com.google.devtools.build.lib.analysis.config.transitions.ComposingPatchTransition;
 import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
-import com.google.devtools.build.lib.buildeventstream.BuildEventConverters;
 import com.google.devtools.build.lib.buildeventstream.BuildEventId;
 import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
-import com.google.devtools.build.lib.buildeventstream.GenericBuildEvent;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
@@ -71,7 +70,6 @@
 import com.google.devtools.common.options.OptionsParsingException;
 import com.google.devtools.common.options.TriState;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -82,6 +80,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.function.Supplier;
 import javax.annotation.Nullable;
 
 /**
@@ -113,7 +112,7 @@
 // TODO(janakr): If overhead of fragments class names is too high, add constructor that just takes
 // fragments and gets names from them.
 @AutoCodec
-public class BuildConfiguration implements BuildConfigurationInterface {
+public class BuildConfiguration {
   /**
    * Sorts fragments by class name. This produces a stable order which, e.g., facilitates consistent
    * output from buildMnemonic.
@@ -1180,6 +1179,8 @@
   /** Data for introspecting the options used by this configuration. */
   private final TransitiveOptionDetails transitiveOptionDetails;
 
+  private final Supplier<BuildConfigurationEvent> buildEventSupplier;
+
   /**
    * Returns true if this configuration is semantically equal to the other, with
    * the possible exception that the other has fewer fragments.
@@ -1406,6 +1407,7 @@
       reservedActionMnemonics.addAll(fragment.getReservedActionMnemonics());
     }
     this.reservedActionMnemonics = reservedActionMnemonics.build();
+    this.buildEventSupplier = Suppliers.memoize(this::createBuildEvent);
   }
 
   /**
@@ -2068,24 +2070,27 @@
     return currentTransition;
   }
 
-  @Override
   public BuildEventId getEventId() {
     return BuildEventId.configurationId(checksum());
   }
 
-  @Override
-  public Collection<BuildEventId> getChildrenEvents() {
-    return ImmutableList.of();
+  public BuildConfigurationEvent toBuildEvent() {
+    return buildEventSupplier.get();
   }
 
-  @Override
-  public BuildEventStreamProtos.BuildEvent asStreamProto(BuildEventConverters converters) {
-    BuildEventStreamProtos.Configuration.Builder builder =
-        BuildEventStreamProtos.Configuration.newBuilder()
-            .setMnemonic(getMnemonic())
-            .setPlatformName(getCpu())
-            .putAllMakeVariable(getMakeEnvironment())
-            .setCpu(getCpu());
-    return GenericBuildEvent.protoChaining(this).setConfiguration(builder.build()).build();
+  private BuildConfigurationEvent createBuildEvent() {
+    BuildEventId eventId = getEventId();
+    BuildEventStreamProtos.BuildEvent.Builder builder =
+        BuildEventStreamProtos.BuildEvent.newBuilder();
+    builder
+        .setId(eventId.asStreamProto())
+        .setConfiguration(
+            BuildEventStreamProtos.Configuration.newBuilder()
+                .setMnemonic(getMnemonic())
+                .setPlatformName(getCpu())
+                .putAllMakeVariable(getMakeEnvironment())
+                .setCpu(getCpu())
+                .build());
+    return new BuildConfigurationEvent(eventId, builder.build());
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/VisibilityErrorEvent.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/VisibilityErrorEvent.java
index 991b26e..1859e6d 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/VisibilityErrorEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/VisibilityErrorEvent.java
@@ -61,6 +61,6 @@
 
   @Override
   public Collection<BuildEvent> getConfigurations() {
-    return ImmutableList.<BuildEvent>of(configuration);
+    return ImmutableList.<BuildEvent>of(configuration.toBuildEvent());
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventstream/BUILD b/src/main/java/com/google/devtools/build/lib/buildeventstream/BUILD
index f56bd27..4817398 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventstream/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/buildeventstream/BUILD
@@ -16,6 +16,7 @@
         "//src/main/java/com/google/devtools/build/lib/buildeventstream/proto:build_event_stream_java_proto",
         "//src/main/java/com/google/devtools/build/lib/causes",
         "//src/main/java/com/google/devtools/build/lib/cmdline",
+        "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
         "//src/main/java/com/google/devtools/build/lib/vfs",
         "//third_party:guava",
         "//third_party:jsr305",
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventstream/BuildEventId.java b/src/main/java/com/google/devtools/build/lib/buildeventstream/BuildEventId.java
index e0c5b78..feab9ba 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventstream/BuildEventId.java
+++ b/src/main/java/com/google/devtools/build/lib/buildeventstream/BuildEventId.java
@@ -18,6 +18,7 @@
 import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.ConfigurationId;
 import com.google.devtools.build.lib.causes.Cause;
 import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.protobuf.TextFormat;
 import java.io.Serializable;
@@ -34,11 +35,13 @@
  * identifiers that do not accidentally coincide is by providing a target or a target pattern;
  * therefore, those (if provided) are made specially visible.
  */
+@AutoCodec
 @Immutable
 public final class BuildEventId implements Serializable {
   private final BuildEventStreamProtos.BuildEventId protoid;
 
-  private BuildEventId(BuildEventStreamProtos.BuildEventId protoid) {
+  @AutoCodec.VisibleForSerialization
+  BuildEventId(BuildEventStreamProtos.BuildEventId protoid) {
     this.protoid = protoid;
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java
index 3a18d41..8c68b26 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java
@@ -28,8 +28,8 @@
 import com.google.devtools.build.lib.analysis.AnalysisProtos.ActionGraphContainer;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.actions.SpawnAction;
-import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
+import com.google.devtools.build.lib.buildeventstream.BuildEvent;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetView;
@@ -103,7 +103,7 @@
     // store environment
     if (action instanceof SpawnAction) {
       SpawnAction spawnAction = (SpawnAction) action;
-      // TODO(twerth): This handles the fixed environemnt. We probably want to output the inherited
+      // TODO(twerth): This handles the fixed environment. We probably want to output the inherited
       // environment as well.
       ImmutableMap<String, String> fixedEnvironment = spawnAction.getEnvironment();
       for (Entry<String, String> environmentVariable : fixedEnvironment.entrySet()) {
@@ -122,8 +122,8 @@
 
     ActionOwner actionOwner = action.getOwner();
     if (actionOwner != null) {
-      BuildConfiguration buildConfiguration = (BuildConfiguration) actionOwner.getConfiguration();
-      actionBuilder.setConfigurationId(knownConfigurations.dataToId(buildConfiguration));
+      BuildEvent event = actionOwner.getConfiguration();
+      actionBuilder.setConfigurationId(knownConfigurations.dataToId(event));
 
       // store aspect
       for (AspectDescriptor aspectDescriptor : actionOwner.getAspectDescriptors()) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/KnownConfigurations.java b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/KnownConfigurations.java
index 71ea0d7..6083d0b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/KnownConfigurations.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/KnownConfigurations.java
@@ -15,25 +15,25 @@
 
 import com.google.devtools.build.lib.analysis.AnalysisProtos;
 import com.google.devtools.build.lib.analysis.AnalysisProtos.ActionGraphContainer.Builder;
-import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.buildeventstream.BuildEvent;
+import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
 
-/**
- * Cache for BuildConfigurations in the action graph.
- */
-public class KnownConfigurations
-    extends BaseCache<BuildConfiguration, AnalysisProtos.Configuration> {
+/** Cache for BuildConfigurations in the action graph. */
+public class KnownConfigurations extends BaseCache<BuildEvent, AnalysisProtos.Configuration> {
 
   KnownConfigurations(Builder actionGraphBuilder) {
     super(actionGraphBuilder);
   }
 
   @Override
-  AnalysisProtos.Configuration createProto(BuildConfiguration buildConfiguration, String id) {
+  AnalysisProtos.Configuration createProto(BuildEvent config, String id) {
+    BuildEventStreamProtos.Configuration configProto =
+        config.asStreamProto(/*converters=*/ null).getConfiguration();
     return AnalysisProtos.Configuration.newBuilder()
-            .setMnemonic(buildConfiguration.getMnemonic())
-            .setPlatformName(buildConfiguration.getPlatformName())
-            .setId(id)
-            .build();
+        .setMnemonic(configProto.getMnemonic())
+        .setPlatformName(configProto.getPlatformName())
+        .setId(id)
+        .build();
   }
 
   @Override
diff --git a/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java b/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java
index e2447f1..9ff8d76 100644
--- a/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java
@@ -650,9 +650,9 @@
                     BuildConfiguration.Options.class)),
             "workspace");
     BuildEvent firstWithConfiguration =
-        new GenericConfigurationEvent(testId("first"), configuration);
+        new GenericConfigurationEvent(testId("first"), configuration.toBuildEvent());
     BuildEvent secondWithConfiguration =
-        new GenericConfigurationEvent(testId("second"), configuration);
+        new GenericConfigurationEvent(testId("second"), configuration.toBuildEvent());
 
     streamer.buildEvent(startEvent);
     streamer.buildEvent(firstWithConfiguration);
@@ -663,7 +663,7 @@
     assertThat(allEventsSeen).hasSize(7);
     assertThat(allEventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
     assertThat(allEventsSeen.get(1).getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
-    assertThat(allEventsSeen.get(2)).isEqualTo(configuration);
+    assertThat(allEventsSeen.get(2)).isEqualTo(configuration.toBuildEvent());
     assertThat(allEventsSeen.get(3).getEventId()).isEqualTo(BuildEventId.progressId(1));
     assertThat(allEventsSeen.get(4)).isEqualTo(firstWithConfiguration);
     assertThat(allEventsSeen.get(5).getEventId()).isEqualTo(BuildEventId.progressId(2));