下面列出了io.netty.channel.ChannelPipeline#fireChannelReadComplete ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void finishPeerRead0(LocalChannel peer) {
Future<?> peerFinishReadFuture = peer.finishReadFuture;
if (peerFinishReadFuture != null) {
if (!peerFinishReadFuture.isDone()) {
runFinishPeerReadTask(peer);
return;
} else {
// Lazy unset to make sure we don't prematurely unset it while scheduling a new task.
FINISH_READ_FUTURE_UPDATER.compareAndSet(peer, peerFinishReadFuture, null);
}
}
ChannelPipeline peerPipeline = peer.pipeline();
if (peer.readInProgress) {
peer.readInProgress = false;
for (;;) {
Object received = peer.inboundBuffer.poll();
if (received == null) {
break;
}
peerPipeline.fireChannelRead(received);
}
peerPipeline.fireChannelReadComplete();
}
}
@Override
protected void doBeginRead() throws Exception {
if (acceptInProgress) {
return;
}
Queue<Object> inboundBuffer = this.inboundBuffer;
if (inboundBuffer.isEmpty()) {
acceptInProgress = true;
return;
}
ChannelPipeline pipeline = pipeline();
for (;;) {
Object m = inboundBuffer.poll();
if (m == null) {
break;
}
pipeline.fireChannelRead(m);
}
pipeline.fireChannelReadComplete();
}
private boolean handleReadException(ChannelPipeline pipeline, ByteBuf byteBuf, Throwable cause, boolean close) {
if (byteBuf != null) {
if (byteBuf.isReadable()) {
readPending = false;
pipeline.fireChannelRead(byteBuf);
} else {
byteBuf.release();
}
}
pipeline.fireChannelReadComplete();
pipeline.fireExceptionCaught(cause);
if (close || cause instanceof IOException) {
closeOnRead(pipeline);
return true;
}
return false;
}
/**
* Write messages to the inbound of this {@link Channel}.
*
* @param msgs the messages to be written
*
* @return {@code true} if the write operation did add something to the inbound buffer
*/
public boolean writeInbound(Object... msgs) {
ensureOpen();
if (msgs.length == 0) {
return !inboundMessages.isEmpty();
}
ChannelPipeline p = pipeline();
for (Object m: msgs) {
p.fireChannelRead(m);
}
p.fireChannelReadComplete();
runPendingTasks();
checkException();
return !inboundMessages.isEmpty();
}
private void handleReadException(ChannelPipeline pipeline, ByteBuf byteBuf, Throwable cause, boolean close,
RecvByteBufAllocator.Handle allocHandle) {
if (byteBuf != null) {
if (byteBuf.isReadable()) {
readPending = false;
pipeline.fireChannelRead(byteBuf);
} else {
byteBuf.release();
}
}
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
pipeline.fireExceptionCaught(cause);
if (close || cause instanceof IOException) {
closeOnRead(pipeline);
}
}
private void handleReadException(ChannelPipeline pipeline, ByteBuf byteBuf, Throwable cause, boolean close,
KQueueRecvByteAllocatorHandle allocHandle) {
if (byteBuf != null) {
if (byteBuf.isReadable()) {
readPending = false;
pipeline.fireChannelRead(byteBuf);
} else {
byteBuf.release();
}
}
if (!failConnectPromise(cause)) {
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
pipeline.fireExceptionCaught(cause);
if (close || cause instanceof IOException) {
shutdownInput(false);
}
}
}
private void handleReadException(ChannelPipeline pipeline, ByteBuf byteBuf, Throwable cause, boolean close,
EpollRecvByteAllocatorHandle allocHandle) {
if (byteBuf != null) {
if (byteBuf.isReadable()) {
readPending = false;
pipeline.fireChannelRead(byteBuf);
} else {
byteBuf.release();
}
}
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
pipeline.fireExceptionCaught(cause);
if (close || cause instanceof IOException) {
shutdownInput(false);
}
}
private void handleReadException(ChannelPipeline pipeline, ByteBuf byteBuf, Throwable cause, boolean close) {
if (byteBuf != null) {
if (byteBuf.isReadable()) {
pipeline.fireChannelRead(byteBuf);
} else {
try {
byteBuf.release();
} catch (IllegalReferenceCountException ignore) {
// ignore as it may be released already
}
}
}
pipeline.fireChannelReadComplete();
pipeline.fireExceptionCaught(cause);
if (close || cause instanceof IOException) {
closeOnRead();
}
}
private UkcpServerChildChannel createChildChannel(InetSocketAddress remoteAddress) {
Ukcp ukcp = new Ukcp(0, output); // temp conv, need to set conv in outter
UkcpServerChildChannel ch = new UkcpServerChildChannel(this, ukcp, remoteAddress);
ChannelPipeline pipeline = pipeline();
pipeline.fireChannelRead(ch);
pipeline.fireChannelReadComplete();
if (log.isDebugEnabled()) {
log.debug("Create childChannel. remoteAddress={}", remoteAddress);
}
if (this.tsUpdate == -1) { // haven't schedule update
long current = System.currentTimeMillis();
long tsUp = ch.kcpCheck(current);
ch.kcpTsUpdate(tsUp);
scheduleUpdate(tsUp, current);
}
return ch;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket p) throws Exception {
UdpChannel channel = userChannels.compute(p.sender(), (lAddr, lChannel) -> {
return ((lChannel == null) || !lChannel.isOpen()) ? new UdpChannel(UdpServerChannel.this, lAddr) : lChannel;
});
channel.buffers.add(p.content().retain());
if (channel.getIsNew()) {
ChannelPipeline serverPipeline = UdpServerChannel.this.pipeline();
serverPipeline.fireChannelRead(channel);
serverPipeline.fireChannelReadComplete();
} else {
if (channel.isRegistered()) {
channel.read();
}
}
}
@Override
protected void doBeginRead() throws Exception {
if (readInProgress) {
return;
}
ChannelPipeline pipeline = pipeline();
Queue<Object> inboundBuffer = this.inboundBuffer;
if (inboundBuffer.isEmpty()) {
readInProgress = true;
return;
}
final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get();
final Integer stackDepth = threadLocals.localChannelReaderStackDepth();
if (stackDepth < MAX_READER_STACK_DEPTH) {
threadLocals.setLocalChannelReaderStackDepth(stackDepth + 1);
try {
for (;;) {
Object received = inboundBuffer.poll();
if (received == null) {
break;
}
pipeline.fireChannelRead(received);
}
pipeline.fireChannelReadComplete();
} finally {
threadLocals.setLocalChannelReaderStackDepth(stackDepth);
}
} else {
try {
eventLoop().execute(readTask);
} catch (Throwable cause) {
logger.warn("Closing Local channels {}-{} because exception occurred!", this, peer, cause);
close();
peer.close();
PlatformDependent.throwException(cause);
}
}
}
private void serve0(final LocalChannel child) {
inboundBuffer.add(child);
if (acceptInProgress) {
acceptInProgress = false;
ChannelPipeline pipeline = pipeline();
for (;;) {
Object m = inboundBuffer.poll();
if (m == null) {
break;
}
pipeline.fireChannelRead(m);
}
pipeline.fireChannelReadComplete();
}
}
private void serve0(final LocalChannel child) {
inboundBuffer.add(child);
if (acceptInProgress) {
acceptInProgress = false;
ChannelPipeline pipeline = pipeline();
for (;;) {
Object m = inboundBuffer.poll();
if (m == null) {
break;
}
pipeline.fireChannelRead(m);
}
pipeline.fireChannelReadComplete();
}
}
private void readInbound() {
RecvByteBufAllocator.Handle handle = unsafe().recvBufAllocHandle();
handle.reset(config());
ChannelPipeline pipeline = pipeline();
do {
Object m = inboundBuffer.poll();
if (m == null) {
break;
}
pipeline.fireChannelRead(m);
} while (handle.continueReading());
pipeline.fireChannelReadComplete();
}
static void fireChannelRead(Channel ch, CodecOutputList<ByteBuf> bufList) {
ChannelPipeline pipeline = ch.pipeline();
int size = bufList.size();
if (size <= 0) {
return;
}
for (int i = 0; i < size; i++) {
ByteBuf msg = bufList.getUnsafe(i);
pipeline.fireChannelRead(msg);
}
pipeline.fireChannelReadComplete();
}
@Override
public final void read() {
final ChannelConfig config = config();
final ChannelPipeline pipeline = pipeline();
final ByteBufAllocator allocator = config.getAllocator();
final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
allocHandle.reset(config);
ByteBuf byteBuf = null;
boolean close = false;
try {
do {
byteBuf = allocHandle.allocate(allocator);
allocHandle.lastBytesRead(doReadBytes(byteBuf));
if (allocHandle.lastBytesRead() <= 0) {
// nothing was read. release the buffer.
byteBuf.release();
byteBuf = null;
close = allocHandle.lastBytesRead() < 0;
if (close) {
// There is nothing left to read as we received an EOF.
readPending = false;
}
break;
}
allocHandle.incMessagesRead(1);
readPending = false;
pipeline.fireChannelRead(byteBuf);
byteBuf = null;
} while (allocHandle.continueReading());
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
if (close) {
closeOnRead(pipeline);
}
} catch (Throwable t) {
handleReadException(pipeline, byteBuf, t, close, allocHandle);
} finally {
// Check if there is a readPending which was not processed yet.
// This could be for two reasons:
// * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method
// * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method
//
// See https://github.com/netty/netty/issues/2254
if (!readPending && !config.isAutoRead()) {
removeReadOp();
}
}
}
@Override
void readReady(final KQueueRecvByteAllocatorHandle allocHandle) {
final ChannelConfig config = config();
if (shouldBreakReadReady(config)) {
clearReadFilter0();
return;
}
final ChannelPipeline pipeline = pipeline();
final ByteBufAllocator allocator = config.getAllocator();
allocHandle.reset(config);
readReadyBefore();
ByteBuf byteBuf = null;
boolean close = false;
try {
do {
// we use a direct buffer here as the native implementations only be able
// to handle direct buffers.
byteBuf = allocHandle.allocate(allocator);
allocHandle.lastBytesRead(doReadBytes(byteBuf));
if (allocHandle.lastBytesRead() <= 0) {
// nothing was read, release the buffer.
byteBuf.release();
byteBuf = null;
close = allocHandle.lastBytesRead() < 0;
if (close) {
// There is nothing left to read as we received an EOF.
readPending = false;
}
break;
}
allocHandle.incMessagesRead(1);
readPending = false;
pipeline.fireChannelRead(byteBuf);
byteBuf = null;
if (shouldBreakReadReady(config)) {
// We need to do this for two reasons:
//
// - If the input was shutdown in between (which may be the case when the user did it in the
// fireChannelRead(...) method we should not try to read again to not produce any
// miss-leading exceptions.
//
// - If the user closes the channel we need to ensure we not try to read from it again as
// the filedescriptor may be re-used already by the OS if the system is handling a lot of
// concurrent connections and so needs a lot of filedescriptors. If not do this we risk
// reading data from a filedescriptor that belongs to another socket then the socket that
// was "wrapped" by this Channel implementation.
break;
}
} while (allocHandle.continueReading());
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
if (close) {
shutdownInput(false);
}
} catch (Throwable t) {
handleReadException(pipeline, byteBuf, t, close, allocHandle);
} finally {
readReadyFinally(config);
}
}
private void readReadyFd() {
if (socket.isInputShutdown()) {
super.clearReadFilter0();
return;
}
final ChannelConfig config = config();
final KQueueRecvByteAllocatorHandle allocHandle = recvBufAllocHandle();
final ChannelPipeline pipeline = pipeline();
allocHandle.reset(config);
readReadyBefore();
try {
readLoop: do {
// lastBytesRead represents the fd. We use lastBytesRead because it must be set so that the
// KQueueRecvByteAllocatorHandle knows if it should try to read again or not when autoRead is
// enabled.
int recvFd = socket.recvFd();
switch(recvFd) {
case 0:
allocHandle.lastBytesRead(0);
break readLoop;
case -1:
allocHandle.lastBytesRead(-1);
close(voidPromise());
return;
default:
allocHandle.lastBytesRead(1);
allocHandle.incMessagesRead(1);
readPending = false;
pipeline.fireChannelRead(new FileDescriptor(recvFd));
break;
}
} while (allocHandle.continueReading());
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
} catch (Throwable t) {
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
pipeline.fireExceptionCaught(t);
} finally {
readReadyFinally(config);
}
}
@Override
void epollInReady() {
final ChannelConfig config = config();
if (shouldBreakEpollInReady(config)) {
clearEpollIn0();
return;
}
final EpollRecvByteAllocatorHandle allocHandle = recvBufAllocHandle();
allocHandle.edgeTriggered(isFlagSet(Native.EPOLLET));
final ChannelPipeline pipeline = pipeline();
final ByteBufAllocator allocator = config.getAllocator();
allocHandle.reset(config);
epollInBefore();
ByteBuf byteBuf = null;
boolean close = false;
try {
do {
if (spliceQueue != null) {
SpliceInTask spliceTask = spliceQueue.peek();
if (spliceTask != null) {
if (spliceTask.spliceIn(allocHandle)) {
// We need to check if it is still active as if not we removed all SpliceTasks in
// doClose(...)
if (isActive()) {
spliceQueue.remove();
}
continue;
} else {
break;
}
}
}
// we use a direct buffer here as the native implementations only be able
// to handle direct buffers.
byteBuf = allocHandle.allocate(allocator);
allocHandle.lastBytesRead(doReadBytes(byteBuf));
if (allocHandle.lastBytesRead() <= 0) {
// nothing was read, release the buffer.
byteBuf.release();
byteBuf = null;
close = allocHandle.lastBytesRead() < 0;
if (close) {
// There is nothing left to read as we received an EOF.
readPending = false;
}
break;
}
allocHandle.incMessagesRead(1);
readPending = false;
pipeline.fireChannelRead(byteBuf);
byteBuf = null;
if (shouldBreakEpollInReady(config)) {
// We need to do this for two reasons:
//
// - If the input was shutdown in between (which may be the case when the user did it in the
// fireChannelRead(...) method we should not try to read again to not produce any
// miss-leading exceptions.
//
// - If the user closes the channel we need to ensure we not try to read from it again as
// the filedescriptor may be re-used already by the OS if the system is handling a lot of
// concurrent connections and so needs a lot of filedescriptors. If not do this we risk
// reading data from a filedescriptor that belongs to another socket then the socket that
// was "wrapped" by this Channel implementation.
break;
}
} while (allocHandle.continueReading());
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
if (close) {
shutdownInput(false);
}
} catch (Throwable t) {
handleReadException(pipeline, byteBuf, t, close, allocHandle);
} finally {
epollInFinally(config);
}
}
@Override
void epollInReady() {
final ChannelConfig config = config();
boolean edgeTriggered = isFlagSet(Native.EPOLLET);
if (!readPending && !edgeTriggered && !config.isAutoRead()) {
// ChannelConfig.setAutoRead(false) was called in the meantime
clearEpollIn0();
return;
}
final ChannelPipeline pipeline = pipeline();
final ByteBufAllocator allocator = config.getAllocator();
RecvByteBufAllocator.Handle allocHandle = this.allocHandle;
if (allocHandle == null) {
this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle();
}
ByteBuf byteBuf = null;
boolean close = false;
try {
// if edgeTriggered is used we need to read all messages as we are not notified again otherwise.
final int maxMessagesPerRead = edgeTriggered
? Integer.MAX_VALUE : config.getMaxMessagesPerRead();
int messages = 0;
int totalReadAmount = 0;
do {
// we use a direct buffer here as the native implementations only be able
// to handle direct buffers.
byteBuf = allocHandle.allocate(allocator);
int writable = byteBuf.writableBytes();
int localReadAmount = doReadBytes(byteBuf);
if (localReadAmount <= 0) {
// not was read release the buffer
byteBuf.release();
close = localReadAmount < 0;
break;
}
readPending = false;
pipeline.fireChannelRead(byteBuf);
byteBuf = null;
if (totalReadAmount >= Integer.MAX_VALUE - localReadAmount) {
allocHandle.record(totalReadAmount);
// Avoid overflow.
totalReadAmount = localReadAmount;
} else {
totalReadAmount += localReadAmount;
}
if (localReadAmount < writable) {
// Read less than what the buffer can hold,
// which might mean we drained the recv buffer completely.
break;
}
if (!edgeTriggered && !config.isAutoRead()) {
// This is not using EPOLLET so we can stop reading
// ASAP as we will get notified again later with
// pending data
break;
}
} while (++ messages < maxMessagesPerRead);
pipeline.fireChannelReadComplete();
allocHandle.record(totalReadAmount);
if (close) {
closeOnRead(pipeline);
close = false;
}
} catch (Throwable t) {
boolean closed = handleReadException(pipeline, byteBuf, t, close);
if (!closed) {
// trigger a read again as there may be something left to read and because of epoll ET we
// will not get notified again until we read everything from the socket
eventLoop().execute(new Runnable() {
@Override
public void run() {
epollInReady();
}
});
}
} finally {
// Check if there is a readPending which was not processed yet.
// This could be for two reasons:
// * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method
// * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method
//
// See https://github.com/netty/netty/issues/2254
if (!readPending && !config.isAutoRead()) {
clearEpollIn0();
}
}
}