Merge "doc: add reference to Gerrit review-strategy plugin" into stable-2.12
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index c1a5dd6..470c6b6 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -36,7 +36,7 @@
 ----
 mvn archetype:generate -DarchetypeGroupId=com.google.gerrit \
     -DarchetypeArtifactId=gerrit-plugin-archetype \
-    -DarchetypeVersion=2.12.3 \
+    -DarchetypeVersion=2.12.4 \
     -DgroupId=com.googlesource.gerrit.plugins.testplugin \
     -DartifactId=testplugin
 ----
diff --git a/ReleaseNotes/ReleaseNotes-2.11.10.txt b/ReleaseNotes/ReleaseNotes-2.11.10.txt
new file mode 100644
index 0000000..9ad34b6
--- /dev/null
+++ b/ReleaseNotes/ReleaseNotes-2.11.10.txt
@@ -0,0 +1,30 @@
+Release notes for Gerrit 2.11.10
+================================
+
+Gerrit 2.11.10 is now available:
+
+link:https://gerrit-releases.storage.googleapis.com/gerrit-2.11.10.war[
+https://gerrit-releases.storage.googleapis.com/gerrit-2.11.10.war]
+
+There are no schema changes from link:ReleaseNotes-2.11.9.html[2.11.9].
+
+Bug Fixes
+---------
+
+* Fix synchronization of Myers diff and Histogram diff invocations.
++
+The fix for
+link:https://code.google.com/p/gerrit/issues/detail?id=3361[Issue 3361]
+that was included in Gerrit versions 2.10.7 and 2.11.4 introduced a
+regression that prevented more than one file header diff from being
+computed at the same time across the entire server.
+
+* Fix `sshd.idleTimeout` setting being ignored.
++
+The `sshd.idleTimeout` setting was not being correctly set on the SSHD
+backend, causing idle sessions to not time out.
+
+* Add the correct license for AsciiDoctor.
++
+AsciiDoctor is licensed under the MIT License, not Apache2 as previously
+documented.
diff --git a/ReleaseNotes/ReleaseNotes-2.12.4.txt b/ReleaseNotes/ReleaseNotes-2.12.4.txt
index ce8651c..411011e 100644
--- a/ReleaseNotes/ReleaseNotes-2.12.4.txt
+++ b/ReleaseNotes/ReleaseNotes-2.12.4.txt
@@ -55,6 +55,19 @@
 
 == Bug Fixes
 
+* link:https://bugs.chromium.org/p/gerrit/issues/detail?id=4400[Issue 4400]:
+Fix `AlreadyClosedException` in Lucene index.
++
+If a Lucene indexing thread was interrupted by an SSH connection being
+closed, this would also close file handles being used to read the index.
++
+Lucene queries are now executed on background threads to isolate them
+from SSH threads.
++
+This may also reduce latency for user dashboards on a multi-core system as
+each query for the different sections can now run on separate threads and
+return results when ready.
+
 * link:https://bugs.chromium.org/p/gerrit/issues/detail?id=4249[Issue 4249]:
 Fix 'Duplicate stages not allowed' error during indexing.
 
@@ -80,7 +93,7 @@
 
 * Fix `sshd.idleTimeout` setting being ignored.
 +
-Ths `sshd.idleTimeout` setting was not being correctly set on the SSHD
+The `sshd.idleTimeout` setting was not being correctly set on the SSHD
 backend, causing idle sessions to not time out.
 
 * link:https://bugs.chromium.org/p/gerrit/issues/detail?id=4324[Issue 4324]:
@@ -102,3 +115,14 @@
 
 * link:https://bugs.chromium.org/p/gerrit/issues/detail?id=4332[Issue 4332]:
 Allow `local` as a valid TLD for outgoing emails.
+
+* Bypass hostname verification when `sendemail.sslVerify` is disabled.
+
+* link:https://bugs.chromium.org/p/gerrit/issues/detail?id=4398[Issue 4398]:
+Replication: Consider ref visibility when scheduling replication.
++
+It was possible for refs to be replicated to remotes despite not being
+visible to groups mentioned in the `authGroup` setting.
+
+* link::https://bugs.chromium.org/p/gerrit/issues/detail?id=4036[Issue 4036]:
+Fix hanging query when using `is:watched` without authentication.
diff --git a/ReleaseNotes/index.txt b/ReleaseNotes/index.txt
index e5294ac..b7446f1 100644
--- a/ReleaseNotes/index.txt
+++ b/ReleaseNotes/index.txt
@@ -13,6 +13,7 @@
 [[2_11]]
 Version 2.11.x
 --------------
