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 java.io.IOException;
import java.io.InputStream;
import java.lang.invoke.MethodHandles;
import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
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.impl.ConcurrentUpdateSolrClient.Update;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.params.UpdateParams;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SolrNamedThreadFactory;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.InputStreamResponseListener;
import org.eclipse.jetty.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
/** A Solr client using {@link Http2SolrClient} to send concurrent updates to Solr. */
public class ConcurrentUpdateHttp2SolrClient extends SolrClient {
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final Update END_UPDATE = new Update(null, null);
private Http2SolrClient client;
private final String basePath;
private final CustomBlockingQueue queue;
private final ExecutorService scheduler;
private final Queue runners;
private final int threadCount;
private boolean shutdownClient;
private boolean shutdownExecutor;
private long pollQueueTimeMillis;
private long stallTimeMillis;
private final boolean streamDeletes;
private volatile boolean closed;
private volatile CountDownLatch lock = null; // used to block everything
private static class CustomBlockingQueue implements Iterable {
private final BlockingQueue queue;
private final Semaphore available;
private final int queueSize;
private final E backdoorE;
public CustomBlockingQueue(int queueSize, int maxConsumers, E backdoorE) {
queue = new LinkedBlockingQueue<>();
available = new Semaphore(queueSize);
this.queueSize = queueSize;
this.backdoorE = backdoorE;
}
public boolean offer(E e) {
boolean success = available.tryAcquire();
if (success) {
queue.offer(e);
}
return success;
}
public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
boolean success = available.tryAcquire(timeout, unit);
if (success) {
queue.offer(e, timeout, unit);
}
return success;
}
public boolean isEmpty() {
return size() == 0;
}
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
E e = queue.poll(timeout, unit);
if (e == null) {
return null;
}
if (e == backdoorE) return null;
available.release();
return e;
}
public boolean add(E e) {
boolean success = available.tryAcquire();
if (success) {
queue.add(e);
} else {
throw new IllegalStateException("Queue is full");
}
return true;
}
public int size() {
return queueSize - available.availablePermits();
}
public int remainingCapacity() {
return available.availablePermits();
}
@Override
public Iterator iterator() {
return queue.iterator();
}
public void backdoorOffer() {
queue.offer(backdoorE);
}
}
protected ConcurrentUpdateHttp2SolrClient(Builder builder) {
this.client = builder.client;
this.shutdownClient = builder.closeHttp2Client;
this.threadCount = builder.threadCount;
this.queue = new CustomBlockingQueue<>(builder.queueSize, threadCount, END_UPDATE);
this.runners = new ArrayDeque<>();
this.streamDeletes = builder.streamDeletes;
this.basePath = builder.baseSolrUrl;
this.defaultCollection = builder.defaultCollection;
this.pollQueueTimeMillis = builder.pollQueueTimeMillis;
this.stallTimeMillis = Integer.getInteger("solr.cloud.client.stallTime", 15000);
// make sure the stall time is larger than the polling time
// to give a chance for the queue to change
long minimalStallTimeMillis = pollQueueTimeMillis * 2;
if (minimalStallTimeMillis > this.stallTimeMillis) {
this.stallTimeMillis = minimalStallTimeMillis;
}
if (stallTimeMillis < pollQueueTimeMillis * 2) {
throw new RuntimeException(
"Invalid stallTime: "
+ stallTimeMillis
+ "ms, must be 2x > pollQueueTime "
+ pollQueueTimeMillis);
}
if (builder.executorService != null) {
this.scheduler = builder.executorService;
this.shutdownExecutor = false;
} else {
this.scheduler =
ExecutorUtil.newMDCAwareCachedThreadPool(
new SolrNamedThreadFactory("concurrentUpdateScheduler"));
this.shutdownExecutor = true;
}
}
/** Opens a connection and sends everything... */
class Runner implements Runnable {
@Override
public void run() {
log.debug("starting runner: {}", this);
// This loop is so we can continue if an element was added to the queue after the last runner
// exited.
for (; ; ) {
try {
sendUpdateStream();
} catch (Throwable e) {
if (e instanceof OutOfMemoryError) {
throw (OutOfMemoryError) e;
}
handleError(e);
} finally {
synchronized (runners) {
// check to see if anything else was added to the queue
if (runners.size() == 1 && !queue.isEmpty() && !ExecutorUtil.isShutdown(scheduler)) {
// If there is something else to process, keep last runner alive by staying in the
// loop.
} else {
runners.remove(this);
if (runners.isEmpty()) {
// notify anyone waiting in blockUntilFinished
runners.notifyAll();
}
break;
}
}
}
}
log.debug("finished: {}", this);
}
//
// Pull from the queue multiple times and streams over a single connection.
// Exits on exception, interruption, or an empty queue to pull from.
//
@SuppressWarnings({"unchecked"})
void sendUpdateStream() throws Exception {
try {
while (!queue.isEmpty()) {
InputStream rspBody = null;
try {
Update update;
notifyQueueAndRunnersIfEmptyQueue();
update = queue.poll(pollQueueTimeMillis, TimeUnit.MILLISECONDS);
if (update == null) {
break;
}
InputStreamResponseListener responseListener = null;
try (Http2SolrClient.OutStream out =
client.initOutStream(basePath, update.getRequest(), update.getCollection())) {
Update upd = update;
while (upd != null) {
UpdateRequest req = upd.getRequest();
if (!out.belongToThisStream(req, upd.getCollection())) {
// Request has different params or destination core/collection, return to queue
queue.add(upd);
break;
}
client.send(out, upd.getRequest(), upd.getCollection());
out.flush();
notifyQueueAndRunnersIfEmptyQueue();
upd = queue.poll(pollQueueTimeMillis, TimeUnit.MILLISECONDS);
}
responseListener = out.getResponseListener();
}
Response response =
responseListener.get(client.getIdleTimeout(), TimeUnit.MILLISECONDS);
rspBody = responseListener.getInputStream();
int statusCode = response.getStatus();
if (statusCode != HttpStatus.OK_200) {
StringBuilder msg = new StringBuilder();
msg.append(response.getReason());
msg.append("\n\n\n\n");
msg.append("request: ").append(basePath);
SolrException solrExc;
NamedList metadata = null;
// parse out the metadata from the SolrException
try {
String encoding = "UTF-8"; // default
NamedList