Example usage for io.netty.util.concurrent PromiseCombiner finish

List of usage examples for io.netty.util.concurrent PromiseCombiner finish

Introduction

In this page you can find the example usage for io.netty.util.concurrent PromiseCombiner finish.

Prototype

public void finish(Promise<Void> aggregatePromise) 

Source Link

Document

Sets the promise to be notified when all combined futures have finished.

Usage

From source file:com.linkedin.r2.transport.http.client.Http2StreamCodec.java

License:Apache License

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
    if (!(msg instanceof RequestWithCallback)) {
        ctx.write(msg, promise);/*from ww w .  ja  va2  s.co  m*/
        return;
    }

    Request request = ((RequestWithCallback) msg).request();
    Http2ConnectionEncoder encoder = encoder();
    int streamId = connection().local().incrementAndGetNextStreamId();
    if (request instanceof StreamRequest) {
        LOG.debug("Writing StreamRequest...");
        StreamRequest streamRequest = (StreamRequest) request;
        Http2Headers http2Headers = NettyRequestAdapter.toHttp2Headers(streamRequest);
        BufferedReader reader = new BufferedReader(ctx, encoder, streamId,
                ((RequestWithCallback) msg).handle());
        streamRequest.getEntityStream().setReader(reader);
        encoder.writeHeaders(ctx, streamId, http2Headers, NO_PADDING, NOT_END_STREAM, promise)
                .addListener(future -> reader.request());
        LOG.debug("Sent HTTP/2 HEADERS frame, stream={}, end={}, headers={}, padding={}bytes",
                new Object[] { streamId, NOT_END_STREAM, http2Headers.size(), NO_PADDING });
    } else if (request instanceof RestRequest) {
        LOG.debug("Writing RestRequest...");
        PromiseCombiner promiseCombiner = new PromiseCombiner();
        ChannelPromise headersPromise = ctx.channel().newPromise();
        ChannelPromise dataPromise = ctx.channel().newPromise();
        promiseCombiner.add(headersPromise);
        promiseCombiner.add(dataPromise);
        promiseCombiner.finish(promise);

        RestRequest restRequest = (RestRequest) request;
        Http2Headers headers = NettyRequestAdapter.toHttp2Headers(restRequest);
        encoder.writeHeaders(ctx, streamId, headers, NO_PADDING, NOT_END_STREAM, headersPromise);
        LOG.debug("Sent HTTP/2 HEADERS frame, stream={}, end={}, headers={}, padding={}bytes",
                new Object[] { streamId, NOT_END_STREAM, headers.size(), NO_PADDING });
        ByteBuf data = Unpooled.wrappedBuffer(restRequest.getEntity().asByteBuffer());
        encoder.writeData(ctx, streamId, data, NO_PADDING, END_STREAM, dataPromise);
        LOG.debug("Sent HTTP/2 DATA frame, stream={}, end={}, data={}bytes, padding={}bytes",
                new Object[] { streamId, END_STREAM, data.readableBytes(), NO_PADDING });
    } else {
        // Request type is not supported. Returns channel back to the pool and throws exception.
        ctx.fireChannelRead(((RequestWithCallback) msg).handle());
        throw new IllegalArgumentException("Request is neither StreamRequest or RestRequest");
    }

    // Sets TransportCallback as a stream property to be retrieved later
    TransportCallback<?> callback = ((RequestWithCallback) msg).callback();
    Http2Connection.PropertyKey callbackKey = ctx.channel()
            .attr(Http2ClientPipelineInitializer.CALLBACK_ATTR_KEY).get();
    connection().stream(streamId).setProperty(callbackKey, callback);

    // Sets AsyncPoolHandle as a stream property to be retrieved later
    AsyncPoolHandle<?> handle = ((RequestWithCallback) msg).handle();
    Http2Connection.PropertyKey handleKey = ctx.channel()
            .attr(Http2ClientPipelineInitializer.CHANNEL_POOL_HANDLE_ATTR_KEY).get();
    connection().stream(streamId).setProperty(handleKey, handle);
}

From source file:com.relayrides.pushy.apns.ApnsClientHandler.java

License:Open Source License

