Java Code Examples for io.netty.util.concurrent.Promise#addListener()

The following examples show how to use io.netty.util.concurrent.Promise#addListener() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Http1TunnelConnectionPool.java    From aws-sdk-java-v2 with Apache License 2.0 5 votes vote down vote up
private void setupChannel(Channel ch, Promise<Channel> acquirePromise) {
    if (isTunnelEstablished(ch)) {
        log.debug(() -> String.format("Tunnel already established for %s", ch.id().asShortText()));
        acquirePromise.setSuccess(ch);
        return;
    }

    log.debug(() -> String.format("Tunnel not yet established for channel %s. Establishing tunnel now.",
            ch.id().asShortText()));

    Promise<Channel> tunnelEstablishedPromise = eventLoop.newPromise();

    SslHandler sslHandler = createSslHandlerIfNeeded(ch.alloc());
    if (sslHandler != null) {
        ch.pipeline().addLast(sslHandler);
    }
    ch.pipeline().addLast(initHandlerSupplier.newInitHandler(delegate, remoteAddress, tunnelEstablishedPromise));

    tunnelEstablishedPromise.addListener((Future<Channel> f) -> {
        if (f.isSuccess()) {
            Channel tunnel = f.getNow();
            handler.channelCreated(tunnel);
            tunnel.attr(TUNNEL_ESTABLISHED_KEY).set(true);
            acquirePromise.setSuccess(tunnel);
        } else {
            ch.close();
            delegate.release(ch);

            Throwable cause = f.cause();
            log.error(() -> String.format("Unable to establish tunnel for channel %s", ch.id().asShortText()), cause);
            acquirePromise.setFailure(cause);
        }
    });
}
 
Example 2
Source File: MultiplexedChannelRecord.java    From ambry with Apache License 2.0 5 votes vote down vote up
private void releaseClaimOnFailure(Promise<Channel> promise) {
  try {
    promise.addListener(f -> {
      if (!promise.isSuccess()) {
        releaseClaim();
      }
    });
  } catch (Throwable e) {
    releaseClaim();
    throw e;
  }
}
 
Example 3
Source File: Http2MultiplexedChannelPool.java    From ambry with Apache License 2.0 5 votes vote down vote up
/**
 * Acquire a stream on a connection that has already been initialized. This will return false if the connection cannot have
 * any more streams allocated, and true if the stream can be allocated.
 *
 * This will NEVER complete the provided future when the return value is false. This will ALWAYS complete the provided
 * future when the return value is true.
 */
private boolean acquireStreamOnInitializedConnection(MultiplexedChannelRecord channelRecord,
    Promise<Channel> promise) {
  long startTime = System.currentTimeMillis();
  Promise<Channel> acquirePromise = channelRecord.getParentChannel().eventLoop().newPromise();

  if (!channelRecord.acquireStream(acquirePromise)) {
    return false;
  }

  acquirePromise.addListener(f -> {
    try {
      if (!acquirePromise.isSuccess()) {
        promise.setFailure(acquirePromise.cause());
        return;
      }

      Channel channel = acquirePromise.getNow();
      channel.parent().attr(HTTP2_MULTIPLEXED_CHANNEL_POOL).set(this);
      channel.parent().attr(MULTIPLEXED_CHANNEL).set(channelRecord);
      promise.setSuccess(channel);
      http2ClientMetrics.http2RegularStreamAcquireTime.update(System.currentTimeMillis() - startTime);
    } catch (Exception e) {
      promise.setFailure(e);
    }
  });

  return true;
}
 