+* link:ReleaseNotes-2.11.10.html[2.11.10]
 * link:ReleaseNotes-2.11.9.html[2.11.9]
 * link:ReleaseNotes-2.11.8.html[2.11.8]
 * link:ReleaseNotes-2.11.7.html[2.11.7]
diff --git a/VERSION b/VERSION
index 0138f8a..f005129 100644
--- a/VERSION
+++ b/VERSION
@@ -2,4 +2,4 @@
 # Used by :api_install and :api_deploy targets
 # when talking to the destination repository.
 #
-GERRIT_VERSION = '2.12.3'
+GERRIT_VERSION = '2.12.4'
diff --git a/gerrit-acceptance-framework/pom.xml b/gerrit-acceptance-framework/pom.xml
index 6841ace..50ef5c1 100644
--- a/gerrit-acceptance-framework/pom.xml
+++ b/gerrit-acceptance-framework/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-acceptance-framework</artifactId>
-  <version>2.12.3</version>
+  <version>2.12.4</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Acceptance Test Framework</name>
   <description>API for Gerrit Plugins</description>
diff --git a/gerrit-extension-api/pom.xml b/gerrit-extension-api/pom.xml
index 86c5bb7..ff88248 100644
--- a/gerrit-extension-api/pom.xml
+++ b/gerrit-extension-api/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-extension-api</artifactId>
-  <version>2.12.3</version>
+  <version>2.12.4</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Extension API</name>
   <description>API for Gerrit Extensions</description>
diff --git a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
index d703bed..fe37362 100644
--- a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
+++ b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
@@ -23,6 +23,7 @@
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.MINUTES;
 
+import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
@@ -58,6 +59,7 @@
 import com.google.gerrit.server.query.change.QueryOptions;
 import com.google.gwtorm.protobuf.ProtobufCodec;
 import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.OrmRuntimeException;
 import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