@Override
public void write(final ChannelHandlerContext context, final Object message, final ChannelPromise writePromise)
        throws Http2Exception {
    if (message instanceof PushNotificationAndResponsePromise) {
        final PushNotificationAndResponsePromise pushNotificationAndResponsePromise = (PushNotificationAndResponsePromise) message;

        final ApnsPushNotification pushNotification = pushNotificationAndResponsePromise.getPushNotification();

        if (this.responsePromises.containsKey(pushNotification)) {
            writePromise.tryFailure(new PushNotificationStillPendingException());
        } else {/*from   w w  w .j a va2s  .c om*/
            this.responsePromises.put(pushNotification,
                    pushNotificationAndResponsePromise.getResponsePromise());

            pushNotificationAndResponsePromise.getResponsePromise().addListener(
                    new GenericFutureListener<Future<PushNotificationResponse<ApnsPushNotification>>>() {

                        @Override
                        public void operationComplete(
                                final Future<PushNotificationResponse<ApnsPushNotification>> future) {
                            // Regardless of the outcome, when the response promise is finished, we want to remove it from
                            // the map of pending promises.
                            ApnsClientHandler.this.responsePromises.remove(pushNotification);
                        }
                    });

            this.write(context, pushNotification, writePromise);
        }
    } else if (message instanceof ApnsPushNotification) {
        final ApnsPushNotification pushNotification = (ApnsPushNotification) message;

        try {
            final int streamId = (int) this.nextStreamId;

            final Http2Headers headers = new DefaultHttp2Headers().method(HttpMethod.POST.asciiName())
                    .authority(this.authority).path(APNS_PATH_PREFIX + pushNotification.getToken())
                    .addInt(APNS_EXPIRATION_HEADER, pushNotification.getExpiration() == null ? 0
                            : (int) (pushNotification.getExpiration().getTime() / 1000));

            final String authenticationToken = this.apnsClient
                    .getAuthenticationTokenSupplierForTopic(pushNotification.getTopic()).getToken();
            headers.add(APNS_AUTHORIZATION_HEADER, "bearer " + authenticationToken);

            if (pushNotification.getCollapseId() != null) {
                headers.add(APNS_COLLAPSE_ID_HEADER, pushNotification.getCollapseId());
            }

            if (pushNotification.getPriority() != null) {
                headers.addInt(APNS_PRIORITY_HEADER, pushNotification.getPriority().getCode());
            }

            if (pushNotification.getTopic() != null) {
                headers.add(APNS_TOPIC_HEADER, pushNotification.getTopic());
            }

            final ChannelPromise headersPromise = context.newPromise();
            this.encoder().writeHeaders(context, streamId, headers, 0, false, headersPromise);
            log.trace("Wrote headers on stream {}: {}", streamId, headers);

            final ByteBuf payloadBuffer = context.alloc().ioBuffer(INITIAL_PAYLOAD_BUFFER_CAPACITY);
            payloadBuffer.writeBytes(pushNotification.getPayload().getBytes(StandardCharsets.UTF_8));

            final ChannelPromise dataPromise = context.newPromise();
            this.encoder().writeData(context, streamId, payloadBuffer, 0, true, dataPromise);
            log.trace("Wrote payload on stream {}: {}", streamId, pushNotification.getPayload());

            final PromiseCombiner promiseCombiner = new PromiseCombiner();
            promiseCombiner.addAll(headersPromise, dataPromise);
            promiseCombiner.finish(writePromise);

            writePromise.addListener(new GenericFutureListener<ChannelPromise>() {

                @Override
                public void operationComplete(final ChannelPromise future) throws Exception {
                    if (future.isSuccess()) {
                        ApnsClientHandler.this.pushNotificationsByStreamId.put(streamId, pushNotification);
                        ApnsClientHandler.this.authenticationTokensByStreamId.put(streamId,
                                authenticationToken);
                    } else {
                        log.trace("Failed to write push notification on stream {}.", streamId, future.cause());

                        final Promise<PushNotificationResponse<ApnsPushNotification>> responsePromise = ApnsClientHandler.this.responsePromises
                                .get(pushNotification);

                        if (responsePromise != null) {
                            responsePromise.tryFailure(future.cause());
                        } else {
                            log.error("Notification write failed, but no response promise found.");
                        }
                    }
                }
            });

            this.nextStreamId += 2;

            if (this.nextStreamId >= STREAM_ID_RESET_THRESHOLD) {
                // This is very unlikely, but in the event that we run out of stream IDs (the maximum allowed is
                // 2^31, per https://httpwg.github.io/specs/rfc7540.html#StreamIdentifiers), we need to open a new
                // connection. Just closing the context should be enough; automatic reconnection should take things
                // from there.
                context.close();
            }
        } catch (NoKeyForTopicException | SignatureException e) {
            writePromise.tryFailure(e);
        }

    } else {
        // This should never happen, but in case some foreign debris winds up in the pipeline, just pass it through.
        log.error("Unexpected object in pipeline: {}", message);
        context.write(message, writePromise);
    }
}