Example 4
Source File: Http2MultiplexedChannelPool.java    From ambry with Apache License 2.0 5 votes vote down vote up
private void acquireStreamOnFreshConnection(Promise<Channel> promise, Channel parentChannel) {
  long startTime = System.currentTimeMillis();
  try {
    MultiplexedChannelRecord multiplexedChannel =
        new MultiplexedChannelRecord(parentChannel, http2ClientConfig.http2MaxConcurrentStreamsPerConnection,
            http2ClientConfig.idleConnectionTimeoutMs, streamChannelInitializer);
    parentChannel.attr(MULTIPLEXED_CHANNEL).set(multiplexedChannel);

    Promise<Channel> streamPromise = parentChannel.eventLoop().newPromise();

    if (!acquireStreamOnInitializedConnection(multiplexedChannel, streamPromise)) {
      failAndCloseParent(promise, parentChannel,
          new IOException("Connection was closed while creating a new stream."));
      return;
    }

    streamPromise.addListener(f -> {
      if (!streamPromise.isSuccess()) {
        promise.setFailure(streamPromise.cause());
        return;
      }

      Channel stream = streamPromise.getNow();
      cacheConnectionForFutureStreams(stream, multiplexedChannel, promise);
      http2ClientMetrics.http2FirstStreamAcquireTime.update(System.currentTimeMillis() - startTime);
    });
  } catch (Throwable e) {
    failAndCloseParent(promise, parentChannel, e);
  }
}
 
Example 5
Source File: ResponsePromise.java    From etcd4j with Apache License 2.0 5 votes vote down vote up
/**
 * Attach Netty Promise
 *
 * @param promise netty promise to set up response promise with
 */
public void attachNettyPromise(Promise<T> promise) {
  promise.addListener(promiseHandler);
  Promise<T> oldPromise = this.promise;

  this.promise = promise;

  if (oldPromise != null) {
    oldPromise.removeListener(promiseHandler);
    oldPromise.cancel(true);
  }
}
 
Example 6
Source File: HttpChannelPool.java    From armeria with Apache License 2.0 5 votes vote down vote up
private void connect(SessionProtocol desiredProtocol, PoolKey key, ChannelAcquisitionFuture promise,
                     ClientConnectionTimingsBuilder timingsBuilder) {
    setPendingAcquisition(desiredProtocol, key, promise);
    timingsBuilder.socketConnectStart();

    final InetSocketAddress remoteAddress;
    try {
        remoteAddress = toRemoteAddress(key);
    } catch (UnknownHostException e) {
        notifyConnect(desiredProtocol, key, eventLoop.newFailedFuture(e), promise, timingsBuilder);
        return;
    }

    // Fail immediately if it is sure that the remote address doesn't support the desired protocol.
    if (SessionProtocolNegotiationCache.isUnsupported(remoteAddress, desiredProtocol)) {
        notifyConnect(desiredProtocol, key,
                      eventLoop.newFailedFuture(
                              new SessionProtocolNegotiationException(
                                      desiredProtocol, "previously failed negotiation")),
                      promise, timingsBuilder);
        return;
    }

    // Create a new connection.
    final Promise<Channel> sessionPromise = eventLoop.newPromise();
    connect(remoteAddress, desiredProtocol, sessionPromise);

    if (sessionPromise.isDone()) {
        notifyConnect(desiredProtocol, key, sessionPromise, promise, timingsBuilder);
    } else {
        sessionPromise.addListener((Future<Channel> future) -> {
            notifyConnect(desiredProtocol, key, future, promise, timingsBuilder);
        });
    }
}
 
Example 7
Source File: ProxyEndpoint.java    From zuul with Apache License 2.0 5 votes vote down vote up
private void proxyRequestToOrigin() {
    Promise<PooledConnection> promise = null;
    try {
        attemptNum += 1;

        IClientConfig requestConfig = origin.getExecutionContext(zuulRequest).getRequestConfig();
        setReadTimeoutOnContext(requestConfig, attemptNum);

        currentRequestStat = createRequestStat();
        origin.preRequestChecks(zuulRequest);
        concurrentReqCount++;

        // update RPS trackers
        updateOriginRpsTrackers(origin, attemptNum);

        // We pass this AtomicReference<Server> here and the origin impl will assign the chosen server to it.
        promise = origin.connectToOrigin(
                zuulRequest, channelCtx.channel().eventLoop(), attemptNum, passport, chosenServer, chosenHostAddr);

        storeAndLogOriginRequestInfo();
        currentRequestAttempt = origin.newRequestAttempt(chosenServer.get(), context, attemptNum);
        requestAttempts.add(currentRequestAttempt);
        passport.add(PassportState.ORIGIN_CONN_ACQUIRE_START);

        if (promise.isDone()) {
            operationComplete(promise);
        } else {
            promise.addListener(this);
        }
    }
    catch (Exception ex) {
        LOG.error("Error while connecting to origin, UUID {} " + context.getUUID(), ex);
        storeAndLogOriginRequestInfo();
        if (promise != null && ! promise.isDone()) {
            promise.setFailure(ex);
        } else {
            errorFromOrigin(ex);
        }
    }
}
 
