|
49 | 49 | import java.net.InetSocketAddress; |
50 | 50 | import java.net.SocketAddress; |
51 | 51 | import java.time.Duration; |
| 52 | +import java.util.concurrent.CountDownLatch; |
52 | 53 | import java.util.concurrent.ExecutionException; |
53 | 54 | import java.util.concurrent.TimeUnit; |
54 | 55 | import java.util.concurrent.TimeoutException; |
55 | 56 | import java.util.concurrent.atomic.AtomicBoolean; |
| 57 | +import java.util.concurrent.atomic.AtomicReference; |
56 | 58 | import java.util.function.Consumer; |
57 | 59 | import java.util.function.Function; |
58 | 60 | import javax.net.ssl.SSLHandshakeException; |
@@ -167,12 +169,11 @@ private NettyFrameHandler( |
167 | 169 | new ChannelInitializer<SocketChannel>() { |
168 | 170 | @Override |
169 | 171 | public void initChannel(SocketChannel ch) { |
170 | | - // ch.pipeline() |
171 | | - // .addFirst( |
172 | | - // HANDLER_FLUSH_CONSOLIDATION, |
173 | | - // new FlushConsolidationHandler( |
174 | | - // |
175 | | - // FlushConsolidationHandler.DEFAULT_EXPLICIT_FLUSH_AFTER_FLUSHES, true)); |
| 172 | + ch.pipeline() |
| 173 | + .addFirst( |
| 174 | + HANDLER_FLUSH_CONSOLIDATION, |
| 175 | + new FlushConsolidationHandler( |
| 176 | + FlushConsolidationHandler.DEFAULT_EXPLICIT_FLUSH_AFTER_FLUSHES, true)); |
176 | 177 | ch.pipeline() |
177 | 178 | .addLast( |
178 | 179 | HANDLER_FRAME_DECODER, |
@@ -271,7 +272,28 @@ public Frame readFrame() { |
271 | 272 |
|
272 | 273 | @Override |
273 | 274 | public void writeFrame(Frame frame) throws IOException { |
274 | | - // TODO check if the frame is not too big? |
| 275 | + if (this.handler.isWritable()) { |
| 276 | + this.doWriteFrame(frame); |
| 277 | + } else { |
| 278 | + if (this.channel.eventLoop().inEventLoop()) { |
| 279 | + // we do not wait in the event loop |
| 280 | + this.doWriteFrame(frame); |
| 281 | + } else { |
| 282 | + try { |
| 283 | + boolean canWriteNow = this.handler.writableLatch().await(10, SECONDS); |
| 284 | + if (canWriteNow) { |
| 285 | + this.doWriteFrame(frame); |
| 286 | + } else { |
| 287 | + throw new IOException("Frame enqueuing failed"); |
| 288 | + } |
| 289 | + } catch (InterruptedException e) { |
| 290 | + Thread.currentThread().interrupt(); |
| 291 | + } |
| 292 | + } |
| 293 | + } |
| 294 | + } |
| 295 | + |
| 296 | + private void doWriteFrame(Frame frame) throws IOException { |
275 | 297 | ByteBuf bb = this.channel.alloc().buffer(frame.size()); |
276 | 298 | frame.writeToByteBuf(bb); |
277 | 299 | this.channel.write(bb); |
@@ -332,6 +354,9 @@ private static class AmqpHandler extends ChannelInboundHandlerAdapter { |
332 | 354 | private final int maxPayloadSize; |
333 | 355 | private final Runnable closeSequence; |
334 | 356 | private volatile AMQConnection connection; |
| 357 | + private final AtomicBoolean writable = new AtomicBoolean(true); |
| 358 | + private final AtomicReference<CountDownLatch> writableLatch = |
| 359 | + new AtomicReference<>(new CountDownLatch(1)); |
335 | 360 |
|
336 | 361 | private AmqpHandler(int maxPayloadSize, Runnable closeSequence) { |
337 | 362 | this.maxPayloadSize = maxPayloadSize; |
@@ -381,6 +406,13 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception |
381 | 406 |
|
382 | 407 | @Override |
383 | 408 | public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { |
| 409 | + boolean canWrite = ctx.channel().isWritable(); |
| 410 | + if (this.writable.compareAndSet(!canWrite, canWrite)) { |
| 411 | + if (canWrite) { |
| 412 | + CountDownLatch latch = writableLatch.getAndSet(new CountDownLatch(1)); |
| 413 | + latch.countDown(); |
| 414 | + } |
| 415 | + } |
384 | 416 | super.channelWritabilityChanged(ctx); |
385 | 417 | } |
386 | 418 |
|
@@ -441,5 +473,13 @@ private boolean needToDispatchIoError() { |
441 | 473 | AMQConnection c = this.connection; |
442 | 474 | return c != null && c.isOpen(); |
443 | 475 | } |
| 476 | + |
| 477 | + private boolean isWritable() { |
| 478 | + return this.writable.get(); |
| 479 | + } |
| 480 | + |
| 481 | + private CountDownLatch writableLatch() { |
| 482 | + return this.writableLatch.get(); |
| 483 | + } |
444 | 484 | } |
445 | 485 | } |
0 commit comments