You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2014/10/15 16:09:32 UTC

svn commit: r1632049 - in /lucene/dev/trunk/solr: ./ solrj/src/java/org/apache/solr/client/solrj/impl/ solrj/src/test/org/apache/solr/client/solrj/impl/

Author: shalin
Date: Wed Oct 15 14:09:31 2014
New Revision: 1632049

URL: http://svn.apache.org/r1632049
Log:
SOLR-4715: Add CloudSolrServer constructors which accept a HttpClient instance

Modified:
    lucene/dev/trunk/solr/CHANGES.txt
    lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java
    lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java
    lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java

Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1632049&r1=1632048&r2=1632049&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Wed Oct 15 14:09:31 2014
@@ -169,6 +169,9 @@ New Features
 * SOLR-6617: /update/json/docs path will use fully qualified node names by default
              (NOble Paul)
 
+* SOLR-4715: Add CloudSolrServer constructors which accept a HttpClient instance.
+  (Hardik Upadhyay, Shawn Heisey, shalin)
+
 Bug Fixes
 ----------------------
 

Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java?rev=1632049&r1=1632048&r2=1632049&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrServer.java Wed Oct 15 14:09:31 2014
@@ -96,6 +96,7 @@ public class CloudSolrServer extends Sol
   private final LBHttpSolrServer lbServer;
   private final boolean shutdownLBHttpSolrServer;
   private HttpClient myClient;
+  private final boolean clientIsInternal;
   //no of times collection state to be reloaded if stale state error is received
   private static final int MAX_STALE_RETRIES = 5;
   Random rand = new Random();
@@ -177,6 +178,7 @@ public class CloudSolrServer extends Sol
    */
   public CloudSolrServer(String zkHost) {
       this.zkHost = zkHost;
+      this.clientIsInternal = true;
       this.myClient = HttpClientUtil.createClient(null);
       this.lbServer = new LBHttpSolrServer(myClient);
       this.lbServer.setRequestWriter(new BinaryRequestWriter());
@@ -184,7 +186,41 @@ public class CloudSolrServer extends Sol
       this.updatesToLeaders = true;
       shutdownLBHttpSolrServer = true;
       lbServer.addQueryParams(STATE_VERSION);
+  }
 
+  /**
+   * Create a new client object that connects to Zookeeper and is always aware
+   * of the SolrCloud state. If there is a fully redundant Zookeeper quorum and
+   * SolrCloud has enough replicas for every shard in a collection, there is no
+   * single point of failure. Updates will be sent to shard leaders by default.
+   *
+   * @param zkHost
+   *          The client endpoint of the zookeeper quorum containing the cloud
+   *          state. The full specification for this string is one or more comma
+   *          separated HOST:PORT values, followed by an optional chroot value
+   *          that starts with a forward slash. Using a chroot allows multiple
+   *          applications to coexist in one ensemble. For full details, see the
+   *          Zookeeper documentation. Some examples:
+   *          <p/>
+   *          "host1:2181"
+   *          <p/>
+   *          "host1:2181,host2:2181,host3:2181/mysolrchroot"
+   *          <p/>
+   *          "zoo1.example.com:2181,zoo2.example.com:2181,zoo3.example.com:2181"
+   * @param httpClient
+   *          the {@see HttpClient} instance to be used for all requests. The
+   *          provided httpClient should use a multi-threaded connection manager.
+   */
+  public CloudSolrServer(String zkHost, HttpClient httpClient)  {
+    this.zkHost = zkHost;
+    this.clientIsInternal = httpClient == null;
+    this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
+    this.lbServer = new LBHttpSolrServer(myClient);
+    this.lbServer.setRequestWriter(new BinaryRequestWriter());
+    this.lbServer.setParser(new BinaryResponseParser());
+    this.updatesToLeaders = true;
+    shutdownLBHttpSolrServer = true;
+    lbServer.addQueryParams(STATE_VERSION);
   }
   
   /**
@@ -206,7 +242,31 @@ public class CloudSolrServer extends Sol
    * @see #CloudSolrServer(String)
    */
   public CloudSolrServer(Collection<String> zkHosts, String chroot) {
-    
+    this(zkHosts, chroot, null);
+  }
+
+  /**
+   * Create a new client object using multiple string values in a Collection
+   * instead of a standard zkHost connection string. Note that this method will
+   * not be used if there is only one String argument - that will use
+   * {@link #CloudSolrServer(String)} instead.
+   *
+   * @param zkHosts
+   *          A Java Collection (List, Set, etc) of HOST:PORT strings, one for
+   *          each host in the zookeeper ensemble. Note that with certain
+   *          Collection types like HashSet, the order of hosts in the final
+   *          connect string may not be in the same order you added them.
+   * @param chroot
+   *          A chroot value for zookeeper, starting with a forward slash. If no
+   *          chroot is required, use null.
+   * @param httpClient
+   *          the {@see HttpClient} instance to be used for all requests. The provided httpClient should use a
+   *          multi-threaded connection manager.
+   * @throws IllegalArgumentException
+   *           if the chroot value does not start with a forward slash.
+   * @see #CloudSolrServer(String)
+   */
+  public CloudSolrServer(Collection<String> zkHosts, String chroot, HttpClient httpClient) {
     StringBuilder zkBuilder = new StringBuilder();
     int lastIndexValue = zkHosts.size() - 1;
     int i = 0;
@@ -225,12 +285,13 @@ public class CloudSolrServer extends Sol
             "The chroot must start with a forward slash.");
       }
     }
-    
+
     /* Log the constructed connection string and then initialize. */
     log.info("Final constructed zkHost string: " + zkBuilder.toString());
-    
+
     this.zkHost = zkBuilder.toString();