Example 8
Source File: Socks4ProxyHandler.java    From cute-proxy with BSD 2-Clause "Simplified" License 5 votes vote down vote up
@Override
public void channelRead0(ChannelHandlerContext ctx, Socks4Message socksRequest) {
    Socks4CommandRequest command = (Socks4CommandRequest) socksRequest;
    if (command.type() != Socks4CommandType.CONNECT) {
        NettyUtils.closeOnFlush(ctx.channel());
        logger.error("unsupported socks4 command: {}", command.type());
        return;
    }
    Promise<Channel> promise = ctx.executor().newPromise();
    Bootstrap bootstrap = initBootStrap(promise, ctx.channel().eventLoop());

    bootstrap.connect(command.dstAddr(), command.dstPort()).addListener((ChannelFutureListener) future -> {
        if (future.isSuccess()) {
            ctx.channel().writeAndFlush(new DefaultSocks4CommandResponse(REJECTED_OR_FAILED));
            NettyUtils.closeOnFlush(ctx.channel());
        }
    });

    promise.addListener((FutureListener<Channel>) future -> {
        Channel outboundChannel = future.getNow();
        if (!future.isSuccess()) {
            ctx.channel().writeAndFlush(new DefaultSocks4CommandResponse(REJECTED_OR_FAILED));
            NettyUtils.closeOnFlush(ctx.channel());
            return;
        }
        ChannelFuture responseFuture = ctx.channel().writeAndFlush(new DefaultSocks4CommandResponse(SUCCESS));

        responseFuture.addListener((ChannelFutureListener) channelFuture -> {
            ctx.pipeline().remove(Socks4ProxyHandler.this);
            ctx.pipeline().remove(Socks4ServerEncoder.class);
            ctx.pipeline().remove(Socks4ServerDecoder.class);
            var address = HostPort.of(command.dstAddr(), command.dstPort());
            initTcpProxyHandlers(ctx, address, outboundChannel);
        });
    });
}
 
Example 9
Source File: HttpConnectProxyInitializer.java    From cute-proxy with BSD 2-Clause "Simplified" License 5 votes vote down vote up
@Override
public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) {
    Promise<Channel> promise = ctx.executor().newPromise();
    Bootstrap bootstrap = initBootStrap(promise, ctx.channel().eventLoop());

    var address = HostPort.parse(request.uri());
    bootstrap.connect(address.host(), address.ensurePort()).addListener((ChannelFutureListener) future -> {
        if (!future.isSuccess()) {
            ctx.channel().writeAndFlush(new DefaultFullHttpResponse(HTTP_1_1, BAD_GATEWAY));
            NettyUtils.closeOnFlush(ctx.channel());
        }
    });

    promise.addListener((FutureListener<Channel>) future -> {
        if (!future.isSuccess()) {
            ctx.channel().writeAndFlush(new DefaultFullHttpResponse(HTTP_1_1, BAD_GATEWAY));
            NettyUtils.closeOnFlush(ctx.channel());
            return;
        }

        Channel outboundChannel = future.getNow();
        ChannelFuture responseFuture = ctx.channel().writeAndFlush(new DefaultFullHttpResponse(HTTP_1_1, OK));
        responseFuture.addListener((ChannelFutureListener) channelFuture -> {
            logger.debug("try to remove HttpConnectProxyInitializer, pipeline: {}", ctx.pipeline());
            //FIXME: throw NoSuchElementException
            if (removed) {
                logger.warn("HttpConnectProxyInitializer removed by others?");
                ctx.close();
                return;
            }
            ctx.pipeline().remove(HttpConnectProxyInitializer.this);
            ctx.pipeline().remove(HttpServerCodec.class);
            initTcpProxyHandlers(ctx, address, outboundChannel);
        });
    });
}
 