@@ -110,7 +112,9 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 /**
  * Secondary index implementation using Apache Lucene.
@@ -426,6 +430,20 @@
 
     @Override
     public ResultSet<ChangeData> read() throws OrmException {
+      if (Thread.interrupted()) {
+        Thread.currentThread().interrupt();
+        throw new OrmException("interupted");
+      }
+      return new ChangeDataResults(
+          executor.submit(new Callable<List<Document>>() {
+            @Override
+            public List<Document> call() throws OrmException {
+              return doRead();
+            }
+          }));
+    }
+
+    private List<Document> doRead() throws OrmException {
       IndexSearcher[] searchers = new IndexSearcher[indexes.size()];
       try {
         int realLimit = opts.start() + opts.limit();
@@ -436,31 +454,14 @@
         }
         TopDocs docs = TopDocs.merge(sort, realLimit, hits);
 
-        List<ChangeData> result =
+        List<Document> result =
             Lists.newArrayListWithCapacity(docs.scoreDocs.length);
         for (int i = opts.start(); i < docs.scoreDocs.length; i++) {
           ScoreDoc sd = docs.scoreDocs[i];
           Document doc = searchers[sd.shardIndex].doc(sd.doc, FIELDS);
-          result.add(toChangeData(doc));
+          result.add(doc);
         }
-
-        final List<ChangeData> r = Collections.unmodifiableList(result);
-        return new ResultSet<ChangeData>() {
-          @Override
-          public Iterator<ChangeData> iterator() {
-            return r.iterator();
-          }
-
-          @Override
-          public List<ChangeData> toList() {
-            return r;
-          }
-
-          @Override
-          public void close() {
-            // Do nothing.
-          }
-        };
+        return result;
       } catch (IOException e) {
         throw new OrmException(e);
       } finally {
@@ -477,6 +478,41 @@
     }
   }
 
+  private class ChangeDataResults implements ResultSet<ChangeData> {
+    private final Future<List<Document>> future;
+
+    ChangeDataResults(Future<List<Document>> future) {
+      this.future = future;
+    }
+
+    @Override
+    public Iterator<ChangeData> iterator() {
+      return toList().iterator();
+    }
+
+    @Override
+    public List<ChangeData> toList() {
+      try {
+        List<Document> docs = future.get();
+        List<ChangeData> result = new ArrayList<>(docs.size());
+        for (Document doc : docs) {
+          result.add(toChangeData(doc));
+        }
+        return result;
+      } catch (InterruptedException e) {
+        close();
+        throw new OrmRuntimeException(e);
+      } catch (ExecutionException e) {
+        Throwables.propagateIfPossible(e.getCause());
+        throw new OrmRuntimeException(e.getCause());
+      }
+    }
+
+    @Override
+    public void close() {
+      future.cancel(false /* do not interrupt Lucene */);
+    }
+  }
   private ChangeData toChangeData(Document doc) {
     BytesRef cb = doc.getBinaryValue(CHANGE_FIELD);
     if (cb == null) {
diff --git a/gerrit-plugin-api/pom.xml b/gerrit-plugin-api/pom.xml
index fa921fd..671d0e2 100644
--- a/gerrit-plugin-api/pom.xml
+++ b/gerrit-plugin-api/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-plugin-api</artifactId>
-  <version>2.12.3</version>
+  <version>2.12.4</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Plugin API</name>
   <description>API for Gerrit Plugins</description>
diff --git a/gerrit-plugin-archetype/pom.xml b/gerrit-plugin-archetype/pom.xml
index dc3c272..d39a9ca 100644
--- a/gerrit-plugin-archetype/pom.xml
+++ b/gerrit-plugin-archetype/pom.xml
@@ -20,7 +20,7 @@
 
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-plugin-archetype</artifactId>
-  <version>2.12.3</version>
+  <version>2.12.4</version>
   <name>Gerrit Code Review - Plugin Archetype</name>
   <description>Maven Archetype for Gerrit Plugins</description>
   <url>https://www.gerritcodereview.com/</url>
diff --git a/gerrit-plugin-gwt-archetype/pom.xml b/gerrit-plugin-gwt-archetype/pom.xml
index bbd4619..658aade 100644
--- a/gerrit-plugin-gwt-archetype/pom.xml
+++ b/gerrit-plugin-gwt-archetype/pom.xml
@@ -20,7 +20,7 @@
 
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-plugin-gwt-archetype</artifactId>
-  <version>2.12.3</version>
+  <version>2.12.4</version>
   <name>Gerrit Code Review - Web UI GWT Plugin Archetype</name>
   <description>Maven Archetype for Gerrit Web UI GWT Plugins</description>
   <url>https://www.gerritcodereview.com/</url>
diff --git a/gerrit-plugin-gwtui/pom.xml b/gerrit-plugin-gwtui/pom.xml
index 399dd99..9da7d9d 100644
--- a/gerrit-plugin-gwtui/pom.xml
+++ b/gerrit-plugin-gwtui/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-plugin-gwtui</artifactId>
-  <version>2.12.3</version>
+  <version>2.12.4</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Plugin GWT UI</name>
   <description>Common Classes for Gerrit GWT UI Plugins</description>
diff --git a/gerrit-plugin-js-archetype/pom.xml b/gerrit-plugin-js-archetype/pom.xml
index 4c022ff..30ad2fc 100644
--- a/gerrit-plugin-js-archetype/pom.xml
+++ b/gerrit-plugin-js-archetype/pom.xml
@@ -20,7 +20,7 @@
 
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-plugin-js-archetype</artifactId>
-  <version>2.12.3</version>
+  <version>2.12.4</version>
   <name>Gerrit Code Review - Web UI JavaScript Plugin Archetype</name>
   <description>Maven Archetype for Gerrit Web UI JavaScript Plugins</description>
   <url>https://www.gerritcodereview.com/</url>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
index a2c8b81..870ca040 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
@@ -29,6 +29,7 @@
 import com.google.gerrit.server.query.Predicate;
 import com.google.gerrit.server.query.QueryParseException;
 import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.OrmRuntimeException;
 import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -100,7 +101,12 @@
    */
   public List<QueryResult> queryChanges(List<Predicate<ChangeData>> queries)
       throws OrmException, QueryParseException {
-    return queryChanges(null, queries);
+    try {
+      return queryChanges(null, queries);
+    } catch (OrmRuntimeException e) {
+      throw new OrmException(e.getMessage(), e);
+    }
+
   }
 
   static {
diff --git a/gerrit-war/pom.xml b/gerrit-war/pom.xml
index 049c274..8a1445e 100644
--- a/gerrit-war/pom.xml
+++ b/gerrit-war/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-war</artifactId>
-  <version>2.12.3</version>
+  <version>2.12.4</version>
   <packaging>war</packaging>
   <name>Gerrit Code Review - WAR</name>
   <description>Gerrit WAR</description>