ES: Adds configuration for the JEST client

Adds new gerrit.config parameters that allows configure JEST client.

Additionally it also moves all Elasticsearch related configuration
options into dedicated section.

Change-Id: I4c6e68783a64273a3de20ec8392d875c28ae7e80
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index a08ee39..a408e75 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -2550,7 +2550,7 @@
 A link:http://lucene.apache.org/[Lucene] index is used.
 +
 +
-* `ELASTICSEARCH`
+* `ELASTICSEARCH` look into link:#elasticsearch[Elasticsearch section]
 +
 An link:http://www.elasticsearch.org/[Elasticsearch] index is used.
 
@@ -2677,21 +2677,16 @@
   maxBufferedDocs = 500
 ----
 
-
-==== Elasticsearch configuration
+[[elasticsearch]]
+=== Section elasticsearch
 
 WARNING: The Elasticsearch support is incomplete. Online reindexing
-is not implemented yet.
+is still considered as beta.
 
 Open and closed changes are indexed in a single index, separated
 into types 'open_changes' and 'closed_changes' respectively.
 
-The following settings are only used when the index type is
-`ELASTICSEARCH`. To configure Elasticsearch servers look into
-link:#elasticsearch[Elasticsearch section]
-
-
-[[index.prefix]]index.prefix::
+[[elasticsearch.prefix]]elasticsearch.prefix::
 +
 This setting can be used to prefix index names to allow multiple Gerrit
 instances in a single Elasticsearch cluster. Prefix 'gerrit1_' would result in a
@@ -2699,13 +2694,57 @@
 +
 Not set by default.
 
-[[elasticsearch]]
-=== Section elasticsearch
+[[elasticsearch.username]]elasticsearch.username::
++
+Username used to connect to Elasticsearch.
++
+Not set by default.
 
-WARNING: The Elasticsearch support is incomplete. Online reindexing
-is not implemented yet.
+[[elasticsearch.password]]elasticsearch.password::
++
+Password used to connect to Elasticsearch.
++
+Not set by default.
 
-Each section correspond to the one Elasticsearch server.
+[[elasticsearch.requestCompression]]elasticsearch.requestCompression::
++
+Enable request compression.
++
+Defaults to `false`.
+
+[[elasticsearch.connectionTimeout]]elasticsearch.connectionTimeout::
++
+How long should Gerrit waits for connection.
++
+The value is in the usual time-unit format like "1 m", "5 m".
++
+Defaults to `5 m`
+
+[[elasticsearch.maxConnectionIdleTime]]elasticsearch.maxConnectionIdleTime::
++
+How long connection can stay in idle.
++
+The value is in the usual time-unit format like "1 m", "5 m".
++
+Defaults to `5 m`
+
+[[elasticsearch.maxTotalConnection]]elasticsearch.maxTotalConnection::
++
+How many connections can be spawn simultaneously.
++
+Defaults to `1`
+
+[[elasticsearch.maxReadTimeout]]elasticsearch.maxReadTimeout::
++
+Timeout for the read operation.
++
+The value is in the usual time-unit format like "1 m", "5 m".
++
+Defaults to `5 m`
+
+===== Elasticsearch server(s) configuration
+
+Each section correspond to one Elasticsearch server.
 
 [[elasticsearch.name.protocol]]elasticsearch.name.protocol::
 +
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index fbe7788..c813d2b 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -83,7 +83,7 @@
     this.indexName =
         String.format(
             "%s%s%04d",
-            Strings.nullToEmpty(cfg.getString("index", null, "prefix")),
+            Strings.nullToEmpty(cfg.getString("elasticsearch", null, "prefix")),
             indexName,
             schema.getVersion());
     this.client = clientBuilder.build();
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
index 1099f53..7ae49c7 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
@@ -24,6 +24,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import org.eclipse.jgit.lib.Config;
 
 @Singleton
@@ -33,9 +34,29 @@
   private static final String DEFAULT_PROTOCOL = "http";
 
   final List<String> urls;
+  final String username;
+  final String password;
+  final boolean requestCompression;
+  final long connectionTimeout;
+  final long maxConnectionIdleTime;
+  final TimeUnit maxConnectionIdleUnit = TimeUnit.MILLISECONDS;
+  final int maxTotalConnection;
+  final int readTimeout;
 
   @Inject
   ElasticConfiguration(@GerritServerConfig Config cfg) {
+    this.username = cfg.getString("elasticsearch", null, "username");
+    this.password = cfg.getString("elasticsearch", null, "password");
+    this.requestCompression = cfg.getBoolean("elasticsearch", null, "requestCompression", false);
+    this.connectionTimeout =
+        cfg.getTimeUnit("elasticsearch", null, "connectionTimeout", 3000, TimeUnit.MILLISECONDS);
+    this.maxConnectionIdleTime =
+        cfg.getTimeUnit(
+            "elasticsearch", null, "maxConnectionIdleTime", 3000, TimeUnit.MILLISECONDS);
+    this.maxTotalConnection = cfg.getInt("elasticsearch", null, "maxTotalConnection", 1);
+    this.readTimeout =
+        (int) cfg.getTimeUnit("elasticsearch", null, "readTimeout", 3000, TimeUnit.MICROSECONDS);
+
     Set<String> subsections = cfg.getSubsections("elasticsearch");
     if (subsections.isEmpty()) {
       this.urls = Arrays.asList(buildUrl(DEFAULT_PROTOCOL, DEFAULT_HOST, DEFAULT_PORT));
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/JestClientBuilder.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/JestClientBuilder.java
index 61517c7..c548cb9 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/JestClientBuilder.java
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/JestClientBuilder.java
@@ -18,6 +18,7 @@
 import com.google.inject.Singleton;
 import io.searchbox.client.JestClientFactory;
 import io.searchbox.client.config.HttpClientConfig;
+import io.searchbox.client.config.HttpClientConfig.Builder;
 import io.searchbox.client.http.JestHttpClient;
 import java.util.concurrent.TimeUnit;
 
@@ -32,12 +33,22 @@
 
   JestHttpClient build() {
     JestClientFactory factory = new JestClientFactory();
-    factory.setHttpClientConfig(
+    Builder builder =
         new HttpClientConfig.Builder(cfg.urls)
             .multiThreaded(true)
             .discoveryEnabled(false)
-            .discoveryFrequency(1L, TimeUnit.MINUTES)
-            .build());
+            .connTimeout((int) cfg.connectionTimeout)
+            .maxConnectionIdleTime(cfg.maxConnectionIdleTime, cfg.maxConnectionIdleUnit)
+            .maxTotalConnection(cfg.maxTotalConnection)
+            .readTimeout(cfg.readTimeout)
+            .requestCompressionEnabled(cfg.requestCompression)
+            .discoveryFrequency(1L, TimeUnit.MINUTES);
+
+    if (cfg.username != null && cfg.password != null) {
+      builder.defaultCredentials(cfg.username, cfg.password);
+    }
+
+    factory.setHttpClientConfig(builder.build());
     return (JestHttpClient) factory.getObject();
   }
 }