From source file:com.turo.pushy.apns.AbstractClientServerTest.java

License:Open Source License

@AfterClass
public static void tearDownAfterClass() throws Exception {
    final PromiseCombiner combiner = new PromiseCombiner();
    combiner.addAll(CLIENT_EVENT_LOOP_GROUP.shutdownGracefully(), SERVER_EVENT_LOOP_GROUP.shutdownGracefully());

    final Promise<Void> shutdownPromise = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
    combiner.finish(shutdownPromise);
    shutdownPromise.await();/*from  w ww  .  j  a v a  2s .  c  om*/
}

From source file:com.turo.pushy.apns.AbstractMockApnsServerHandler.java

License:Open Source License

@Override
public void write(final ChannelHandlerContext context, final Object message, final ChannelPromise writePromise)
        throws Exception {
    if (message instanceof AcceptNotificationResponse) {
        final AcceptNotificationResponse acceptNotificationResponse = (AcceptNotificationResponse) message;
        this.encoder().writeHeaders(context, acceptNotificationResponse.getStreamId(), SUCCESS_HEADERS, 0, true,
                writePromise);//  w w w . ja  v a  2 s .c o  m

        log.trace("Accepted push notification on stream {}", acceptNotificationResponse.getStreamId());
    } else if (message instanceof RejectNotificationResponse) {
        final RejectNotificationResponse rejectNotificationResponse = (RejectNotificationResponse) message;

        final Http2Headers headers = new DefaultHttp2Headers();
        headers.status(rejectNotificationResponse.getErrorReason().getHttpResponseStatus().codeAsText());
        headers.add(HttpHeaderNames.CONTENT_TYPE, "application/json");

        if (rejectNotificationResponse.getApnsId() != null) {
            headers.add(APNS_ID_HEADER, rejectNotificationResponse.getApnsId().toString());
        }

        final byte[] payloadBytes;
        {
            final ErrorResponse errorResponse = new ErrorResponse(
                    rejectNotificationResponse.getErrorReason().getReasonText(),
                    rejectNotificationResponse.getTimestamp());

            payloadBytes = GSON.toJson(errorResponse).getBytes();
        }

        final ChannelPromise headersPromise = context.newPromise();
        this.encoder().writeHeaders(context, rejectNotificationResponse.getStreamId(), headers, 0, false,
                headersPromise);

        final ChannelPromise dataPromise = context.newPromise();
        this.encoder().writeData(context, rejectNotificationResponse.getStreamId(),
                Unpooled.wrappedBuffer(payloadBytes), 0, true, dataPromise);

        final PromiseCombiner promiseCombiner = new PromiseCombiner();
        promiseCombiner.addAll((ChannelFuture) headersPromise, dataPromise);
        promiseCombiner.finish(writePromise);

        log.trace("Rejected push notification on stream {}: {}", rejectNotificationResponse.getStreamId(),
                rejectNotificationResponse.getErrorReason());
    } else if (message instanceof InternalServerErrorResponse) {
        final InternalServerErrorResponse internalServerErrorResponse = (InternalServerErrorResponse) message;

        final Http2Headers headers = new DefaultHttp2Headers();
        headers.status(HttpResponseStatus.INTERNAL_SERVER_ERROR.codeAsText());

        this.encoder().writeHeaders(context, internalServerErrorResponse.getStreamId(), headers, 0, true,
                writePromise);

        log.trace("Encountered an internal error on stream {}", internalServerErrorResponse.getStreamId());
    } else {
        context.write(message, writePromise);
    }
}

From source file:com.turo.pushy.apns.ApnsClientHandler.java

License:Open Source License

