Propagate postable events further up

With the introduction of the ExtendedEventHandler, SkyFunctions were
given the possibility to post additional Postable events in addition
to the standard events. As SkyFunctions have to be restartable, events
are collected first and only posted after the function is finished.
Make sure that this also applies to postable events and they are not
dropped.

Change-Id: Ie1c3a0134935c75ea984fa2cc924e7327a9da81f
PiperOrigin-RevId: 158964337
diff --git a/src/main/java/com/google/devtools/build/skyframe/ValueWithMetadata.java b/src/main/java/com/google/devtools/build/skyframe/ValueWithMetadata.java
index 3b93434..7e1adda 100644
--- a/src/main/java/com/google/devtools/build/skyframe/ValueWithMetadata.java
+++ b/src/main/java/com/google/devtools/build/skyframe/ValueWithMetadata.java
@@ -15,10 +15,9 @@
 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.Order;
+import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
 import com.google.devtools.build.lib.util.Preconditions;
-
 import java.util.Objects;
-
 import javax.annotation.Nullable;
 
 /**
@@ -32,17 +31,23 @@
   private static final NestedSet<TaggedEvents> NO_EVENTS =
       NestedSetBuilder.<TaggedEvents>emptySet(Order.STABLE_ORDER);
 
+  private static final NestedSet<Postable> NO_POSTS =
+      NestedSetBuilder.<Postable>emptySet(Order.STABLE_ORDER);
+
   public ValueWithMetadata(SkyValue value) {
     this.value = value;
   }
 
-  /** Builds a value entry value that has an error (and no value value).
+  /**
+   * Builds a value entry value that has an error (and no value value).
    *
    * <p>This is intended only for use in alternative {@code MemoizingEvaluator} implementations.
    */