Example 10
Source File: DnsNameResolverContext.java    From netty-4.1.22 with Apache License 2.0 5 votes vote down vote up
private void doSearchDomainQuery(String hostname, FutureListener<T> listener) {
    DnsNameResolverContext<T> nextContext = newResolverContext(parent, hostname, additionals, resolveCache,
            nameServerAddrs);
    Promise<T> nextPromise = parent.executor().newPromise();
    nextContext.internalResolve(nextPromise);
    nextPromise.addListener(listener);
}
 
Example 11
Source File: HealthCheckedChannelPool.java    From aws-sdk-java-v2 with Apache License 2.0 5 votes vote down vote up
/**
 * Try to acquire a channel from the underlying pool. This will keep retrying the acquisition until the provided result
 * future is completed.
 *
 * @param resultFuture The future that should be completed with the acquired channel. If this is completed external to this
 * function, this function will stop trying to acquire a channel.
 * @param timeoutFuture The future for the timeout task. This future will be cancelled when a channel is acquired.
 */
private void tryAcquire(Promise<Channel> resultFuture, ScheduledFuture<?> timeoutFuture) {
    // Something else completed the future (probably a timeout). Stop trying to get a channel.
    if (resultFuture.isDone()) {
        return;
    }

    Promise<Channel> delegateFuture = eventLoopGroup.next().newPromise();
    delegate.acquire(delegateFuture);
    delegateFuture.addListener(f -> ensureAcquiredChannelIsHealthy(delegateFuture, resultFuture, timeoutFuture));
}
 
Example 12
Source File: MultiplexedChannelRecord.java    From aws-sdk-java-v2 with Apache License 2.0 5 votes vote down vote up
private void releaseClaimOnFailure(Promise<Channel> promise) {
    try {
        promise.addListener(f -> {
            if (!promise.isSuccess()) {
                releaseClaim();
            }
        });
    } catch (Throwable e) {
        releaseClaim();
        throw e;
    }
}
 
Example 13
Source File: Http2MultiplexedChannelPool.java    From aws-sdk-java-v2 with Apache License 2.0 5 votes vote down vote up
/**
 * Acquire a stream on a connection that has already been initialized. This will return false if the connection cannot have
 * any more streams allocated, and true if the stream can be allocated.
 *
 * This will NEVER complete the provided future when the return value is false. This will ALWAYS complete the provided
 * future when the return value is true.
 */
private boolean acquireStreamOnInitializedConnection(MultiplexedChannelRecord channelRecord, Promise<Channel> promise) {
    Promise<Channel> acquirePromise = channelRecord.getConnection().eventLoop().newPromise();

    if (!channelRecord.acquireStream(acquirePromise)) {
        return false;
    }

    acquirePromise.addListener(f -> {
        try {
            if (!acquirePromise.isSuccess()) {
                promise.setFailure(acquirePromise.cause());
                return;
            }

            Channel channel = acquirePromise.getNow();
            channel.attr(ChannelAttributeKey.HTTP2_MULTIPLEXED_CHANNEL_POOL).set(this);
            channel.attr(MULTIPLEXED_CHANNEL).set(channelRecord);
            promise.setSuccess(channel);

            tryExpandConnectionWindow(channel.parent());
        } catch (Exception e) {
            promise.setFailure(e);
        }
    });

    return true;
}
 
Example 14
Source File: Http2MultiplexedChannelPool.java    From aws-sdk-java-v2 with Apache License 2.0 5 votes vote down vote up
private void acquireStreamOnFreshConnection(Promise<Channel> promise, Channel parentChannel, Protocol protocol) {
    try {
        Long maxStreams = parentChannel.attr(MAX_CONCURRENT_STREAMS).get();

        Validate.isTrue(protocol == Protocol.HTTP2,
                        "Protocol negotiated on connection (%s) was expected to be HTTP/2, but it "
                        + "was %s.", parentChannel, Protocol.HTTP1_1);
        Validate.isTrue(maxStreams != null,
                        "HTTP/2 was negotiated on the connection (%s), but the maximum number of "
                        + "streams was not initialized.", parentChannel);
        Validate.isTrue(maxStreams > 0, "Maximum streams were not positive on channel (%s).", parentChannel);

        MultiplexedChannelRecord multiplexedChannel = new MultiplexedChannelRecord(parentChannel, maxStreams,
                                                                                   idleConnectionTimeout);
        parentChannel.attr(MULTIPLEXED_CHANNEL).set(multiplexedChannel);

        Promise<Channel> streamPromise = parentChannel.eventLoop().newPromise();

        if (!acquireStreamOnInitializedConnection(multiplexedChannel, streamPromise)) {
            failAndCloseParent(promise, parentChannel,
                               new IOException("Connection was closed while creating a new stream."));
            return;
        }

        streamPromise.addListener(f -> {
            if (!streamPromise.isSuccess()) {
                promise.setFailure(streamPromise.cause());
                return;
            }

            Channel stream = streamPromise.getNow();
            cacheConnectionForFutureStreams(stream, multiplexedChannel, promise);
        });
    } catch (Throwable e) {
        failAndCloseParent(promise, parentChannel, e);
    }
}
 
