{"action":"opened","issue":{"url":"https://api.github.com/repos/sudheer4b3/PracticeAlgoDsNow/issues/1","repository_url":"https://api.github.com/repos/sudheer4b3/PracticeAlgoDsNow","labels_url":"https://api.github.com/repos/sudheer4b3/PracticeAlgoDsNow/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/sudheer4b3/PracticeAlgoDsNow/issues/1/comments","events_url":"https://api.github.com/repos/sudheer4b3/PracticeAlgoDsNow/issues/1/events","html_url":"https://github.com/sudheer4b3/PracticeAlgoDsNow/issues/1","id":308936826,"number":1,"title":"To Me LB","user":{"login":"sudheer4b3","id":19250358,"avatar_url":"https://avatars3.githubusercontent.com/u/19250358?v=4","gravatar_id":"","url":"https://api.github.com/users/sudheer4b3","html_url":"https://github.com/sudheer4b3","followers_url":"https://api.github.com/users/sudheer4b3/followers","following_url":"https://api.github.com/users/sudheer4b3/following{/other_user}","gists_url":"https://api.github.com/users/sudheer4b3/gists{/gist_id}","starred_url":"https://api.github.com/users/sudheer4b3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sudheer4b3/subscriptions","organizations_url":"https://api.github.com/users/sudheer4b3/orgs","repos_url":"https://api.github.com/users/sudheer4b3/repos","events_url":"https://api.github.com/users/sudheer4b3/events{/privacy}","received_events_url":"https://api.github.com/users/sudheer4b3/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-03-27T11:54:28Z","updated_at":"2018-03-27T11:54:28Z","closed_at":null,"author_association":"OWNER","body":"/*\r\n * Licensed to the Apache Software Foundation (ASF) under one or more\r\n * contributor license agreements.  See the NOTICE file distributed with\r\n * this work for additional information regarding copyright ownership.\r\n * The ASF licenses this file to You under the Apache License, Version 2.0\r\n * (the \"License\"); you may not use this file except in compliance with\r\n * the License.  You may obtain a copy of the License at\r\n *\r\n *     http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\npackage org.apache.solr.client.solrj.impl;\r\n\r\nimport org.apache.http.client.HttpClient;\r\nimport org.apache.solr.client.solrj.*;\r\nimport org.apache.solr.client.solrj.request.RequestWriter;\r\nimport org.apache.solr.client.solrj.response.QueryResponse;\r\nimport org.apache.solr.common.params.ModifiableSolrParams;\r\nimport org.apache.solr.common.util.NamedList;\r\nimport org.apache.solr.common.util.SolrjNamedThreadFactory;\r\nimport org.apache.solr.common.SolrException;\r\n\r\nimport java.io.IOException;\r\nimport java.lang.ref.WeakReference;\r\nimport java.net.MalformedURLException;\r\nimport java.net.SocketException;\r\nimport java.net.SocketTimeoutException;\r\nimport java.net.URL;\r\nimport java.util.concurrent.*;\r\nimport java.util.concurrent.atomic.AtomicInteger;\r\nimport java.util.*;\r\n\r\n/**\r\n * LBHttpSolrServer or \"LoadBalanced HttpSolrServer\" is a load balancing wrapper around\r\n * {@link org.apache.solr.client.solrj.impl.HttpSolrServer}. This is useful when you\r\n * have multiple SolrServers and the requests need to be Load Balanced among them.\r\n *\r\n * Do <b>NOT</b> use this class for indexing in master/slave scenarios since documents must be sent to the\r\n * correct master; no inter-node routing is done.\r\n *\r\n * In SolrCloud (leader/replica) scenarios, this class may be used for updates since updates will be forwarded\r\n * to the appropriate leader.\r\n *\r\n * Also see the <a href=\"http://wiki.apache.org/solr/LBHttpSolrServer\">wiki</a> page.\r\n *\r\n * <p/>\r\n * It offers automatic failover when a server goes down and it detects when the server comes back up.\r\n * <p/>\r\n * Load balancing is done using a simple round-robin on the list of servers.\r\n * <p/>\r\n * If a request to a server fails by an IOException due to a connection timeout or read timeout then the host is taken\r\n * off the list of live servers and moved to a 'dead server list' and the request is resent to the next live server.\r\n * This process is continued till it tries all the live servers. If at least one server is alive, the request succeeds,\r\n * and if not it fails.\r\n * <blockquote><pre>\r\n * SolrServer lbHttpSolrServer = new LBHttpSolrServer(\"http://host1:8080/solr/\",\"http://host2:8080/solr\",\"http://host2:8080/solr\");\r\n * //or if you wish to pass the HttpClient do as follows\r\n * httpClient httpClient =  new HttpClient();\r\n * SolrServer lbHttpSolrServer = new LBHttpSolrServer(httpClient,\"http://host1:8080/solr/\",\"http://host2:8080/solr\",\"http://host2:8080/solr\");\r\n * </pre></blockquote>\r\n * This detects if a dead server comes alive automatically. The check is done in fixed intervals in a dedicated thread.\r\n * This interval can be set using {@link #setAliveCheckInterval} , the default is set to one minute.\r\n * <p/>\r\n * <b>When to use this?</b><br/> This can be used as a software load balancer when you do not wish to setup an external\r\n * load balancer. Alternatives to this code are to use\r\n * a dedicated hardware load balancer or using Apache httpd with mod_proxy_balancer as a load balancer. See <a\r\n * href=\"http://en.wikipedia.org/wiki/Load_balancing_(computing)\">Load balancing on Wikipedia</a>\r\n *\r\n * @since solr 1.4\r\n */\r\npublic class LBHttpSolrServer extends SolrServer {\r\n\r\n\r\n  // keys to the maps are currently of the form \"http://localhost:8983/solr\"\r\n  // which should be equivalent to CommonsHttpSolrServer.getBaseURL()\r\n  private final Map<String, ServerWrapper> aliveServers = new LinkedHashMap<String, ServerWrapper>();\r\n  // access to aliveServers should be synchronized on itself\r\n  \r\n  protected final Map<String, ServerWrapper> zombieServers = new ConcurrentHashMap<String, ServerWrapper>();\r\n\r\n  // changes to aliveServers are reflected in this array, no need to synchronize\r\n  private volatile ServerWrapper[] aliveServerList = new ServerWrapper[0];\r\n\r\n\r\n  private ScheduledExecutorService aliveCheckExecutor;\r\n\r\n  private final HttpClient httpClient;\r\n  private final boolean clientIsInternal;\r\n  private final AtomicInteger counter = new AtomicInteger(-1);\r\n\r\n  private static final SolrQuery solrQuery = new SolrQuery(\"*:*\");\r\n  private volatile ResponseParser parser;\r\n  private volatile RequestWriter requestWriter;\r\n\r\n  private Set<String> queryParams;\r\n\r\n  static {\r\n    solrQuery.setRows(0);\r\n  }\r\n\r\n  protected static class ServerWrapper {\r\n    final HttpSolrServer solrServer;\r\n\r\n    long lastUsed;     // last time used for a real request\r\n    long lastChecked;  // last time checked for liveness\r\n\r\n    // \"standard\" servers are used by default.  They normally live in the alive list\r\n    // and move to the zombie list when unavailable.  When they become available again,\r\n    // they move back to the alive list.\r\n    boolean standard = true;\r\n\r\n    int failedPings = 0;\r\n\r\n    public ServerWrapper(HttpSolrServer solrServer) {\r\n      this.solrServer = solrServer;\r\n    }\r\n\r\n    @Override\r\n    public String toString() {\r\n      return solrServer.getBaseURL();\r\n    }\r\n\r\n    public String getKey() {\r\n      return solrServer.getBaseURL();\r\n    }\r\n\r\n    @Override\r\n    public int hashCode() {\r\n      return this.getKey().hashCode();\r\n    }\r\n\r\n    @Override\r\n    public boolean equals(Object obj) {\r\n      if (this == obj) return true;\r\n      if (!(obj instanceof ServerWrapper)) return false;\r\n      return this.getKey().equals(((ServerWrapper)obj).getKey());\r\n    }\r\n  }\r\n\r\n  public static class Req {\r\n    protected SolrRequest request;\r\n    protected List<String> servers;\r\n    protected int numDeadServersToTry;\r\n\r\n    public Req(SolrRequest request, List<String> servers) {\r\n      this.request = request;\r\n      this.servers = servers;\r\n      this.numDeadServersToTry = servers.size();\r\n    }\r\n\r\n    public SolrRequest getRequest() {\r\n      return request;\r\n    }\r\n    public List<String> getServers() {\r\n      return servers;\r\n    }\r\n\r\n    /** @return the number of dead servers to try if there are no live servers left */\r\n    public int getNumDeadServersToTry() {\r\n      return numDeadServersToTry;\r\n    }\r\n\r\n    /** @param numDeadServersToTry The number of dead servers to try if there are no live servers left.\r\n     * Defaults to the number of servers in this request. */\r\n    public void setNumDeadServersToTry(int numDeadServersToTry) {\r\n      this.numDeadServersToTry = numDeadServersToTry;\r\n    }\r\n  }\r\n\r\n  public static class Rsp {\r\n    protected String server;\r\n    protected NamedList<Object> rsp;\r\n\r\n    /** The response from the server */\r\n    public NamedList<Object> getResponse() {\r\n      return rsp;\r\n    }\r\n\r\n    /** The server that returned the response */\r\n    public String getServer() {\r\n      return server;\r\n    }\r\n  }\r\n\r\n  public LBHttpSolrServer(String... solrServerUrls) throws MalformedURLException {\r\n    this(null, solrServerUrls);\r\n  }\r\n  \r\n  /** The provided httpClient should use a multi-threaded connection manager */ \r\n  public LBHttpSolrServer(HttpClient httpClient, String... solrServerUrl)\r\n          throws MalformedURLException {\r\n    this(httpClient, new BinaryResponseParser(), solrServerUrl);\r\n  }\r\n\r\n  /** The provided httpClient should use a multi-threaded connection manager */  \r\n  public LBHttpSolrServer(HttpClient httpClient, ResponseParser parser, String... solrServerUrl)\r\n          throws MalformedURLException {\r\n    clientIsInternal = (httpClient == null);\r\n    this.parser = parser;\r\n    if (httpClient == null) {\r\n      ModifiableSolrParams params = new ModifiableSolrParams();\r\n      params.set(HttpClientUtil.PROP_USE_RETRY, false);\r\n      this.httpClient = HttpClientUtil.createClient(params);\r\n    } else {\r\n      this.httpClient = httpClient;\r\n    }\r\n    for (String s : solrServerUrl) {\r\n      ServerWrapper wrapper = new ServerWrapper(makeServer(s));\r\n      aliveServers.put(wrapper.getKey(), wrapper);\r\n    }\r\n    updateAliveList();\r\n  }\r\n  \r\n  public Set<String> getQueryParams() {\r\n    return queryParams;\r\n  }\r\n\r\n  /**\r\n   * Expert Method.\r\n   * @param queryParams set of param keys to only send via the query string\r\n   */\r\n  public void setQueryParams(Set<String> queryParams) {\r\n    this.queryParams = queryParams;\r\n  }\r\n\r\n  public static String normalize(String server) {\r\n    if (server.endsWith(\"/\"))\r\n      server = server.substring(0, server.length() - 1);\r\n    return server;\r\n  }\r\n\r\n  protected HttpSolrServer makeServer(String server) throws MalformedURLException {\r\n    HttpSolrServer s = new HttpSolrServer(server, httpClient, parser);\r\n    if (requestWriter != null) {\r\n      s.setRequestWriter(requestWriter);\r\n    }\r\n    if (queryParams != null) {\r\n      s.setQueryParams(queryParams);\r\n    }\r\n    return s;\r\n  }\r\n\r\n  /**\r\n   * Tries to query a live server from the list provided in Req. Servers in the dead pool are skipped.\r\n   * If a request fails due to an IOException, the server is moved to the dead pool for a certain period of\r\n   * time, or until a test request on that server succeeds.\r\n   *\r\n   * Servers are queried in the exact order given (except servers currently in the dead pool are skipped).\r\n   * If no live servers from the provided list remain to be tried, a number of previously skipped dead servers will be tried.\r\n   * Req.getNumDeadServersToTry() controls how many dead servers will be tried.\r\n   *\r\n   * If no live servers are found a SolrServerException is thrown.\r\n   *\r\n   * @param req contains both the request as well as the list of servers to query\r\n   *\r\n   * @return the result of the request\r\n   *\r\n   * @throws IOException If there is a low-level I/O error.\r\n   */\r\n  public Rsp request(Req req) throws SolrServerException, IOException {\r\n    Rsp rsp = new Rsp();\r\n    Exception ex = null;\r\n\r\n    List<ServerWrapper> skipped = new ArrayList<ServerWrapper>(req.getNumDeadServersToTry());\r\n\r\n    for (String serverStr : req.getServers()) {\r\n      serverStr = normalize(serverStr);\r\n      // if the server is currently a zombie, just skip to the next one\r\n      ServerWrapper wrapper = zombieServers.get(serverStr);\r\n      if (wrapper != null) {\r\n        // System.out.println(\"ZOMBIE SERVER QUERIED: \" + serverStr);\r\n        if (skipped.size() < req.getNumDeadServersToTry())\r\n          skipped.add(wrapper);\r\n        continue;\r\n      }\r\n      rsp.server = serverStr;\r\n      HttpSolrServer server = makeServer(serverStr);\r\n\r\n      try {\r\n        rsp.rsp = server.request(req.getRequest());\r\n        return rsp; // SUCCESS\r\n      } catch (SolrException e) {\r\n        // we retry on 404 or 403 or 503 - you can see this on solr shutdown\r\n        if (e.code() == 404 || e.code() == 403 || e.code() == 503 || e.code() == 500) {\r\n          ex = addZombie(server, e);\r\n        } else {\r\n          // Server is alive but the request was likely malformed or invalid\r\n          throw e;\r\n        }\r\n       \r\n       // TODO: consider using below above - currently does cause a problem with distrib updates:\r\n       // seems to match up against a failed forward to leader exception as well...\r\n       //     || e.getMessage().contains(\"java.net.SocketException\")\r\n       //     || e.getMessage().contains(\"java.net.ConnectException\")\r\n      } catch (SocketException e) {\r\n        ex = addZombie(server, e);\r\n      } catch (SocketTimeoutException e) {\r\n        ex = addZombie(server, e);\r\n      } catch (SolrServerException e) {\r\n        Throwable rootCause = e.getRootCause();\r\n        if (rootCause instanceof IOException) {\r\n          ex = addZombie(server, e);\r\n        } else {\r\n          throw e;\r\n        }\r\n      } catch (Exception e) {\r\n        throw new SolrServerException(e);\r\n      }\r\n    }\r\n\r\n    // try the servers we previously skipped\r\n    for (ServerWrapper wrapper : skipped) {\r\n      try {\r\n        rsp.rsp = wrapper.solrServer.request(req.getRequest());\r\n        zombieServers.remove(wrapper.getKey());\r\n        return rsp; // SUCCESS\r\n      } catch (SolrException e) {\r\n        // we retry on 404 or 403 or 503 - you can see this on solr shutdown\r\n        if (e.code() == 404 || e.code() == 403 || e.code() == 503 || e.code() == 500) {\r\n          ex = e;\r\n          // already a zombie, no need to re-add\r\n        } else {\r\n          // Server is alive but the request was malformed or invalid\r\n          zombieServers.remove(wrapper.getKey());\r\n          throw e;\r\n        }\r\n\r\n      } catch (SocketException e) {\r\n        ex = e;\r\n      } catch (SocketTimeoutException e) {\r\n        ex = e;\r\n      } catch (SolrServerException e) {\r\n        Throwable rootCause = e.getRootCause();\r\n        if (rootCause instanceof IOException) {\r\n          ex = e;\r\n          // already a zombie, no need to re-add\r\n        } else {\r\n          throw e;\r\n        }\r\n      } catch (Exception e) {\r\n        throw new SolrServerException(e);\r\n      }\r\n    }\r\n\r\n\r\n    if (ex == null) {\r\n      throw new SolrServerException(\"No live SolrServers available to handle this request\");\r\n    } else {\r\n      throw new SolrServerException(\"No live SolrServers available to handle this request:\" + zombieServers.keySet(), ex);\r\n    }\r\n\r\n  }\r\n\r\n  protected Exception addZombie(HttpSolrServer server, Exception e) {\r\n\r\n    ServerWrapper wrapper;\r\n\r\n    wrapper = new ServerWrapper(server);\r\n    wrapper.lastUsed = System.currentTimeMillis();\r\n    wrapper.standard = false;\r\n    zombieServers.put(wrapper.getKey(), wrapper);\r\n    startAliveCheckExecutor();\r\n    return e;\r\n  }  \r\n\r\n\r\n\r\n  private void updateAliveList() {\r\n    synchronized (aliveServers) {\r\n      aliveServerList = aliveServers.values().toArray(new ServerWrapper[aliveServers.size()]);\r\n    }\r\n  }\r\n\r\n  private ServerWrapper removeFromAlive(String key) {\r\n    synchronized (aliveServers) {\r\n      ServerWrapper wrapper = aliveServers.remove(key);\r\n      if (wrapper != null)\r\n        updateAliveList();\r\n      return wrapper;\r\n    }\r\n  }\r\n\r\n  private void addToAlive(ServerWrapper wrapper) {\r\n    synchronized (aliveServers) {\r\n      ServerWrapper prev = aliveServers.put(wrapper.getKey(), wrapper);\r\n      // TODO: warn if there was a previous entry?\r\n      updateAliveList();\r\n    }\r\n  }\r\n\r\n  public void addSolrServer(String server) throws MalformedURLException {\r\n    HttpSolrServer solrServer = makeServer(server);\r\n    addToAlive(new ServerWrapper(solrServer));\r\n  }\r\n\r\n  public String removeSolrServer(String server) {\r\n    try {\r\n      server = new URL(server).toExternalForm();\r\n    } catch (MalformedURLException e) {\r\n      throw new RuntimeException(e);\r\n    }\r\n    if (server.endsWith(\"/\")) {\r\n      server = server.substring(0, server.length() - 1);\r\n    }\r\n\r\n    // there is a small race condition here - if the server is in the process of being moved between\r\n    // lists, we could fail to remove it.\r\n    removeFromAlive(server);\r\n    zombieServers.remove(server);\r\n    return null;\r\n  }\r\n\r\n  public void setConnectionTimeout(int timeout) {\r\n    HttpClientUtil.setConnectionTimeout(httpClient, timeout);\r\n  }\r\n\r\n  /**\r\n   * set soTimeout (read timeout) on the underlying HttpConnectionManager. This is desirable for queries, but probably\r\n   * not for indexing.\r\n   */\r\n  public void setSoTimeout(int timeout) {\r\n    HttpClientUtil.setSoTimeout(httpClient, timeout);\r\n  }\r\n\r\n  @Override\r\n  public void shutdown() {\r\n    if (aliveCheckExecutor != null) {\r\n      aliveCheckExecutor.shutdownNow();\r\n    }\r\n    if(clientIsInternal) {\r\n      httpClient.getConnectionManager().shutdown();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Tries to query a live server. A SolrServerException is thrown if all servers are dead.\r\n   * If the request failed due to IOException then the live server is moved to dead pool and the request is\r\n   * retried on another live server.  After live servers are exhausted, any servers previously marked as dead\r\n   * will be tried before failing the request.\r\n   *\r\n   * @param request the SolrRequest.\r\n   *\r\n   * @return response\r\n   *\r\n   * @throws IOException If there is a low-level I/O error.\r\n   */\r\n  @Override\r\n  public NamedList<Object> request(final SolrRequest request)\r\n          throws SolrServerException, IOException {\r\n    Exception ex = null;\r\n    ServerWrapper[] serverList = aliveServerList;\r\n    \r\n    int maxTries = serverList.length;\r\n    Map<String,ServerWrapper> justFailed = null;\r\n\r\n    for (int attempts=0; attempts<maxTries; attempts++) {\r\n      int count = counter.incrementAndGet();      \r\n      ServerWrapper wrapper = serverList[count % serverList.length];\r\n      wrapper.lastUsed = System.currentTimeMillis();\r\n\r\n      try {\r\n        return wrapper.solrServer.request(request);\r\n      } catch (SolrException e) {\r\n        // Server is alive but the request was malformed or invalid\r\n        throw e;\r\n      } catch (SolrServerException e) {\r\n        if (e.getRootCause() instanceof IOException) {\r\n          ex = e;\r\n          moveAliveToDead(wrapper);\r\n          if (justFailed == null) justFailed = new HashMap<String,ServerWrapper>();\r\n          justFailed.put(wrapper.getKey(), wrapper);\r\n        } else {\r\n          throw e;\r\n        }\r\n      } catch (Exception e) {\r\n        throw new SolrServerException(e);\r\n      }\r\n    }\r\n\r\n\r\n    // try other standard servers that we didn't try just now\r\n    for (ServerWrapper wrapper : zombieServers.values()) {\r\n      if (wrapper.standard==false || justFailed!=null && justFailed.containsKey(wrapper.getKey())) continue;\r\n      try {\r\n        NamedList<Object> rsp = wrapper.solrServer.request(request);\r\n        // remove from zombie list *before* adding to alive to avoid a race that could lose a server\r\n        zombieServers.remove(wrapper.getKey());\r\n        addToAlive(wrapper);\r\n        return rsp;\r\n      } catch (SolrException e) {\r\n        // Server is alive but the request was malformed or invalid\r\n        throw e;\r\n      } catch (SolrServerException e) {\r\n        if (e.getRootCause() instanceof IOException) {\r\n          ex = e;\r\n          // still dead\r\n        } else {\r\n          throw e;\r\n        }\r\n      } catch (Exception e) {\r\n        throw new SolrServerException(e);\r\n      }\r\n    }\r\n\r\n\r\n    if (ex == null) {\r\n      throw new SolrServerException(\"No live SolrServers available to handle this request\");\r\n    } else {\r\n      throw new SolrServerException(\"No live SolrServers available to handle this request\", ex);\r\n    }\r\n  }\r\n  \r\n  /**\r\n   * Takes up one dead server and check for aliveness. The check is done in a roundrobin. Each server is checked for\r\n   * aliveness once in 'x' millis where x is decided by the setAliveCheckinterval() or it is defaulted to 1 minute\r\n   *\r\n   * @param zombieServer a server in the dead pool\r\n   */\r\n  private void checkAZombieServer(ServerWrapper zombieServer) {\r\n    long currTime = System.currentTimeMillis();\r\n    try {\r\n      zombieServer.lastChecked = currTime;\r\n      QueryResponse resp = zombieServer.solrServer.query(solrQuery);\r\n      if (resp.getStatus() == 0) {\r\n        // server has come back up.\r\n        // make sure to remove from zombies before adding to alive to avoid a race condition\r\n        // where another thread could mark it down, move it back to zombie, and then we delete\r\n        // from zombie and lose it forever.\r\n        ServerWrapper wrapper = zombieServers.remove(zombieServer.getKey());\r\n        if (wrapper != null) {\r\n          wrapper.failedPings = 0;\r\n          if (wrapper.standard) {\r\n            addToAlive(wrapper);\r\n          }\r\n        } else {\r\n          // something else already moved the server from zombie to alive\r\n        }\r\n      }\r\n    } catch (Exception e) {\r\n      //Expected. The server is still down.\r\n      zombieServer.failedPings++;\r\n\r\n      // If the server doesn't belong in the standard set belonging to this load balancer\r\n      // then simply drop it after a certain number of failed pings.\r\n      if (!zombieServer.standard && zombieServer.failedPings >= NONSTANDARD_PING_LIMIT) {\r\n        zombieServers.remove(zombieServer.getKey());\r\n      }\r\n    }\r\n  }\r\n\r\n  private void moveAliveToDead(ServerWrapper wrapper) {\r\n    wrapper = removeFromAlive(wrapper.getKey());\r\n    if (wrapper == null)\r\n      return;  // another thread already detected the failure and removed it\r\n    zombieServers.put(wrapper.getKey(), wrapper);\r\n    startAliveCheckExecutor();\r\n  }\r\n\r\n  private int interval = CHECK_INTERVAL;\r\n\r\n  /**\r\n   * LBHttpSolrServer keeps pinging the dead servers at fixed interval to find if it is alive. Use this to set that\r\n   * interval\r\n   *\r\n   * @param interval time in milliseconds\r\n   */\r\n  public void setAliveCheckInterval(int interval) {\r\n    if (interval <= 0) {\r\n      throw new IllegalArgumentException(\"Alive check interval must be \" +\r\n              \"positive, specified value = \" + interval);\r\n    }\r\n    this.interval = interval;\r\n  }\r\n\r\n  private void startAliveCheckExecutor() {\r\n    // double-checked locking, but it's OK because we don't *do* anything with aliveCheckExecutor\r\n    // if it's not null.\r\n    if (aliveCheckExecutor == null) {\r\n      synchronized (this) {\r\n        if (aliveCheckExecutor == null) {\r\n          aliveCheckExecutor = Executors.newSingleThreadScheduledExecutor(\r\n              new SolrjNamedThreadFactory(\"aliveCheckExecutor\"));\r\n          aliveCheckExecutor.scheduleAtFixedRate(\r\n                  getAliveCheckRunner(new WeakReference<LBHttpSolrServer>(this)),\r\n                  this.interval, this.interval, TimeUnit.MILLISECONDS);\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  private static Runnable getAliveCheckRunner(final WeakReference<LBHttpSolrServer> lbRef) {\r\n    return new Runnable() {\r\n      @Override\r\n      public void run() {\r\n        LBHttpSolrServer lb = lbRef.get();\r\n        if (lb != null && lb.zombieServers != null) {\r\n          for (ServerWrapper zombieServer : lb.zombieServers.values()) {\r\n            lb.checkAZombieServer(zombieServer);\r\n          }\r\n        }\r\n      }\r\n    };\r\n  }\r\n\r\n  public HttpClient getHttpClient() {\r\n    return httpClient;\r\n  }\r\n\r\n  public ResponseParser getParser() {\r\n    return parser;\r\n  }\r\n  \r\n  public void setParser(ResponseParser parser) {\r\n    this.parser = parser;\r\n  }\r\n  \r\n  public void setRequestWriter(RequestWriter requestWriter) {\r\n    this.requestWriter = requestWriter;\r\n  }\r\n  \r\n  public RequestWriter getRequestWriter() {\r\n    return requestWriter;\r\n  }\r\n  \r\n  @Override\r\n  protected void finalize() throws Throwable {\r\n    try {\r\n      if(this.aliveCheckExecutor!=null)\r\n        this.aliveCheckExecutor.shutdownNow();\r\n    } finally {\r\n      super.finalize();\r\n    }\r\n  }\r\n\r\n  // defaults\r\n  private static final int CHECK_INTERVAL = 60 * 1000; //1 minute between checks\r\n  private static final int NONSTANDARD_PING_LIMIT = 5;  // number of times we'll ping dead servers not in the server list\r\n\r\n}\r\n"}}
{"actor":{"display_login":"sudheer4b3"}}