-  public static ValueWithMetadata error(ErrorInfo errorInfo,
-      NestedSet<TaggedEvents> transitiveEvents) {
-    return new ErrorInfoValue(errorInfo, null, transitiveEvents);
+  public static ValueWithMetadata error(
+      ErrorInfo errorInfo,
+      NestedSet<TaggedEvents> transitiveEvents,
+      NestedSet<Postable> transitivePostables) {
+    return new ErrorInfoValue(errorInfo, null, transitiveEvents, transitivePostables);
   }
 
   /**
@@ -54,15 +59,16 @@
   public static SkyValue normal(
       @Nullable SkyValue value,
       @Nullable ErrorInfo errorInfo,
-      NestedSet<TaggedEvents> transitiveEvents) {
+      NestedSet<TaggedEvents> transitiveEvents,
+      NestedSet<Postable> transitivePostables) {
     Preconditions.checkState(value != null || errorInfo != null,
         "Value and error cannot both be null");
     if (errorInfo == null) {
-      return transitiveEvents.isEmpty()
+      return (transitiveEvents.isEmpty() && transitivePostables.isEmpty())
           ? value
-          : ValueWithEvents.createValueWithEvents(value, transitiveEvents);
+          : ValueWithEvents.createValueWithEvents(value, transitiveEvents, transitivePostables);
     }
-    return new ErrorInfoValue(errorInfo, value, transitiveEvents);
+    return new ErrorInfoValue(errorInfo, value, transitiveEvents, transitivePostables);
   }
 
   @Nullable SkyValue getValue() {
@@ -74,22 +80,31 @@
 
   public abstract NestedSet<TaggedEvents> getTransitiveEvents();
 
+  public abstract NestedSet<Postable> getTransitivePostables();
+
   /** Implementation of {@link ValueWithMetadata} for the value case. */
   public static class ValueWithEvents extends ValueWithMetadata {
 
     private final NestedSet<TaggedEvents> transitiveEvents;
+    private final NestedSet<Postable> transitivePostables;
 
-    private ValueWithEvents(SkyValue value, NestedSet<TaggedEvents> transitiveEvents) {
+    private ValueWithEvents(
+        SkyValue value,
+        NestedSet<TaggedEvents> transitiveEvents,
+        NestedSet<Postable> transitivePostables) {
       super(Preconditions.checkNotNull(value));
       this.transitiveEvents = Preconditions.checkNotNull(transitiveEvents);
+      this.transitivePostables = Preconditions.checkNotNull(transitivePostables);
     }
 
-    public static ValueWithEvents createValueWithEvents(SkyValue value,
-            NestedSet<TaggedEvents> transitiveEvents) {
+    public static ValueWithEvents createValueWithEvents(
+        SkyValue value,
+        NestedSet<TaggedEvents> transitiveEvents,
+        NestedSet<Postable> transitivePostables) {
       if (value instanceof NotComparableSkyValue) {
-        return new NotComparableValueWithEvents(value, transitiveEvents);
+        return new NotComparableValueWithEvents(value, transitiveEvents, transitivePostables);
       } else {
-        return new ValueWithEvents(value, transitiveEvents);
+        return new ValueWithEvents(value, transitiveEvents, transitivePostables);
       }
     }
 
@@ -100,6 +115,11 @@
     @Override
     public NestedSet<TaggedEvents> getTransitiveEvents() { return transitiveEvents; }
 
+    @Override
+    public NestedSet<Postable> getTransitivePostables() {
+      return transitivePostables;
+    }
+
     /**
      * We override equals so that if the same value is written to a {@link NodeEntry} twice, it can
      * verify that the two values are equal, and avoid incrementing its version.
@@ -121,12 +141,16 @@
       // conservative than deep equals. Using shallow equals means that we may unnecessarily
       // consider some values unequal that are actually equal, but this is still a net win over
       // deep equals.
-      return value.equals(that.value) && transitiveEvents.shallowEquals(that.transitiveEvents);
+      return value.equals(that.value)
+          && transitiveEvents.shallowEquals(that.transitiveEvents)
+          && transitivePostables.shallowEquals(that.transitivePostables);
     }
 
     @Override
     public int hashCode() {
-      return 31 * value.hashCode() + transitiveEvents.shallowHashCode();
+      return 31 * value.hashCode()
+          + transitiveEvents.shallowHashCode()
+          + 3 * transitivePostables.shallowHashCode();
     }
 
     @Override
@@ -135,9 +159,11 @@
 
   private static final class NotComparableValueWithEvents extends ValueWithEvents
           implements NotComparableSkyValue {
-    private NotComparableValueWithEvents(SkyValue value,
-            NestedSet<TaggedEvents> transitiveEvents) {
-      super(value, transitiveEvents);
+    private NotComparableValueWithEvents(
+        SkyValue value,
+        NestedSet<TaggedEvents> transitiveEvents,
+        NestedSet<Postable> transitivePostables) {
+      super(value, transitiveEvents, transitivePostables);
     }
   }
 
@@ -151,12 +177,17 @@
 
     private final ErrorInfo errorInfo;
     private final NestedSet<TaggedEvents> transitiveEvents;
+    private final NestedSet<Postable> transitivePostables;
 
-    public ErrorInfoValue(ErrorInfo errorInfo, @Nullable SkyValue value,
-        NestedSet<TaggedEvents> transitiveEvents) {
+    public ErrorInfoValue(
+        ErrorInfo errorInfo,
+        @Nullable SkyValue value,
+        NestedSet<TaggedEvents> transitiveEvents,
+        NestedSet<Postable> transitivePostables) {
       super(value);
       this.errorInfo = Preconditions.checkNotNull(errorInfo);
       this.transitiveEvents = Preconditions.checkNotNull(transitiveEvents);
+      this.transitivePostables = Preconditions.checkNotNull(transitivePostables);
     }
 
     @Nullable
@@ -167,6 +198,11 @@
     public NestedSet<TaggedEvents> getTransitiveEvents() { return transitiveEvents; }
 
     @Override
+    public NestedSet<Postable> getTransitivePostables() {
+      return transitivePostables;
+    }
+
+    @Override
     public boolean equals(Object o) {
       if (this == o) {
         return true;
@@ -185,12 +221,15 @@
       // deep equals.
       return Objects.equals(this.value, that.value)
           && Objects.equals(this.errorInfo, that.errorInfo)
-          && transitiveEvents.shallowEquals(that.transitiveEvents);
+          && transitiveEvents.shallowEquals(that.transitiveEvents)
+          && transitivePostables.shallowEquals(that.transitivePostables);
     }
 
     @Override
     public int hashCode() {
-      return 31 * Objects.hash(value, errorInfo) + transitiveEvents.shallowHashCode();
+      return 31 * Objects.hash(value, errorInfo)
+          + transitiveEvents.shallowHashCode()
+          + 3 * transitivePostables.shallowHashCode();
     }
 
     @Override
@@ -220,7 +259,7 @@
     if (value instanceof ValueWithMetadata) {
       return (ValueWithMetadata) value;
     }
-    return ValueWithEvents.createValueWithEvents(value, NO_EVENTS);
+    return ValueWithEvents.createValueWithEvents(value, NO_EVENTS, NO_POSTS);
   }
 
   @Nullable
@@ -237,4 +276,11 @@
     }
     return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
   }
+
+  static NestedSet<Postable> getPosts(SkyValue value) {
+    if (value instanceof ValueWithMetadata) {
+      return ((ValueWithMetadata) value).getTransitivePostables();
+    }
+    return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
+  }
 }