Example 15
Source File: NettyRequestExecutor.java    From aws-sdk-java-v2 with Apache License 2.0 5 votes vote down vote up
@SuppressWarnings("unchecked")
public CompletableFuture<Void> execute() {
    Promise<Channel> channelFuture = context.eventLoopGroup().next().newPromise();
    context.channelPool().acquire(channelFuture);
    executeFuture = createExecuteFuture(channelFuture);
    channelFuture.addListener((GenericFutureListener) this::makeRequestListener);
    return executeFuture;
}
 
Example 16
Source File: ImapClient.java    From NioImapClient with Apache License 2.0 5 votes vote down vote up
/**
 * Sends a command. If there is currently a command in progress, this command will be queued and executed when the currently running command finishes.
 * It is possible for a command to be queued and then a connection closed before it is actually executed, so it is important to listen to the returned future in order to ensure that the command was completed.
 *
 * @param imapCommand command to send
 * @param <T>         Response type
 * @return Response future. Will be completed when a tagged response is received for this command.
 */
public synchronized <T extends ImapResponse> CompletableFuture<T> sendRaw(ImapCommand imapCommand) {
  final Promise<T> commandPromise = promiseExecutor.next().newPromise();
  commandPromise.addListener((f) -> {
    writeNext();
  });

  send(imapCommand, commandPromise);

  return NettyCompletableFuture.from(commandPromise);
}
 
Example 17
Source File: SslHandler.java    From netty-4.1.22 with Apache License 2.0 5 votes vote down vote up
private void applyHandshakeTimeout(Promise<Channel> p) {
    final Promise<Channel> promise = p == null ? handshakePromise : p;
    // Set timeout if necessary.
    final long handshakeTimeoutMillis = this.handshakeTimeoutMillis;
    if (handshakeTimeoutMillis <= 0 || promise.isDone()) {
        return;
    }

    final ScheduledFuture<?> timeoutFuture = ctx.executor().schedule(new Runnable() {
        @Override
        public void run() {
            if (promise.isDone()) {
                return;
            }
            try {
                if (handshakePromise.tryFailure(HANDSHAKE_TIMED_OUT)) {
                    SslUtils.handleHandshakeFailure(ctx, HANDSHAKE_TIMED_OUT, true);
                }
            } finally {
                releaseAndFailAll(HANDSHAKE_TIMED_OUT);
            }
        }
    }, handshakeTimeoutMillis, TimeUnit.MILLISECONDS);

    // Cancel the handshake timeout when handshake is finished.
    promise.addListener(new FutureListener<Channel>() {
        @Override
        public void operationComplete(Future<Channel> f) throws Exception {
            timeoutFuture.cancel(false);
        }
    });
}
 