private void writePushNotification(final ChannelHandlerContext context,
        final PushNotificationPromise responsePromise, final ChannelPromise writePromise) {
    if (context.channel().isActive()) {
        final int streamId = this.connection().local().incrementAndGetNextStreamId();

        if (streamId > 0) {
            // We'll attach the push notification and response promise to the stream as soon as the stream is created.
            // Because we're using a StreamBufferingEncoder under the hood, there's no guarantee as to when the stream
            // will actually be created, and so we attach these in the onStreamAdded listener to make sure everything
            // is happening in a predictable order.
            this.unattachedResponsePromisesByStreamId.put(streamId, responsePromise);
            final ApnsPushNotification pushNotification = responsePromise.getPushNotification();

            final Http2Headers headers = getHeadersForPushNotification(pushNotification, streamId);

            final ChannelPromise headersPromise = context.newPromise();
            this.encoder().writeHeaders(context, streamId, headers, 0, false, headersPromise);
            log.trace("Wrote headers on stream {}: {}", streamId, headers);

            final ByteBuf payloadBuffer = context.alloc().ioBuffer(INITIAL_PAYLOAD_BUFFER_CAPACITY);
            payloadBuffer.writeBytes(pushNotification.getPayload().getBytes(StandardCharsets.UTF_8));

            final ChannelPromise dataPromise = context.newPromise();
            this.encoder().writeData(context, streamId, payloadBuffer, 0, true, dataPromise);
            log.trace("Wrote payload on stream {}: {}", streamId, pushNotification.getPayload());

            final PromiseCombiner promiseCombiner = new PromiseCombiner();
            promiseCombiner.addAll((ChannelFuture) headersPromise, dataPromise);
            promiseCombiner.finish(writePromise);

            writePromise.addListener(new GenericFutureListener<ChannelPromise>() {

                @Override/*from w ww.j a v  a2  s.  c om*/
                public void operationComplete(final ChannelPromise future) {
                    if (!future.isSuccess()) {
                        log.trace("Failed to write push notification on stream {}.", streamId, future.cause());
                        responsePromise.tryFailure(future.cause());
                    }
                }
            });
        } else {
            // This is very unlikely, but in the event that we run out of stream IDs, we need to open a new
            // connection. Just closing the context should be enough; automatic reconnection should take things
            // from there.
            writePromise.tryFailure(STREAMS_EXHAUSTED_EXCEPTION);
            context.channel().close();
        }
    } else {
        writePromise.tryFailure(STREAM_CLOSED_BEFORE_REPLY_EXCEPTION);
    }
}

From source file:com.turo.pushy.apns.server.MockApnsServerHandler.java

License:Open Source License

@Override
public void write(final ChannelHandlerContext context, final Object message,
        final ChannelPromise writePromise) {
    if (message instanceof AcceptNotificationResponse) {
        final AcceptNotificationResponse acceptNotificationResponse = (AcceptNotificationResponse) message;

        final Http2Headers headers = new DefaultHttp2Headers().status(HttpResponseStatus.OK.codeAsText())
                .add(APNS_ID_HEADER, FastUUID.toString(acceptNotificationResponse.getApnsId()));

        this.encoder().writeHeaders(context, acceptNotificationResponse.getStreamId(), headers, 0, true,
                writePromise);/*from  www  . ja  v a2  s  .  co  m*/

        log.trace("Accepted push notification on stream {}", acceptNotificationResponse.getStreamId());
    } else if (message instanceof RejectNotificationResponse) {
        final RejectNotificationResponse rejectNotificationResponse = (RejectNotificationResponse) message;

        final Http2Headers headers = new DefaultHttp2Headers()
                .status(rejectNotificationResponse.getErrorReason().getHttpResponseStatus().codeAsText())
                .add(HttpHeaderNames.CONTENT_TYPE, "application/json")
                .add(APNS_ID_HEADER, FastUUID.toString(rejectNotificationResponse.getApnsId()));

        final byte[] payloadBytes;
        {
            final ErrorPayload errorPayload = new ErrorPayload(
                    rejectNotificationResponse.getErrorReason().getReasonText(),
                    rejectNotificationResponse.getTimestamp());

            payloadBytes = GSON.toJson(errorPayload).getBytes();
        }

        final ChannelPromise headersPromise = context.newPromise();
        this.encoder().writeHeaders(context, rejectNotificationResponse.getStreamId(), headers, 0, false,
                headersPromise);

        final ChannelPromise dataPromise = context.newPromise();
        this.encoder().writeData(context, rejectNotificationResponse.getStreamId(),
                Unpooled.wrappedBuffer(payloadBytes), 0, true, dataPromise);

        final PromiseCombiner promiseCombiner = new PromiseCombiner();
        promiseCombiner.addAll((ChannelFuture) headersPromise, dataPromise);
        promiseCombiner.finish(writePromise);

        log.trace("Rejected push notification on stream {}: {}", rejectNotificationResponse.getStreamId(),
                rejectNotificationResponse.getErrorReason());
    } else {
        context.write(message, writePromise);
    }
}

From source file:org.apache.hadoop.hbase.ipc.NettyRpcDuplexHandler.java

License:Apache License