-    this.myClient = HttpClientUtil.createClient(null);
+    this.clientIsInternal = httpClient == null;
+    this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
     this.lbServer = new LBHttpSolrServer(myClient);
     this.lbServer.setRequestWriter(new BinaryRequestWriter());
     this.lbServer.setParser(new BinaryResponseParser());
@@ -246,8 +307,23 @@ public class CloudSolrServer extends Sol
    * @see #CloudSolrServer(String) for full description and details on zkHost
    */
   public CloudSolrServer(String zkHost, boolean updatesToLeaders) {
+    this(zkHost, updatesToLeaders, null);
+  }
+
+  /**
+   * @param zkHost
+   *          A zookeeper client endpoint.
+   * @param updatesToLeaders
+   *          If true, sends updates only to shard leaders.
+   * @param httpClient
+   *          the {@see HttpClient} instance to be used for all requests. The provided httpClient should use a
+   *          multi-threaded connection manager.
+   * @see #CloudSolrServer(String) for full description and details on zkHost
+   */
+  public CloudSolrServer(String zkHost, boolean updatesToLeaders, HttpClient httpClient) {
     this.zkHost = zkHost;
-    this.myClient = HttpClientUtil.createClient(null);
+    this.clientIsInternal = httpClient == null;
+    this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
     this.lbServer = new LBHttpSolrServer(myClient);
     this.lbServer.setRequestWriter(new BinaryRequestWriter());
     this.lbServer.setParser(new BinaryResponseParser());
@@ -289,8 +365,8 @@ public class CloudSolrServer extends Sol
     this.lbServer = lbServer;
     this.updatesToLeaders = updatesToLeaders;
     shutdownLBHttpSolrServer = false;
+    this.clientIsInternal = false;
     lbServer.addQueryParams(STATE_VERSION);
-
   }
   
   public ResponseParser getParser() {
@@ -978,7 +1054,7 @@ public class CloudSolrServer extends Sol
       lbServer.shutdown();
     }
     
-    if (myClient!=null) {
+    if (clientIsInternal && myClient!=null) {
       myClient.getConnectionManager().shutdown();
     }
 

Modified: lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java?rev=1632049&r1=1632048&r2=1632049&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java (original)
+++ lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrServer.java Wed Oct 15 14:09:31 2014
@@ -45,8 +45,9 @@ import java.util.*;
  * Do <b>NOT</b> use this class for indexing in master/slave scenarios since documents must be sent to the
  * correct master; no inter-node routing is done.
  *
- * In SolrCloud (leader/replica) scenarios, this class may be used for updates since updates will be forwarded
- * to the appropriate leader.
+ * In SolrCloud (leader/replica) scenarios, it is usually better to use
+ * {@link org.apache.solr.client.solrj.impl.CloudSolrServer}, but this class may be used
+ * for updates because the server will forward them to the appropriate leader.
  *
  * Also see the <a href="http://wiki.apache.org/solr/LBHttpSolrServer">wiki</a> page.
  *
@@ -631,6 +632,9 @@ public class LBHttpSolrServer extends So
     };
   }
 
+  /**
+   * Return the HttpClient this instance uses.
+   */
   public HttpClient getHttpClient() {
     return httpClient;
   }
@@ -638,11 +642,29 @@ public class LBHttpSolrServer extends So
   public ResponseParser getParser() {
     return parser;
   }
-  
+
+  /**
+   * Changes the {@link ResponseParser} that will be used for the internal
+   * SolrServer objects. Throws an exception if used after internal server
+   * objects have been added, so if you want to use this method, you must
+   * not put any URLs in your constructor.
+   *
+   * @param parser Default Response Parser chosen to parse the response if the parser
+   *               were not specified as part of the request.
+   * @see org.apache.solr.client.solrj.SolrRequest#getResponseParser()
+   */
   public void setParser(ResponseParser parser) {
     this.parser = parser;
   }
-  
+
+  /**
+   * Changes the {@link RequestWriter} that will be used for the internal
+   * SolrServer objects. Throws an exception if used after internal server
+   * objects have been added, so if you want to use this method, you must
+   * not put any URLs in your constructor.
+   *
+   * @param requestWriter Default RequestWriter, used to encode requests sent to the server.
+   */
   public void setRequestWriter(RequestWriter requestWriter) {
     this.requestWriter = requestWriter;
   }

Modified: lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java?rev=1632049&r1=1632048&r2=1632049&view=diff
==============================================================================
--- lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java (original)
+++ lucene/dev/trunk/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrServerTest.java Wed Oct 15 14:09:31 2014
@@ -32,6 +32,7 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
+import org.apache.http.client.HttpClient;
 import org.apache.lucene.util.LuceneTestCase.Slow;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
@@ -122,6 +123,7 @@ public class CloudSolrServerTest extends
   public void doTest() throws Exception {
     allTests();
     stateVersionParamTest();
+    customHttpClientTest();
   }
 
   private void allTests() throws Exception {
@@ -439,4 +441,20 @@ public class CloudSolrServerTest extends
     // see SOLR-6146 - this test will fail by virtue of the zkClient tracking performed
     // in the afterClass method of the base class
   }
+
+  public void customHttpClientTest() {
+    CloudSolrServer server = null;
+    ModifiableSolrParams params = new ModifiableSolrParams();
+    params.set(HttpClientUtil.PROP_SO_TIMEOUT, 1000);
+    HttpClient client = null;
+
+    try {
+      client = HttpClientUtil.createClient(params);
+      server = new CloudSolrServer(zkServer.getZkAddress(), client);
+      assertTrue(server.getLbServer().getHttpClient() == client);
+    } finally {
+      server.shutdown();
+      client.getConnectionManager().shutdown();
+    }
+  }
 }