示例#1
0
  @Test
  public void commandRetriedChannelClosesWhileFlush() throws Exception {

    assumeTrue(Version.identify().get("netty-transport").artifactVersion().startsWith("4.0.2"));

    RedisCommands<String, String> connection = client.connect().sync();
    RedisCommands<String, String> verificationConnection = client.connect().sync();
    RedisChannelWriter<String, String> channelWriter =
        getRedisChannelHandler(connection).getChannelWriter();

    connection.set(key, "1");
    assertThat(verificationConnection.get(key)).isEqualTo("1");

    final CountDownLatch block = new CountDownLatch(1);

    ConnectionWatchdog connectionWatchdog =
        Connections.getConnectionWatchdog(connection.getStatefulConnection());

    AsyncCommand<String, String, Object> command = getBlockOnEncodeCommand(block);

    channelWriter.write(command);

    connectionWatchdog.setReconnectSuspended(true);

    Channel channel = getChannel(getRedisChannelHandler(connection));
    channel.unsafe().disconnect(channel.newPromise());

    assertThat(channel.isOpen()).isFalse();
    assertThat(command.isCancelled()).isFalse();
    assertThat(command.isDone()).isFalse();
    block.countDown();
    assertThat(command.await(2, TimeUnit.SECONDS)).isFalse();

    connectionWatchdog.setReconnectSuspended(false);
    connectionWatchdog.scheduleReconnect();

    assertThat(command.await(2, TimeUnit.SECONDS)).isTrue();
    assertThat(command.isCancelled()).isFalse();
    assertThat(command.isDone()).isTrue();

    assertThat(verificationConnection.get(key)).isEqualTo("2");

    assertThat(getQueue(getRedisChannelHandler(connection))).isEmpty();
    assertThat(getCommandBuffer(getRedisChannelHandler(connection))).isEmpty();

    connection.close();
    verificationConnection.close();
  }
示例#2
0
  @Test
  public void commandNotExecutedChannelClosesWhileFlush() throws Exception {

    RedisCommands<String, String> connection = client.connect().sync();
    RedisCommands<String, String> verificationConnection = client.connect().sync();
    RedisChannelWriter<String, String> channelWriter =
        getRedisChannelHandler(connection).getChannelWriter();

    connection.set(key, "1");
    assertThat(verificationConnection.get(key)).isEqualTo("1");

    final CountDownLatch block = new CountDownLatch(1);

    AsyncCommand<String, String, Object> command =
        new AsyncCommand<String, String, Object>(
            new Command<>(
                CommandType.INCR, new IntegerOutput(CODEC), new CommandArgs<>(CODEC).addKey(key))) {

          @Override
          public void encode(ByteBuf buf) {
            try {
              block.await();
            } catch (InterruptedException e) {
            }
            super.encode(buf);
          }
        };

    channelWriter.write(command);

    Channel channel = getChannel(getRedisChannelHandler(connection));
    channel.unsafe().disconnect(channel.newPromise());

    assertThat(channel.isOpen()).isFalse();
    assertThat(command.isCancelled()).isFalse();
    assertThat(command.isDone()).isFalse();
    block.countDown();
    assertThat(command.await(2, TimeUnit.SECONDS)).isTrue();
    assertThat(command.isCancelled()).isFalse();
    assertThat(command.isDone()).isTrue();

    assertThat(verificationConnection.get(key)).isEqualTo("1");

    assertThat(getQueue(getRedisChannelHandler(connection))).isEmpty();
    assertThat(getCommandBuffer(getRedisChannelHandler(connection))).isEmpty();

    connection.close();
  }
示例#3
0
  private ChannelFuture doBind(final SocketAddress localAddress) {
    final ChannelFuture regFuture = initAndRegister();
    final Channel channel = regFuture.channel();
    if (regFuture.cause() != null) {
      return regFuture;
    }

    if (regFuture.isDone()) {
      // At this point we know that the registration was complete and succesful.
      ChannelPromise promise = channel.newPromise();
      doBind0(regFuture, channel, localAddress, promise);
      return promise;
    } else {
      // Registration future is almost always fulfilled already, but just in case it's not.
      final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
      regFuture.addListener(
          new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
              Throwable cause = future.cause();
              if (cause != null) {
                // Registration on the EventLoop failed so fail the ChannelPromise directly to not
                // cause an
                // IllegalStateException once we try to access the EventLoop of the Channel.
                promise.setFailure(cause);
              } else {
                // Registration was successful, so set the correct executor to use.
                // See https://github.com/netty/netty/issues/2586
                promise.executor = channel.eventLoop();
              }
              doBind0(regFuture, channel, localAddress, promise);
            }
          });
      return promise;
    }
  }
示例#4
0
 @Override
 public ChannelFuture register(Channel channel) {
   super.register(channel).syncUninterruptibly();
   promise = channel.newPromise();
   return promise;
 }
  public void write(
      ActiveMQBuffer buffer,
      final boolean flush,
      final boolean batched,
      final ChannelFutureListener futureListener) {

    try {
      writeLock.acquire();

      try {
        if (batchBuffer == null && batchingEnabled && batched && !flush) {
          // Lazily create batch buffer

          batchBuffer = ActiveMQBuffers.dynamicBuffer(BATCHING_BUFFER_SIZE);
        }

        if (batchBuffer != null) {
          batchBuffer.writeBytes(buffer, 0, buffer.writerIndex());

          if (batchBuffer.writerIndex() >= BATCHING_BUFFER_SIZE || !batched || flush) {
            // If the batch buffer is full or it's flush param or not batched then flush the buffer

            buffer = batchBuffer;
          } else {
            return;
          }

          if (!batched || flush) {
            batchBuffer = null;
          } else {
            // Create a new buffer

            batchBuffer = ActiveMQBuffers.dynamicBuffer(BATCHING_BUFFER_SIZE);
          }
        }

        // depending on if we need to flush or not we can use a voidPromise or
        // use a normal promise
        final ByteBuf buf = buffer.byteBuf();
        final ChannelPromise promise;
        if (flush || futureListener != null) {
          promise = channel.newPromise();
        } else {
          promise = channel.voidPromise();
        }

        EventLoop eventLoop = channel.eventLoop();
        boolean inEventLoop = eventLoop.inEventLoop();
        if (!inEventLoop) {
          if (futureListener != null) {
            channel.writeAndFlush(buf, promise).addListener(futureListener);
          } else {
            channel.writeAndFlush(buf, promise);
          }
        } else {
          // create a task which will be picked up by the eventloop and trigger the write.
          // This is mainly needed as this method is triggered by different threads for the same
          // channel.
          // if we not do this we may produce out of order writes.
          final Runnable task =
              new Runnable() {
                @Override
                public void run() {
                  if (futureListener != null) {
                    channel.writeAndFlush(buf, promise).addListener(futureListener);
                  } else {
                    channel.writeAndFlush(buf, promise);
                  }
                }
              };
          // execute the task on the eventloop
          eventLoop.execute(task);
        }

        // only try to wait if not in the eventloop otherwise we will produce a deadlock
        if (flush && !inEventLoop) {
          while (true) {
            try {
              boolean ok = promise.await(10000);

              if (!ok) {
                ActiveMQClientLogger.LOGGER.timeoutFlushingPacket();
              }

              break;
            } catch (InterruptedException e) {
              throw new ActiveMQInterruptedException(e);
            }
          }
        }
      } finally {
        writeLock.release();
      }
    } catch (InterruptedException e) {
      throw new ActiveMQInterruptedException(e);
    }
  }