private void writeRequest(ChannelHandlerContext ctx, Call call, ChannelPromise promise) throws IOException {
    id2Call.put(call.id, call);//  w w  w  .j  a  v  a 2  s .  c o  m
    ByteBuf cellBlock = cellBlockBuilder.buildCellBlock(codec, compressor, call.cells, ctx.alloc());
    CellBlockMeta cellBlockMeta;
    if (cellBlock != null) {
        CellBlockMeta.Builder cellBlockMetaBuilder = CellBlockMeta.newBuilder();
        cellBlockMetaBuilder.setLength(cellBlock.writerIndex());
        cellBlockMeta = cellBlockMetaBuilder.build();
    } else {
        cellBlockMeta = null;
    }
    RequestHeader requestHeader = IPCUtil.buildRequestHeader(call, cellBlockMeta);
    int sizeWithoutCellBlock = IPCUtil.getTotalSizeWhenWrittenDelimited(requestHeader, call.param);
    int totalSize = cellBlock != null ? sizeWithoutCellBlock + cellBlock.writerIndex() : sizeWithoutCellBlock;
    ByteBuf buf = ctx.alloc().buffer(sizeWithoutCellBlock + 4);
    buf.writeInt(totalSize);
    ByteBufOutputStream bbos = new ByteBufOutputStream(buf);
    requestHeader.writeDelimitedTo(bbos);
    if (call.param != null) {
        call.param.writeDelimitedTo(bbos);
    }
    if (cellBlock != null) {
        ChannelPromise withoutCellBlockPromise = ctx.newPromise();
        ctx.write(buf, withoutCellBlockPromise);
        ChannelPromise cellBlockPromise = ctx.newPromise();
        ctx.write(cellBlock, cellBlockPromise);
        PromiseCombiner combiner = new PromiseCombiner();
        combiner.addAll(withoutCellBlockPromise, cellBlockPromise);
        combiner.finish(promise);
    } else {
        ctx.write(buf, promise);
    }
}

From source file:org.apache.hadoop.hbase.security.CryptoAESWrapHandler.java

License:Apache License

@Override
public void flush(ChannelHandlerContext ctx) throws Exception {
    if (queue.isEmpty()) {
        return;//from w ww.  ja  v a  2s.c om
    }
    ByteBuf buf = null;
    try {
        ChannelPromise promise = ctx.newPromise();
        int readableBytes = queue.readableBytes();
        buf = queue.remove(readableBytes, promise);
        byte[] bytes = new byte[readableBytes];
        buf.readBytes(bytes);
        byte[] wrapperBytes = cryptoAES.wrap(bytes, 0, bytes.length);
        ChannelPromise lenPromise = ctx.newPromise();
        ctx.write(ctx.alloc().buffer(4).writeInt(wrapperBytes.length), lenPromise);
        ChannelPromise contentPromise = ctx.newPromise();
        ctx.write(Unpooled.wrappedBuffer(wrapperBytes), contentPromise);
        PromiseCombiner combiner = new PromiseCombiner();
        combiner.addAll(lenPromise, contentPromise);
        combiner.finish(promise);
        ctx.flush();
    } finally {
        if (buf != null) {
            ReferenceCountUtil.safeRelease(buf);
        }
    }
}

From source file:org.apache.hadoop.hbase.security.SaslWrapHandler.java

License:Apache License

@Override
public void flush(ChannelHandlerContext ctx) throws Exception {
    if (queue.isEmpty()) {
        return;/*from ww w.  j a v a2  s.c om*/
    }
    ByteBuf buf = null;
    try {
        ChannelPromise promise = ctx.newPromise();
        int readableBytes = queue.readableBytes();
        buf = queue.remove(readableBytes, promise);
        byte[] bytes = new byte[readableBytes];
        buf.readBytes(bytes);
        byte[] wrapperBytes = saslClient.wrap(bytes, 0, bytes.length);
        ChannelPromise lenPromise = ctx.newPromise();
        ctx.write(ctx.alloc().buffer(4).writeInt(wrapperBytes.length), lenPromise);
        ChannelPromise contentPromise = ctx.newPromise();
        ctx.write(Unpooled.wrappedBuffer(wrapperBytes), contentPromise);
        PromiseCombiner combiner = new PromiseCombiner();
        combiner.addAll(lenPromise, contentPromise);
        combiner.finish(promise);
        ctx.flush();
    } finally {
        if (buf != null) {
            ReferenceCountUtil.safeRelease(buf);
        }
    }
}