Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.client.solrj.impl;
import static org.apache.solr.common.params.CommonParams.ADMIN_PATHS;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.solr.client.solrj.ResponseParser;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.IsUpdateRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.RequestWriter;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SolrNamedThreadFactory;
import org.slf4j.MDC;
public abstract class LBSolrClient extends SolrClient {
// defaults
protected static final Set RETRY_CODES =
new HashSet<>(Arrays.asList(404, 403, 503, 500));
private static final int NONSTANDARD_PING_LIMIT =
5; // number of times we'll ping dead servers not in the server list
// keys to the maps are currently of the form "http://localhost:8983/solr"
// which should be equivalent to HttpSolrServer.getBaseURL()
private final Map aliveServers = new LinkedHashMap<>();
// access to aliveServers should be synchronized on itself
protected final Map zombieServers = new ConcurrentHashMap<>();
// changes to aliveServers are reflected in this array, no need to synchronize
private volatile ServerWrapper[] aliveServerList = new ServerWrapper[0];
private volatile ScheduledExecutorService aliveCheckExecutor;
protected long aliveCheckIntervalMillis =
TimeUnit.MILLISECONDS.convert(60, TimeUnit.SECONDS); // 1 minute between checks
private final AtomicInteger counter = new AtomicInteger(-1);
private static final SolrQuery solrQuery = new SolrQuery("*:*");
protected volatile ResponseParser parser;
protected volatile RequestWriter requestWriter;
static {
solrQuery.setRows(0);
/*
* Default sort (if we don't supply a sort) is by score and since we request 0 rows any sorting
* and scoring is not necessary. SolrQuery.DOCID schema-independently specifies a non-scoring
* sort. _docid_ asc sort is efficient, _docid_ desc sort is not, so
* choose ascending DOCID sort.
*/
solrQuery.setSort(SolrQuery.DOCID, SolrQuery.ORDER.asc);
// not a top-level request, we are interested only in the server being sent to i.e. it need not
// distribute our request to further servers
solrQuery.setDistrib(false);
}
protected static class ServerWrapper {
final String baseUrl;
// "standard" servers are used by default. They normally live in the alive list
// and move to the zombie list when unavailable. When they become available again,
// they move back to the alive list.
boolean standard = true;
int failedPings = 0;
ServerWrapper(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getBaseUrl() {
return baseUrl;
}
@Override
public String toString() {
return baseUrl;
}
@Override
public int hashCode() {
return baseUrl.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof ServerWrapper)) return false;
return baseUrl.equals(((ServerWrapper) obj).baseUrl);
}
}
protected static class ServerIterator {
String serverStr;
List skipped;
int numServersTried;
Iterator it;
Iterator skippedIt;
String exceptionMessage;
long timeAllowedNano;
long timeOutTime;
final Map zombieServers;
final Req req;
public ServerIterator(Req req, Map zombieServers) {
this.it = req.getServers().iterator();
this.req = req;
this.zombieServers = zombieServers;
this.timeAllowedNano = getTimeAllowedInNanos(req.getRequest());
this.timeOutTime = System.nanoTime() + timeAllowedNano;
fetchNext();
}
public synchronized boolean hasNext() {
return serverStr != null;
}
private void fetchNext() {
serverStr = null;
if (req.numServersToTry != null && numServersTried > req.numServersToTry) {
exceptionMessage = "Time allowed to handle this request exceeded";
return;
}
while (it.hasNext()) {
serverStr = it.next();
serverStr = normalize(serverStr);
// if the server is currently a zombie, just skip to the next one
ServerWrapper wrapper = zombieServers.get(serverStr);
if (wrapper != null) {
final int numDeadServersToTry = req.getNumDeadServersToTry();
if (numDeadServersToTry > 0) {
if (skipped == null) {
skipped = new ArrayList<>(numDeadServersToTry);
skipped.add(wrapper.getBaseUrl());
} else if (skipped.size() < numDeadServersToTry) {
skipped.add(wrapper.getBaseUrl());
}
}
continue;
}
break;
}
if (serverStr == null && skipped != null) {
if (skippedIt == null) {
skippedIt = skipped.iterator();
}
if (skippedIt.hasNext()) {
serverStr = skippedIt.next();
}
}
}
boolean isServingZombieServer() {
return skippedIt != null;
}
public synchronized String nextOrError() throws SolrServerException {
return nextOrError(null);
}
public synchronized String nextOrError(Exception previousEx) throws SolrServerException {
String suffix = "";
if (previousEx == null) {
suffix = ":" + zombieServers.keySet();
}
// Skipping check time exceeded for the first request
if (numServersTried > 0 && isTimeExceeded(timeAllowedNano, timeOutTime)) {
throw new SolrServerException(
"Time allowed to handle this request exceeded" + suffix, previousEx);
}
if (serverStr == null) {
throw new SolrServerException(
"No live SolrServers available to handle this request" + suffix, previousEx);
}
numServersTried++;
if (req.getNumServersToTry() != null && numServersTried > req.getNumServersToTry()) {
throw new SolrServerException(
"No live SolrServers available to handle this request:"
+ " numServersTried="
+ numServersTried
+ " numServersToTry="
+ req.getNumServersToTry()
+ suffix,
previousEx);
}
String rs = serverStr;
fetchNext();
return rs;
}
}
// Req should be parameterized too, but that touches a whole lotta code
public static class Req {
protected SolrRequest> request;
protected List servers;
protected int numDeadServersToTry;
private final Integer numServersToTry;
public Req(SolrRequest> request, List servers) {
this(request, servers, null);
}
public Req(SolrRequest> request, List servers, Integer numServersToTry) {
this.request = request;
this.servers = servers;
this.numDeadServersToTry = servers.size();
this.numServersToTry = numServersToTry;
}
public SolrRequest> getRequest() {
return request;
}
public List getServers() {
return servers;
}
/**
* @return the number of dead servers to try if there are no live servers left
*/
public int getNumDeadServersToTry() {
return numDeadServersToTry;
}
/**
* @param numDeadServersToTry The number of dead servers to try if there are no live servers
* left. Defaults to the number of servers in this request.
*/
public void setNumDeadServersToTry(int numDeadServersToTry) {
this.numDeadServersToTry = numDeadServersToTry;
}
public Integer getNumServersToTry() {
return numServersToTry;
}
}
public static class Rsp {
protected String server;
protected NamedList