@Override public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception { ChannelFuture f = finishEncode(ctx, ctx.newPromise()); f.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture f) throws Exception { ctx.close(promise); } }); if (!f.isDone()) { // Ensure the channel is closed even if the write operation completes in time. ctx.executor().schedule(new Runnable() { @Override public void run() { ctx.close(promise); } }, 10, TimeUnit.SECONDS); // FIXME: Magic number } }
void writePriority(Http2Stream stream, int streamDependency, short weight, boolean exclusive) { EventExecutor executor = chctx.executor(); if (executor.inEventLoop()) { _writePriority(stream, streamDependency, weight, exclusive); } else { executor.execute(() -> { _writePriority(stream, streamDependency, weight, exclusive); }); } } }
@Override public void close() { if (executor.inEventLoop()) { close0(); } else { executor.submit(new Runnable() { @Override public void run() { close0(); } }).awaitUninterruptibly(); } }
@Override public Future<Channel> acquire(final Promise<Channel> promise) { try { if (executor.inEventLoop()) { acquire0(promise); } else { executor.execute(new Runnable() { @Override public void run() { acquire0(promise); } }); } } catch (Throwable cause) { promise.setFailure(cause); } return promise; }
static void invokeChannelUnregistered(final AbstractChannelHandlerContext next) { EventExecutor executor = next.executor(); if (executor.inEventLoop()) { next.invokeChannelUnregistered(); } else { executor.execute(new Runnable() { @Override public void run() { next.invokeChannelUnregistered(); } }); } }
@Override public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { long size = calculateSize(msg); long now = TrafficCounter.milliSecondFromNano(); if (size > 0) { long wait = trafficCounter.readTimeToWait(size, readLimit, maxTime, now); wait = checkWaitReadTime(ctx, wait, now); if (wait >= MINIMAL_WAIT) { // At least 10ms seems a minimal channel.attr(READ_SUSPENDED).set(true); Attribute<Runnable> attr = channel.attr(REOPEN_TASK); Runnable reopenTask = attr.get(); if (reopenTask == null) { attr.set(reopenTask); ctx.executor().schedule(reopenTask, wait, TimeUnit.MILLISECONDS); if (logger.isDebugEnabled()) { logger.debug("Suspend final status => " + config.isAutoRead() + ':' + isHandlerActive(ctx) + " will reopened at: " + wait); ctx.fireChannelRead(msg);
private void requestClientToCloseConnection() { if (ctx.channel().isActive()) { // Application level protocol for asking client to close connection ctx.writeAndFlush(pushProtocol.goAwayMessage()); // Force close connection if client doesn't close in reasonable time after we made request ctx.executor().schedule(() -> forceCloseConnectionFromServerSide(), CLIENT_CLOSE_GRACE_PERIOD.get(), TimeUnit.SECONDS); } else { forceCloseConnectionFromServerSide(); } }
@Override void submitWrite(final ChannelHandlerContext ctx, final Object msg, final long size, final long delay, final long now, final ChannelPromise promise) { final ToSend newToSend; // write order control synchronized (this) { if (delay == 0 && messagesQueue.isEmpty()) { trafficCounter.bytesRealWriteFlowControl(size); ctx.write(msg, promise); return; } newToSend = new ToSend(delay + now, msg, promise); messagesQueue.addLast(newToSend); queueSize += size; checkWriteSuspend(ctx, delay, queueSize); } final long futureNow = newToSend.relativeTimeAction; ctx.executor().schedule(new Runnable() { @Override public void run() { sendAllValid(ctx, futureNow); } }, delay, TimeUnit.MILLISECONDS); }
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { this.remoteAddress = ctx.channel().remoteAddress(); this.ctx = ctx; if (log.isDebugEnabled()) { log.debug("[{}] Scheduling keep-alive task every {} s", ctx.channel(), keepAliveIntervalSeconds); } if (keepAliveIntervalSeconds > 0) { this.keepAliveTask = ctx.executor().scheduleAtFixedRate(this::handleKeepAliveTimeout, keepAliveIntervalSeconds, keepAliveIntervalSeconds, TimeUnit.SECONDS); } }
public WsClientHandler(ChannelHandlerContext ctx, int pingRate) { this.ctx = ctx; this.ping = this.ctx.executor().scheduleAtFixedRate(() -> { LOG.trace("Sending ping on channel {}", ctx.channel()); ctx.writeAndFlush(new PingWebSocketFrame()); }, pingRate, pingRate, TimeUnit.SECONDS); }
private void verifyRegisteredWithRightExecutor(ChannelHandlerContext ctx) { if (ctx.channel().isRegistered() && !executor.inEventLoop()) { throw new IllegalArgumentException("Channel handler MUST be registered with the same EventExecutor that it is created with."); } }
@Override public void operationComplete(Future<Void> future) throws Exception { assert executor.inEventLoop(); if (closed) { // Since the pool is closed, we have no choice but to close the channel channel.close(); promise.setFailure(POOL_CLOSED_ON_RELEASE_EXCEPTION); return; } if (future.isSuccess()) { decrementAndRunTaskQueue(); promise.setSuccess(null); } else { Throwable cause = future.cause(); // Check if the exception was not because of we passed the Channel to the wrong pool. if (!(cause instanceof IllegalArgumentException)) { decrementAndRunTaskQueue(); } promise.setFailure(future.cause()); } } }));
channel.writeAndFlush(goaway); LOG.debug("gracefullyWithDelay: flushed initial go_away frame. channel=" + channel.id().asShortText()); ctx.executor().schedule(() -> {
/** * Removes a pending write operation and performs it via * {@link ChannelHandlerContext#write(Object, ChannelPromise)}. * * @return {@link ChannelFuture} if something was written and {@code null} * if the {@link PendingWriteQueue} is empty. */ public ChannelFuture removeAndWrite() { assert ctx.executor().inEventLoop(); PendingWrite write = head; if (write == null) { return null; } Object msg = write.msg; ChannelPromise promise = write.promise; recycle(write, true); return ctx.write(msg, promise); }
/** * Removes a pending write operation and release it's message via {@link ReferenceCountUtil#safeRelease(Object)}. * * @return {@link ChannelPromise} of the pending write or {@code null} if the queue is empty. * */ public ChannelPromise remove() { assert ctx.executor().inEventLoop(); PendingWrite write = head; if (write == null) { return null; } ChannelPromise promise = write.promise; ReferenceCountUtil.safeRelease(write.msg); recycle(write, true); return promise; }
@Override public void channelActive(final ChannelHandlerContext ctx) throws Exception { welcomeFuture = ctx.executor().schedule(new Runnable() { @Override public void run() { if (welcome != null) { ctx.write(Unpooled.wrappedBuffer(welcome.getBytes())); ctx.writeAndFlush(Unpooled.wrappedBuffer(prompt.getBytes())); } } }, 500, TimeUnit.MILLISECONDS); }
@Override void execute() { EventExecutor executor = ctx.executor(); if (executor.inEventLoop()) { callHandlerRemoved0(ctx); } else { try { executor.execute(this); } catch (RejectedExecutionException e) { if (logger.isWarnEnabled()) { logger.warn( "Can't invoke handlerRemoved() as the EventExecutor {} rejected it," + " removing handler {}.", executor, ctx.name(), e); } // remove0(...) was call before so just call AbstractChannelHandlerContext.setRemoved(). ctx.setRemoved(); } } } }
/** * Returns {@code true} if there are no pending write operations left in this queue. */ public boolean isEmpty() { assert ctx.executor().inEventLoop(); return head == null; }