优化DeParser
This commit is contained in:
@@ -1,430 +1,430 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.net.client;
|
package org.redkale.net.client;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.*;
|
import java.util.concurrent.atomic.*;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import org.redkale.annotation.*;
|
import org.redkale.annotation.*;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注意: 要确保AsyncConnection的读写过程都必须在channel.ioThread中运行
|
* 注意: 要确保AsyncConnection的读写过程都必须在channel.ioThread中运行
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @since 2.3.0
|
* @since 2.3.0
|
||||||
*
|
*
|
||||||
* @param <R> 请求对象
|
* @param <R> 请求对象
|
||||||
* @param <P> 响应对象
|
* @param <P> 响应对象
|
||||||
*/
|
*/
|
||||||
public abstract class ClientConnection<R extends ClientRequest, P> implements Consumer<AsyncConnection> {
|
public abstract class ClientConnection<R extends ClientRequest, P> implements Consumer<AsyncConnection> {
|
||||||
|
|
||||||
//=-1 表示连接放在connAddrEntrys存储
|
//=-1 表示连接放在connAddrEntrys存储
|
||||||
//>=0 表示connArray的下坐标,从0开始
|
//>=0 表示connArray的下坐标,从0开始
|
||||||
protected final int index;
|
protected final int index;
|
||||||
|
|
||||||
protected final Client client;
|
protected final Client client;
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
protected final LongAdder respWaitingCounter;
|
protected final LongAdder respWaitingCounter;
|
||||||
|
|
||||||
protected final LongAdder doneRequestCounter = new LongAdder();
|
protected final LongAdder doneRequestCounter = new LongAdder();
|
||||||
|
|
||||||
protected final LongAdder doneResponseCounter = new LongAdder();
|
protected final LongAdder doneResponseCounter = new LongAdder();
|
||||||
|
|
||||||
protected final AtomicBoolean writePending = new AtomicBoolean();
|
protected final AtomicBoolean writePending = new AtomicBoolean();
|
||||||
|
|
||||||
protected final ReentrantLock writeLock = new ReentrantLock();
|
protected final ReentrantLock writeLock = new ReentrantLock();
|
||||||
|
|
||||||
protected final ByteArray writeArray = new ByteArray();
|
protected final ByteArray writeArray = new ByteArray();
|
||||||
|
|
||||||
protected final ThreadLocal<ByteArray> arrayThreadLocal = ThreadLocal.withInitial(ByteArray::new);
|
protected final ThreadLocal<ByteArray> arrayThreadLocal = ThreadLocal.withInitial(ByteArray::new);
|
||||||
|
|
||||||
protected final ByteBuffer writeBuffer;
|
protected final ByteBuffer writeBuffer;
|
||||||
|
|
||||||
protected final CompletionHandler<Integer, ClientConnection> writeHandler = new CompletionHandler<Integer, ClientConnection>() {
|
protected final CompletionHandler<Integer, ClientConnection> writeHandler = new CompletionHandler<Integer, ClientConnection>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void completed(Integer result, ClientConnection attachment) {
|
public void completed(Integer result, ClientConnection attachment) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void failed(Throwable exc, ClientConnection attachment) {
|
public void failed(Throwable exc, ClientConnection attachment) {
|
||||||
writePending.set(false);
|
writePending.set(false);
|
||||||
attachment.dispose(exc);
|
attachment.dispose(exc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final AtomicBoolean pauseWriting = new AtomicBoolean();
|
final AtomicBoolean pauseWriting = new AtomicBoolean();
|
||||||
|
|
||||||
final ConcurrentLinkedQueue<ClientFuture> pauseRequests = new ConcurrentLinkedQueue<>();
|
final ConcurrentLinkedQueue<ClientFuture> pauseRequests = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
//pauseWriting=true,此字段才会有值; pauseWriting=false,此字段值为null
|
//pauseWriting=true,此字段才会有值; pauseWriting=false,此字段值为null
|
||||||
ClientFuture currHalfWriteFuture;
|
ClientFuture currHalfWriteFuture;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final Client.AddressConnEntry connEntry;
|
private final Client.AddressConnEntry connEntry;
|
||||||
|
|
||||||
protected final AsyncConnection channel;
|
protected final AsyncConnection channel;
|
||||||
|
|
||||||
private final ClientCodec<R, P> codec;
|
private final ClientCodec<R, P> codec;
|
||||||
|
|
||||||
//respFutureQueue、respFutureMap二选一, SPSC队列模式
|
//respFutureQueue、respFutureMap二选一, SPSC队列模式
|
||||||
private final ConcurrentLinkedDeque<ClientFuture<R, P>> respFutureQueue = new ConcurrentLinkedDeque<>();
|
private final ConcurrentLinkedDeque<ClientFuture<R, P>> respFutureQueue = new ConcurrentLinkedDeque<>();
|
||||||
|
|
||||||
//respFutureQueue、respFutureMap二选一, key: requestid, SPSC模式
|
//respFutureQueue、respFutureMap二选一, key: requestid, SPSC模式
|
||||||
private final ConcurrentHashMap<Serializable, ClientFuture<R, P>> respFutureMap = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<Serializable, ClientFuture<R, P>> respFutureMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
Iterator<ClientFuture<R, P>> currRespIterator; //必须在调用decodeMessages之前重置为null
|
Iterator<ClientFuture<R, P>> currRespIterator; //必须在调用decodeMessages之前重置为null
|
||||||
|
|
||||||
private int maxPipelines; //最大并行处理数
|
private int maxPipelines; //最大并行处理数
|
||||||
|
|
||||||
private boolean authenticated;
|
private boolean authenticated;
|
||||||
|
|
||||||
@SuppressWarnings({"LeakingThisInConstructor", "OverridableMethodCallInConstructor"})
|
@SuppressWarnings({"LeakingThisInConstructor", "OverridableMethodCallInConstructor"})
|
||||||
public ClientConnection(Client<? extends ClientConnection<R, P>, R, P> client, int index, AsyncConnection channel) {
|
public ClientConnection(Client<? extends ClientConnection<R, P>, R, P> client, int index, AsyncConnection channel) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.codec = createCodec();
|
this.codec = createCodec();
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.connEntry = index >= 0 ? null : client.connAddrEntrys.get(channel.getRemoteAddress());
|
this.connEntry = index >= 0 ? null : client.connAddrEntrys.get(channel.getRemoteAddress());
|
||||||
this.respWaitingCounter = index >= 0 ? client.connRespWaitings[index] : this.connEntry.connRespWaiting;
|
this.respWaitingCounter = index >= 0 ? client.connRespWaitings[index] : this.connEntry.connRespWaiting;
|
||||||
this.channel = channel.beforeCloseListener(this).fastHandler(writeHandler);
|
this.channel = channel.beforeCloseListener(this).fastHandler(writeHandler);
|
||||||
this.writeBuffer = channel.pollWriteBuffer();
|
this.writeBuffer = channel.pollWriteBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ClientCodec createCodec();
|
protected abstract ClientCodec createCodec();
|
||||||
|
|
||||||
protected final CompletableFuture<P> writeChannel(R request) {
|
protected final CompletableFuture<P> writeChannel(R request) {
|
||||||
return writeChannel(request, null);
|
return writeChannel(request, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final CompletableFuture<List<P>> writeChannel(R[] requests) {
|
protected final CompletableFuture<List<P>> writeChannel(R[] requests) {
|
||||||
return writeChannel(requests, null);
|
return writeChannel(requests, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//respTransfer只会在ClientCodec的读线程里调用
|
//respTransfer只会在ClientCodec的读线程里调用
|
||||||
protected final <T> CompletableFuture<T> writeChannel(R request, Function<P, T> respTransfer) {
|
protected final <T> CompletableFuture<T> writeChannel(R request, Function<P, T> respTransfer) {
|
||||||
request.respTransfer = respTransfer;
|
request.respTransfer = respTransfer;
|
||||||
ClientFuture respFuture = createClientFuture(request);
|
ClientFuture respFuture = createClientFuture(request);
|
||||||
int rts = this.channel.getReadTimeoutSeconds();
|
int rts = this.channel.getReadTimeoutSeconds();
|
||||||
if (rts > 0 && !request.isCloseType()) {
|
if (rts > 0 && !request.isCloseType()) {
|
||||||
respFuture.setTimeout(client.timeoutScheduler.schedule(respFuture, rts, TimeUnit.SECONDS));
|
respFuture.setTimeout(client.timeoutScheduler.schedule(respFuture, rts, TimeUnit.SECONDS));
|
||||||
}
|
}
|
||||||
respWaitingCounter.increment(); //放在writeChannelInWriteThread计数会延迟,导致不准确
|
respWaitingCounter.increment(); //放在writeChannelInWriteThread计数会延迟,导致不准确
|
||||||
writeLock.lock();
|
writeLock.lock();
|
||||||
try {
|
try {
|
||||||
offerRespFuture(respFuture);
|
offerRespFuture(respFuture);
|
||||||
if (pauseWriting.get()) {
|
if (pauseWriting.get()) {
|
||||||
pauseRequests.add(respFuture);
|
pauseRequests.add(respFuture);
|
||||||
} else {
|
} else {
|
||||||
sendRequestInLocking(request, respFuture);
|
sendRequestInLocking(request, respFuture);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
writeLock.unlock();
|
||||||
}
|
}
|
||||||
return respFuture;
|
return respFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
//respTransfer只会在ClientCodec的读线程里调用
|
//respTransfer只会在ClientCodec的读线程里调用
|
||||||
protected final <T> CompletableFuture<List<T>> writeChannel(R[] requests, Function<P, T> respTransfer) {
|
protected final <T> CompletableFuture<List<T>> writeChannel(R[] requests, Function<P, T> respTransfer) {
|
||||||
ClientFuture[] respFutures = new ClientFuture[requests.length];
|
ClientFuture[] respFutures = new ClientFuture[requests.length];
|
||||||
int rts = this.channel.getReadTimeoutSeconds();
|
int rts = this.channel.getReadTimeoutSeconds();
|
||||||
for (int i = 0; i < respFutures.length; i++) {
|
for (int i = 0; i < respFutures.length; i++) {
|
||||||
R request = requests[i];
|
R request = requests[i];
|
||||||
request.respTransfer = respTransfer;
|
request.respTransfer = respTransfer;
|
||||||
ClientFuture respFuture = createClientFuture(requests[i]);
|
ClientFuture respFuture = createClientFuture(requests[i]);
|
||||||
respFutures[i] = respFuture;
|
respFutures[i] = respFuture;
|
||||||
if (rts > 0 && !request.isCloseType()) {
|
if (rts > 0 && !request.isCloseType()) {
|
||||||
respFuture.setTimeout(client.timeoutScheduler.schedule(respFuture, rts, TimeUnit.SECONDS));
|
respFuture.setTimeout(client.timeoutScheduler.schedule(respFuture, rts, TimeUnit.SECONDS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
respWaitingCounter.add(respFutures.length);//放在writeChannelInWriteThread计数会延迟,导致不准确
|
respWaitingCounter.add(respFutures.length);//放在writeChannelInWriteThread计数会延迟,导致不准确
|
||||||
|
|
||||||
writeLock.lock();
|
writeLock.lock();
|
||||||
try {
|
try {
|
||||||
for (ClientFuture respFuture : respFutures) {
|
for (ClientFuture respFuture : respFutures) {
|
||||||
offerRespFuture(respFuture);
|
offerRespFuture(respFuture);
|
||||||
if (pauseWriting.get()) {
|
if (pauseWriting.get()) {
|
||||||
pauseRequests.add(respFuture);
|
pauseRequests.add(respFuture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendRequestInLocking(respFutures);
|
sendRequestInLocking(respFutures);
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
writeLock.unlock();
|
||||||
}
|
}
|
||||||
return Utility.allOfFutures(respFutures);
|
return Utility.allOfFutures(respFutures);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendRequestInLocking(R request, ClientFuture respFuture) {
|
private void sendRequestInLocking(R request, ClientFuture respFuture) {
|
||||||
if (true) { //新方式
|
if (false) { //新方式
|
||||||
ByteArray array = arrayThreadLocal.get();
|
ByteArray array = arrayThreadLocal.get();
|
||||||
array.clear();
|
array.clear();
|
||||||
request.writeTo(this, array);
|
request.writeTo(this, array);
|
||||||
if (request.isCompleted()) {
|
if (request.isCompleted()) {
|
||||||
doneRequestCounter.increment();
|
doneRequestCounter.increment();
|
||||||
} else { //还剩半包没发送完
|
} else { //还剩半包没发送完
|
||||||
pauseWriting.set(true);
|
pauseWriting.set(true);
|
||||||
currHalfWriteFuture = respFuture;
|
currHalfWriteFuture = respFuture;
|
||||||
}
|
}
|
||||||
channel.fastWrite(array.getBytes());
|
channel.fastWrite(array.getBytes());
|
||||||
} else { //旧方式
|
} else { //旧方式
|
||||||
//发送请求数据包
|
//发送请求数据包
|
||||||
writeArray.clear();
|
writeArray.clear();
|
||||||
request.writeTo(this, writeArray);
|
request.writeTo(this, writeArray);
|
||||||
if (request.isCompleted()) {
|
if (request.isCompleted()) {
|
||||||
doneRequestCounter.increment();
|
doneRequestCounter.increment();
|
||||||
} else { //还剩半包没发送完
|
} else { //还剩半包没发送完
|
||||||
pauseWriting.set(true);
|
pauseWriting.set(true);
|
||||||
currHalfWriteFuture = respFuture;
|
currHalfWriteFuture = respFuture;
|
||||||
}
|
}
|
||||||
if (writeArray.length() > 0) {
|
if (writeArray.length() > 0) {
|
||||||
if (writeBuffer.capacity() >= writeArray.length()) {
|
if (writeBuffer.capacity() >= writeArray.length()) {
|
||||||
writeBuffer.clear();
|
writeBuffer.clear();
|
||||||
writeBuffer.put(writeArray.content(), 0, writeArray.length());
|
writeBuffer.put(writeArray.content(), 0, writeArray.length());
|
||||||
writeBuffer.flip();
|
writeBuffer.flip();
|
||||||
channel.write(writeBuffer, this, writeHandler);
|
channel.write(writeBuffer, this, writeHandler);
|
||||||
} else {
|
} else {
|
||||||
channel.write(writeArray, this, writeHandler);
|
channel.write(writeArray, this, writeHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendRequestInLocking(ClientFuture[] respFutures) {
|
private void sendRequestInLocking(ClientFuture[] respFutures) {
|
||||||
ByteArray array = arrayThreadLocal.get();
|
ByteArray array = arrayThreadLocal.get();
|
||||||
array.clear();
|
array.clear();
|
||||||
for (ClientFuture respFuture : respFutures) {
|
for (ClientFuture respFuture : respFutures) {
|
||||||
if (pauseWriting.get()) {
|
if (pauseWriting.get()) {
|
||||||
pauseRequests.add(respFuture);
|
pauseRequests.add(respFuture);
|
||||||
} else {
|
} else {
|
||||||
ClientRequest request = respFuture.request;
|
ClientRequest request = respFuture.request;
|
||||||
request.writeTo(this, array);
|
request.writeTo(this, array);
|
||||||
if (request.isCompleted()) {
|
if (request.isCompleted()) {
|
||||||
doneRequestCounter.increment();
|
doneRequestCounter.increment();
|
||||||
} else { //还剩半包没发送完
|
} else { //还剩半包没发送完
|
||||||
pauseWriting.set(true);
|
pauseWriting.set(true);
|
||||||
currHalfWriteFuture = respFuture;
|
currHalfWriteFuture = respFuture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
channel.fastWrite(array.getBytes());
|
channel.fastWrite(array.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送半包和积压的请求数据包
|
//发送半包和积压的请求数据包
|
||||||
void sendHalfWriteInReadThread(R request, Throwable halfRequestExc) {
|
void sendHalfWriteInReadThread(R request, Throwable halfRequestExc) {
|
||||||
writeLock.lock();
|
writeLock.lock();
|
||||||
try {
|
try {
|
||||||
pauseWriting.set(false);
|
pauseWriting.set(false);
|
||||||
ClientFuture respFuture = this.currHalfWriteFuture;
|
ClientFuture respFuture = this.currHalfWriteFuture;
|
||||||
if (respFuture != null) {
|
if (respFuture != null) {
|
||||||
this.currHalfWriteFuture = null;
|
this.currHalfWriteFuture = null;
|
||||||
if (halfRequestExc == null) {
|
if (halfRequestExc == null) {
|
||||||
offerFirstRespFuture(respFuture);
|
offerFirstRespFuture(respFuture);
|
||||||
sendRequestInLocking(request, respFuture);
|
sendRequestInLocking(request, respFuture);
|
||||||
} else {
|
} else {
|
||||||
codec.responseComplete(true, respFuture, null, halfRequestExc);
|
codec.responseComplete(true, respFuture, null, halfRequestExc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!pauseWriting.get() && (respFuture = pauseRequests.poll()) != null) {
|
while (!pauseWriting.get() && (respFuture = pauseRequests.poll()) != null) {
|
||||||
sendRequestInLocking((R) respFuture.getRequest(), respFuture);
|
sendRequestInLocking((R) respFuture.getRequest(), respFuture);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
writeLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletableFuture<P> writeVirtualRequest(R request) {
|
CompletableFuture<P> writeVirtualRequest(R request) {
|
||||||
if (!request.isVirtualType()) {
|
if (!request.isVirtualType()) {
|
||||||
return CompletableFuture.failedFuture(new RuntimeException("ClientVirtualRequest must be virtualType = true"));
|
return CompletableFuture.failedFuture(new RuntimeException("ClientVirtualRequest must be virtualType = true"));
|
||||||
}
|
}
|
||||||
ClientFuture<R, P> respFuture = createClientFuture(request);
|
ClientFuture<R, P> respFuture = createClientFuture(request);
|
||||||
writeLock.lock();
|
writeLock.lock();
|
||||||
try {
|
try {
|
||||||
offerRespFuture(respFuture);
|
offerRespFuture(respFuture);
|
||||||
} finally {
|
} finally {
|
||||||
writeLock.unlock();
|
writeLock.unlock();
|
||||||
}
|
}
|
||||||
channel.readRegister(getCodec()); //不能在创建连接时注册读事件
|
channel.readRegister(getCodec()); //不能在创建连接时注册读事件
|
||||||
return respFuture;
|
return respFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void preComplete(P resp, R req, Throwable exc) {
|
protected void preComplete(P resp, R req, Throwable exc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClientFuture<R, P> createClientFuture(R request) {
|
protected ClientFuture<R, P> createClientFuture(R request) {
|
||||||
return new ClientFuture(this, request);
|
return new ClientFuture(this, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override //AsyncConnection.beforeCloseListener
|
@Override //AsyncConnection.beforeCloseListener
|
||||||
public void accept(AsyncConnection t) {
|
public void accept(AsyncConnection t) {
|
||||||
respWaitingCounter.reset();
|
respWaitingCounter.reset();
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
client.connOpenStates[index].set(false);
|
client.connOpenStates[index].set(false);
|
||||||
client.connArray[index] = null; //必须connOpenStates之后
|
client.connArray[index] = null; //必须connOpenStates之后
|
||||||
} else if (connEntry != null) { //index=-1
|
} else if (connEntry != null) { //index=-1
|
||||||
connEntry.connOpenState.set(false);
|
connEntry.connOpenState.set(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose(Throwable exc) {
|
public void dispose(Throwable exc) {
|
||||||
channel.offerWriteBuffer(writeBuffer);
|
channel.offerWriteBuffer(writeBuffer);
|
||||||
channel.dispose();
|
channel.dispose();
|
||||||
Throwable e = exc == null ? new ClosedChannelException() : exc;
|
Throwable e = exc == null ? new ClosedChannelException() : exc;
|
||||||
CompletableFuture f;
|
CompletableFuture f;
|
||||||
respWaitingCounter.reset();
|
respWaitingCounter.reset();
|
||||||
WorkThread thread = channel.getReadIOThread();
|
WorkThread thread = channel.getReadIOThread();
|
||||||
if (!respFutureQueue.isEmpty()) {
|
if (!respFutureQueue.isEmpty()) {
|
||||||
while ((f = respFutureQueue.poll()) != null) {
|
while ((f = respFutureQueue.poll()) != null) {
|
||||||
CompletableFuture future = f;
|
CompletableFuture future = f;
|
||||||
thread.runWork(() -> future.completeExceptionally(e));
|
thread.runWork(() -> future.completeExceptionally(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!respFutureMap.isEmpty()) {
|
if (!respFutureMap.isEmpty()) {
|
||||||
respFutureMap.forEach((key, future) -> {
|
respFutureMap.forEach((key, future) -> {
|
||||||
respFutureMap.remove(key);
|
respFutureMap.remove(key);
|
||||||
thread.runWork(() -> future.completeExceptionally(e));
|
thread.runWork(() -> future.completeExceptionally(e));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//只会在WriteIOThread中调用, 必须在writeLock内执行
|
//只会在WriteIOThread中调用, 必须在writeLock内执行
|
||||||
void offerFirstRespFuture(ClientFuture<R, P> respFuture) {
|
void offerFirstRespFuture(ClientFuture<R, P> respFuture) {
|
||||||
Serializable requestid = respFuture.request.getRequestid();
|
Serializable requestid = respFuture.request.getRequestid();
|
||||||
if (requestid == null) {
|
if (requestid == null) {
|
||||||
respFutureQueue.offerFirst(respFuture);
|
respFutureQueue.offerFirst(respFuture);
|
||||||
} else {
|
} else {
|
||||||
respFutureMap.put(requestid, respFuture);
|
respFutureMap.put(requestid, respFuture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//必须在writeLock内执行
|
//必须在writeLock内执行
|
||||||
void offerRespFuture(ClientFuture<R, P> respFuture) {
|
void offerRespFuture(ClientFuture<R, P> respFuture) {
|
||||||
Serializable requestid = respFuture.request.getRequestid();
|
Serializable requestid = respFuture.request.getRequestid();
|
||||||
if (requestid == null) {
|
if (requestid == null) {
|
||||||
respFutureQueue.offer(respFuture);
|
respFutureQueue.offer(respFuture);
|
||||||
} else {
|
} else {
|
||||||
respFutureMap.put(requestid, respFuture);
|
respFutureMap.put(requestid, respFuture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//只会被Timeout在ReadIOThread中调用
|
//只会被Timeout在ReadIOThread中调用
|
||||||
void removeRespFuture(Serializable requestid, ClientFuture<R, P> respFuture) {
|
void removeRespFuture(Serializable requestid, ClientFuture<R, P> respFuture) {
|
||||||
if (requestid == null) {
|
if (requestid == null) {
|
||||||
respFutureQueue.remove(respFuture);
|
respFutureQueue.remove(respFuture);
|
||||||
} else {
|
} else {
|
||||||
respFutureMap.remove(requestid);
|
respFutureMap.remove(requestid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//只会被ClientCodec在ReadIOThread中调用
|
//只会被ClientCodec在ReadIOThread中调用
|
||||||
ClientFuture<R, P> pollRespFuture(Serializable requestid) {
|
ClientFuture<R, P> pollRespFuture(Serializable requestid) {
|
||||||
if (requestid == null) {
|
if (requestid == null) {
|
||||||
return respFutureQueue.poll();
|
return respFutureQueue.poll();
|
||||||
} else {
|
} else {
|
||||||
return respFutureMap.remove(requestid);
|
return respFutureMap.remove(requestid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//只会被ClientCodec在ReadIOThread中调用
|
//只会被ClientCodec在ReadIOThread中调用
|
||||||
R findRequest(Serializable requestid) {
|
R findRequest(Serializable requestid) {
|
||||||
if (requestid == null) {
|
if (requestid == null) {
|
||||||
if (currRespIterator == null) {
|
if (currRespIterator == null) {
|
||||||
currRespIterator = respFutureQueue.iterator();
|
currRespIterator = respFutureQueue.iterator();
|
||||||
}
|
}
|
||||||
ClientFuture<R, P> future = currRespIterator.hasNext() ? currRespIterator.next() : null;
|
ClientFuture<R, P> future = currRespIterator.hasNext() ? currRespIterator.next() : null;
|
||||||
return future == null ? null : future.request;
|
return future == null ? null : future.request;
|
||||||
} else {
|
} else {
|
||||||
ClientFuture<R, P> future = respFutureMap.get(requestid);
|
ClientFuture<R, P> future = respFutureMap.get(requestid);
|
||||||
return future == null ? null : future.request;
|
return future == null ? null : future.request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAuthenticated() {
|
public boolean isAuthenticated() {
|
||||||
return authenticated;
|
return authenticated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncConnection getChannel() {
|
public AsyncConnection getChannel() {
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SocketAddress getRemoteAddress() {
|
public SocketAddress getRemoteAddress() {
|
||||||
return channel.getRemoteAddress();
|
return channel.getRemoteAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getDoneRequestCounter() {
|
public long getDoneRequestCounter() {
|
||||||
return doneRequestCounter.longValue();
|
return doneRequestCounter.longValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getDoneResponseCounter() {
|
public long getDoneResponseCounter() {
|
||||||
return doneResponseCounter.longValue();
|
return doneResponseCounter.longValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <C extends ClientCodec<R, P>> C getCodec() {
|
public <C extends ClientCodec<R, P>> C getCodec() {
|
||||||
return (C) codec;
|
return (C) codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxPipelines() {
|
public int getMaxPipelines() {
|
||||||
return maxPipelines;
|
return maxPipelines;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClientConnection setAuthenticated(boolean authenticated) {
|
protected ClientConnection setAuthenticated(boolean authenticated) {
|
||||||
this.authenticated = authenticated;
|
this.authenticated = authenticated;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClientConnection setMaxPipelines(int maxPipelines) {
|
protected ClientConnection setMaxPipelines(int maxPipelines) {
|
||||||
this.maxPipelines = maxPipelines;
|
this.maxPipelines = maxPipelines;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClientConnection resetMaxPipelines() {
|
protected ClientConnection resetMaxPipelines() {
|
||||||
this.maxPipelines = client.maxPipelines;
|
this.maxPipelines = client.maxPipelines;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int runningCount() {
|
public int runningCount() {
|
||||||
return respWaitingCounter.intValue();
|
return respWaitingCounter.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLastWriteTime() {
|
public long getLastWriteTime() {
|
||||||
return channel.getLastWriteTime();
|
return channel.getLastWriteTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLastReadTime() {
|
public long getLastReadTime() {
|
||||||
return channel.getLastReadTime();
|
return channel.getLastReadTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOpen() {
|
public boolean isOpen() {
|
||||||
return channel.isOpen();
|
return channel.isOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String s = super.toString();
|
String s = super.toString();
|
||||||
int pos = s.lastIndexOf('@');
|
int pos = s.lastIndexOf('@');
|
||||||
if (pos < 1) {
|
if (pos < 1) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
int cha = pos + 10 - s.length();
|
int cha = pos + 10 - s.length();
|
||||||
if (cha < 1) {
|
if (cha < 1) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < cha; i++) s += ' ';
|
for (int i = 0; i < cha; i++) s += ' ';
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user