Example 18
Source File: RequestContextTest.java    From armeria with Apache License 2.0 4 votes vote down vote up
@Test
public void contextAwareEventExecutor() throws Exception {
    when(channel.eventLoop()).thenReturn(eventLoop.get());
    final RequestContext context = createContext();
    final Set<Integer> callbacksCalled = Collections.newSetFromMap(new ConcurrentHashMap<>());
    final EventExecutor executor = context.contextAwareEventLoop();
    final CountDownLatch latch = new CountDownLatch(18);
    executor.execute(() -> checkCallback(1, context, callbacksCalled, latch));
    executor.schedule(() -> checkCallback(2, context, callbacksCalled, latch), 0, TimeUnit.SECONDS);
    executor.schedule(() -> {
        checkCallback(2, context, callbacksCalled, latch);
        return "success";
    }, 0, TimeUnit.SECONDS);
    executor.scheduleAtFixedRate(() -> checkCallback(3, context, callbacksCalled, latch), 0, 1000,
                                 TimeUnit.SECONDS);
    executor.scheduleWithFixedDelay(() -> checkCallback(4, context, callbacksCalled, latch), 0, 1000,
                                    TimeUnit.SECONDS);
    executor.submit(() -> checkCallback(5, context, callbacksCalled, latch));
    executor.submit(() -> checkCallback(6, context, callbacksCalled, latch), "success");
    executor.submit(() -> {
        checkCallback(7, context, callbacksCalled, latch);
        return "success";
    });
    executor.invokeAll(makeTaskList(8, 10, context, callbacksCalled, latch));
    executor.invokeAll(makeTaskList(11, 12, context, callbacksCalled, latch), 10000, TimeUnit.SECONDS);
    executor.invokeAny(makeTaskList(13, 13, context, callbacksCalled, latch));
    executor.invokeAny(makeTaskList(14, 14, context, callbacksCalled, latch), 10000, TimeUnit.SECONDS);
    final Promise<String> promise = executor.newPromise();
    promise.addListener(f -> checkCallback(15, context, callbacksCalled, latch));
    promise.setSuccess("success");
    executor.newSucceededFuture("success")
            .addListener(f -> checkCallback(16, context, callbacksCalled, latch));
    executor.newFailedFuture(new IllegalArgumentException())
            .addListener(f -> checkCallback(17, context, callbacksCalled, latch));
    final ProgressivePromise<String> progressivePromise = executor.newProgressivePromise();
    progressivePromise.addListener(f -> checkCallback(18, context, callbacksCalled, latch));
    progressivePromise.setSuccess("success");
    latch.await();
    eventLoop.get().shutdownGracefully();
    await().untilAsserted(() -> {
        assertThat(callbacksCalled).containsExactlyElementsOf(IntStream.rangeClosed(1, 18)
                                                                       .boxed()::iterator);
    });
}
 
Example 19
Source File: ImapClient.java    From NioImapClient with Apache License 2.0 4 votes vote down vote up
private Future sendLogout() {
  Promise<TaggedResponse> logoutPromise = promiseExecutor.next().newPromise();
  actuallySend(new BaseImapCommand(ImapCommandType.LOGOUT), logoutPromise);

  return logoutPromise.addListener(future1 -> closeNow());
}
 
Example 20
Source File: RntbdClientChannelPool.java    From azure-cosmosdb-java with MIT License 2 votes vote down vote up
private void acquire0(final Promise<Channel> promise) {

        checkState(this.executor.inEventLoop());

        if (this.isClosed()) {
            promise.setFailure(POOL_CLOSED_ON_ACQUIRE);
            return;
        }

        if (this.acquiredChannelCount.get() < this.maxChannels) {

            // We need to create a new promise to ensure the AcquireListener runs in the correct event loop

            checkState(this.acquiredChannelCount.get() >= 0);

            final AcquireListener l = new AcquireListener(this, promise);
            l.acquired();

            final Promise<Channel> p = this.executor.newPromise();
            p.addListener(l);

            super.acquire(p); // acquire an existing channel or create and acquire a new channel

        } else {

            if (this.pendingAcquisitionQueue.size() >= this.maxPendingAcquisitions) {

                promise.setFailure(TOO_MANY_PENDING_ACQUISITIONS);

            } else {

                // Add a task to the pending acquisition queue and we'll satisfy the request later

                AcquireTask task = new AcquireTask(this, promise);

                if (this.pendingAcquisitionQueue.offer(task)) {

                    if (acquisitionTimeoutTask != null) {
                        task.timeoutFuture = executor.schedule(acquisitionTimeoutTask, acquisitionTimeoutNanos, TimeUnit.NANOSECONDS);
                    }

                } else {
                    promise.setFailure(TOO_MANY_PENDING_ACQUISITIONS);
                }
            }

            checkState(this.pendingAcquisitionQueue.size() > 0);
        }
    }