Fix race condition in checking topic mergeability

The list of changes in the topic is looked up using the secondary
index, which prepopulates the mergeable field on the ChangeData. This
value may be stale, as it is just a boolean yes/no, suitable
primarily for rendering the search results list. In particular, it
may not reflect the current state of the branch tip, if the
ReindexAfterUpdate queue has not yet been fully processed.

ActionsIT was hitting this race condition by submitting a change then
immediately checking the mergeability of a change conflicting with the
new branch tip. The mergeability of this second change should switch
from true to false as a result (blocking submission of the whole
topic). Because of this race condition, it was indeterminate which
mergeability bit would be returned from the search index.

The workaround for now is to allow explicitly clearing the mergeable
bit in ChangeData. A more robust change would be to tweak the index
system to say we want to prepopulate the ChangeData with fewer stored
fields from the index. As InternalChangeQuery is used more, this may
become more and more important.

Change-Id: I847c7896371451b85a05f4d768b805b953b61466
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java
index b53d193..66c99f1 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java
@@ -19,7 +19,6 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.client.SubmitType;
 import com.google.gerrit.extensions.common.ActionInfo;
 import com.google.gerrit.testutil.ConfigSuite;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
index 3cba4be..f7fab69 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
@@ -260,6 +260,11 @@
         if (!changeControl.canSubmit()) {
           return BLOCKED_TOPIC_TOOLTIP;
         }
+        // Recheck mergeability rather than using value stored in the index,
+        // which may be stale.
+        // TODO(dborowitz): This is ugly; consider providing a way to not read
+        // stored fields from the index in the first place.
+        c.setMergeable(null);
         if (!c.isMergeable()) {
           return CLICK_FAILURE_OTHER_TOOLTIP;
         }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
index 3c24dd2..802cf65 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -602,7 +602,7 @@
     return submitRecords;
   }
 
-  public void setMergeable(boolean mergeable) {
+  public void setMergeable(Boolean mergeable) {
     this.mergeable = mergeable;
   }