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 static org.apache.solr.common.params.CommonParams.ID;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.net.ConnectException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.solr.client.solrj.ResponseParser;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.V2RequestSupport;
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
import org.apache.solr.client.solrj.request.IsUpdateRequest;
import org.apache.solr.client.solrj.request.RequestWriter;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.request.V2Request;
import org.apache.solr.client.solrj.routing.ReplicaListTransformer;
import org.apache.solr.client.solrj.routing.RequestReplicaListTransformerGenerator;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.ToleratedUpdateError;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.DocRouter;
import org.apache.solr.common.cloud.ImplicitDocRouter;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkCoreNodeProps;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.params.UpdateParams;
import org.apache.solr.common.util.CollectionUtil;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.Hash;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.util.SolrNamedThreadFactory;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public abstract class CloudSolrClient extends SolrClient {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
protected volatile String defaultCollection;
// no of times collection state to be reloaded if stale state error is received
private static final int MAX_STALE_RETRIES =
Integer.parseInt(System.getProperty("cloudSolrClientMaxStaleRetries", "5"));
private final Random rand = new Random();
private final boolean updatesToLeaders;
private final boolean directUpdatesToLeadersOnly;
private final RequestReplicaListTransformerGenerator requestRLTGenerator;
private final boolean parallelUpdates;
private ExecutorService threadPool =
ExecutorUtil.newMDCAwareCachedThreadPool(
new SolrNamedThreadFactory("CloudSolrClient ThreadPool"));
public static final String STATE_VERSION = "_stateVer_";
protected long retryExpiryTimeNano =
TimeUnit.NANOSECONDS.convert(3, TimeUnit.SECONDS); // 3 seconds or 3 million nanos
private static final Set NON_ROUTABLE_PARAMS =
Set.of(
UpdateParams.EXPUNGE_DELETES,
UpdateParams.MAX_OPTIMIZE_SEGMENTS,
UpdateParams.COMMIT,
UpdateParams.WAIT_SEARCHER,
UpdateParams.OPEN_SEARCHER,
UpdateParams.SOFT_COMMIT,
UpdateParams.PREPARE_COMMIT,
UpdateParams.OPTIMIZE
// Not supported via SolrCloud
// UpdateParams.ROLLBACK
);
protected volatile Object[] locks = objectList(3);
/** Constructs {@link CloudSolrClient} instances from provided configuration. */
public static class Builder extends CloudHttp2SolrClient.Builder {
/**
* Provide a series of Solr URLs to be used when configuring {@link CloudSolrClient} instances.
* The solr client will use these urls to understand the cluster topology, which solr nodes are
* active etc.
*
*
Provided Solr URLs are expected to point to the root Solr path
* ("http://hostname:8983/solr"); they should not include any collections, cores, or other path
* components.
*
*
Usage example:
*
*
* final List<String> solrBaseUrls = new ArrayList<String>();
* solrBaseUrls.add("http://solr1:8983/solr"); solrBaseUrls.add("http://solr2:8983/solr"); solrBaseUrls.add("http://solr3:8983/solr");
* final SolrClient client = new CloudSolrClient.Builder(solrBaseUrls).build();
*
*/
public Builder(List solrUrls) {
super(solrUrls);
}
/**
* Provide a series of ZK hosts which will be used when configuring {@link CloudSolrClient}
* instances. This requires a dependency on {@code solr-solrj-zookeeper} which transitively
* depends on more JARs. The ZooKeeper based connection is the most reliable and performant
* means for CloudSolrClient to work. On the other hand, it means exposing ZooKeeper more
* broadly than to Solr nodes, which is a security risk.
*
*
Usage example when Solr stores data at the ZooKeeper root ('/'):
*
*
* final List<String> zkServers = new ArrayList<String>();
* zkServers.add("zookeeper1:2181"); zkServers.add("zookeeper2:2181"); zkServers.add("zookeeper3:2181");
* final SolrClient client = new CloudSolrClient.Builder(zkServers, Optional.empty()).build();
*
*
* Usage example when Solr data is stored in a ZooKeeper chroot:
*
*
* final List<String> zkServers = new ArrayList<String>();
* zkServers.add("zookeeper1:2181"); zkServers.add("zookeeper2:2181"); zkServers.add("zookeeper3:2181");
* final SolrClient client = new CloudSolrClient.Builder(zkServers, Optional.of("/solr")).build();
*
*
* @param zkHosts a List of at least one ZooKeeper host and port (e.g. "zookeeper1:2181")
* @param zkChroot the path to the root ZooKeeper node containing Solr data. Provide {@code
* java.util.Optional.empty()} if no ZK chroot is used.
*/
public Builder(List zkHosts, Optional zkChroot) {
super(zkHosts, zkChroot);
}
}
static class StateCache extends ConcurrentHashMap {
final AtomicLong puts = new AtomicLong();
final AtomicLong hits = new AtomicLong();
final Lock evictLock = new ReentrantLock(true);
protected volatile long timeToLiveMs = 60 * 1000L;
@Override
public ExpiringCachedDocCollection get(Object key) {
ExpiringCachedDocCollection val = super.get(key);
if (val == null) {
// a new collection is likely to be added now.
// check if there are stale items and remove them
evictStale();
return null;
}
if (val.isExpired(timeToLiveMs)) {
super.remove(key);
return null;
}
hits.incrementAndGet();
return val;
}
@Override
public ExpiringCachedDocCollection put(String key, ExpiringCachedDocCollection value) {
puts.incrementAndGet();
return super.put(key, value);
}
void evictStale() {
if (!evictLock.tryLock()) return;
try {
for (Entry e : entrySet()) {
if (e.getValue().isExpired(timeToLiveMs)) {
super.remove(e.getKey());
}
}
} finally {
evictLock.unlock();
}
}
}
/**
* This is the time to wait to refetch the state after getting the same state version from ZK
*
*
secs
*
* @deprecated use {@link CloudSolrClient.Builder#setRetryExpiryTime(int)} instead
*/
@Deprecated
public void setRetryExpiryTime(int secs) {
this.retryExpiryTimeNano = TimeUnit.NANOSECONDS.convert(secs, TimeUnit.SECONDS);
}
protected final StateCache collectionStateCache = new StateCache();
class ExpiringCachedDocCollection {
final DocCollection cached;
final long cachedAtNano;
// This is the time at which the collection is retried and got the same old version
volatile long retriedAtNano = -1;
// flag that suggests that this is potentially to be rechecked
volatile boolean maybeStale = false;
ExpiringCachedDocCollection(DocCollection cached) {
this.cached = cached;
this.cachedAtNano = System.nanoTime();
}
boolean isExpired(long timeToLiveMs) {
return (System.nanoTime() - cachedAtNano)
> TimeUnit.NANOSECONDS.convert(timeToLiveMs, TimeUnit.MILLISECONDS);
}
boolean shouldRetry() {
if (maybeStale) { // we are not sure if it is stale so check with retry time
if ((retriedAtNano == -1 || (System.nanoTime() - retriedAtNano) > retryExpiryTimeNano)) {
return true; // we retried a while back. and we could not get anything new.
// it's likely that it is not going to be available now also.
}
}
return false;
}
void setRetriedAt() {
retriedAtNano = System.nanoTime();
}
}
protected CloudSolrClient(
boolean updatesToLeaders, boolean parallelUpdates, boolean directUpdatesToLeadersOnly) {
this.updatesToLeaders = updatesToLeaders;
this.parallelUpdates = parallelUpdates;
this.directUpdatesToLeadersOnly = directUpdatesToLeadersOnly;
this.requestRLTGenerator = new RequestReplicaListTransformerGenerator();
}
/**
* Sets the cache ttl for DocCollection Objects cached.
*
* @param seconds ttl value in seconds
* @deprecated use {@link CloudSolrClient.Builder#withCollectionCacheTtl(int)} instead
*/
@Deprecated
public void setCollectionCacheTTl(int seconds) {
assert seconds > 0;
this.collectionStateCache.timeToLiveMs = seconds * 1000L;
}
protected abstract LBSolrClient getLbClient();
public abstract ClusterStateProvider getClusterStateProvider();
public ClusterState getClusterState() {
return getClusterStateProvider().getClusterState();
}
protected abstract boolean wasCommError(Throwable t);
@Override
public void close() throws IOException {
if (this.threadPool != null && !ExecutorUtil.isShutdown(this.threadPool)) {
ExecutorUtil.shutdownAndAwaitTermination(this.threadPool);
this.threadPool = null;
}
}
public ResponseParser getParser() {
return getLbClient().getParser();
}
/**
* Note: This setter method is not thread-safe.
*
* @param processor 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()
* @deprecated use {@link CloudHttp2SolrClient.Builder} instead
*/
@Deprecated
public void setParser(ResponseParser processor) {
getLbClient().setParser(processor);
}
public RequestWriter getRequestWriter() {
return getLbClient().getRequestWriter();
}
/**
* Choose the {@link RequestWriter} to use.
*
*
Note: This setter method is not thread-safe.
*
* @deprecated use {@link CloudHttp2SolrClient.Builder} instead
*/
@Deprecated
public void setRequestWriter(RequestWriter requestWriter) {
getLbClient().setRequestWriter(requestWriter);
}
/**
* Sets the default collection for request.
*
* @deprecated use {@link CloudHttp2SolrClient.Builder#withDefaultCollection(String)} instead
*/
@Deprecated
public void setDefaultCollection(String collection) {
this.defaultCollection = collection;
}
/** Gets the default collection for request */
public String getDefaultCollection() {
return defaultCollection;
}
/** Gets whether direct updates are sent in parallel */
public boolean isParallelUpdates() {
return parallelUpdates;
}
/**
* Connect to the zookeeper ensemble. This is an optional method that may be used to force a
* connect before any other requests are sent.
*/
public void connect() {
getClusterStateProvider().connect();
}
/**
* Connect to a cluster. If the cluster is not ready, retry connection up to a given timeout.
*
* @param duration the timeout
* @param timeUnit the units of the timeout
* @throws TimeoutException if the cluster is not ready after the timeout
* @throws InterruptedException if the wait is interrupted
*/
public void connect(long duration, TimeUnit timeUnit)
throws TimeoutException, InterruptedException {
if (log.isInfoEnabled()) {
log.info(
"Waiting for {} {} for cluster at {} to be ready",
duration,
timeUnit,
getClusterStateProvider());
}
long timeout = System.nanoTime() + timeUnit.toNanos(duration);
while (System.nanoTime() < timeout) {
try {
connect();
if (log.isInfoEnabled()) {
log.info("Cluster at {} ready", getClusterStateProvider());
}
return;
} catch (RuntimeException e) {
// not ready yet, then...
}
TimeUnit.MILLISECONDS.sleep(250);
}
throw new TimeoutException("Timed out waiting for cluster");
}
@SuppressWarnings({"unchecked"})
private NamedList