List of usage examples for io.netty.util.concurrent PromiseCombiner finish
public void finish(Promise<Void> aggregatePromise)
Sets the promise to be notified when all combined futures have finished.
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); } } }