@Before
  public void setUp() throws Exception {
    super.setUp();

    server = createServer(true, true);

    AddressSettings settings = new AddressSettings();
    settings.setRedeliveryDelay(100);
    server.getConfiguration().getAddressesSettings().put("#", settings);

    server.start();

    locator = createNettyNonHALocator();

    factory = createSessionFactory(locator);

    ClientSession session = factory.createTransactedSession();

    session.createQueue(inQueue, inQueue, true);

    session.createQueue(outQueue, outQueue, true);

    session.close();
  }
  @Test
  public void testSendReceiveLargeMessages() throws Exception {
    SimpleString QUEUE = new SimpleString("jms.queue.somequeue");

    ActiveMQConnectionFactory jbcf =
        ActiveMQJMSClient.createConnectionFactoryWithHA(JMSFactoryType.CF, livetc, backuptc);
    jbcf.setReconnectAttempts(-1);
    jbcf.setBlockOnDurableSend(true);
    jbcf.setBlockOnNonDurableSend(true);
    jbcf.setMinLargeMessageSize(1024);
    // jbcf.setConsumerWindowSize(0);
    // jbcf.setMinLargeMessageSize(1024);

    final CountDownLatch flagAlign = new CountDownLatch(1);

    final CountDownLatch waitToKill = new CountDownLatch(1);

    final AtomicBoolean killed = new AtomicBoolean(false);

    jbcf.getServerLocator()
        .addIncomingInterceptor(
            new Interceptor() {
              int count = 0;

              @Override
              public boolean intercept(Packet packet, RemotingConnection connection)
                  throws ActiveMQException {

                if (packet instanceof SessionReceiveContinuationMessage) {
                  if (count++ == 300 && !killed.get()) {
                    System.out.println("sending countDown on latch waitToKill");
                    killed.set(true);
                    waitToKill.countDown();
                  }
                }
                return true;
              }
            });

    Connection conn = JMSUtil.createConnectionAndWaitForTopology(jbcf, 2, 5);
    Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
    final ClientSession coreSession = ((ActiveMQSession) sess).getCoreSession();

    // The thread that will fail the server
    Thread spoilerThread =
        new Thread() {
          public void run() {
            flagAlign.countDown();
            // a large timeout just to help in case of debugging
            try {
              waitToKill.await(120, TimeUnit.SECONDS);
            } catch (Exception e) {
              e.printStackTrace();
            }

            try {
              System.out.println("Killing server...");

              JMSUtil.crash(liveService, coreSession);
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        };

    coreSession.createQueue(QUEUE, QUEUE, true);

    Queue queue = sess.createQueue("somequeue");

    MessageProducer producer = sess.createProducer(queue);
    producer.setDeliveryMode(DeliveryMode.PERSISTENT);

    for (int i = 0; i < 100; i++) {
      TextMessage message = sess.createTextMessage(new String(new byte[10 * 1024]));
      producer.send(message);

      if (i % 10 == 0) {
        sess.commit();
      }
    }

    sess.commit();

    conn.start();

    spoilerThread.start();

    assertTrue(flagAlign.await(10, TimeUnit.SECONDS));

    MessageConsumer consumer = sess.createConsumer(queue);

    // We won't receive the whole thing here.. we just want to validate if message will arrive or
    // not...
    // this test is not meant to validate transactionality during Failover as that would require XA
    // and recovery
    for (int i = 0; i < 90; i++) {
      TextMessage message = null;

      int retryNrs = 0;
      do {
        retryNrs++;
        try {
          message = (TextMessage) consumer.receive(5000);
          assertNotNull(message);
          break;
        } catch (JMSException e) {
          new Exception("Exception on receive message", e).printStackTrace();
        }
      } while (retryNrs < 10);

      assertNotNull(message);

      try {
        sess.commit();
      } catch (Exception e) {
        new Exception("Exception during commit", e);
        sess.rollback();
      }
    }

    conn.close();

    spoilerThread.join();
  }
  @Test
  public void testManualFailover() throws Exception {
    ActiveMQConnectionFactory jbcfLive =
        ActiveMQJMSClient.createConnectionFactoryWithoutHA(
            JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));

    jbcfLive.setBlockOnNonDurableSend(true);
    jbcfLive.setBlockOnDurableSend(true);

    ActiveMQConnectionFactory jbcfBackup =
        ActiveMQJMSClient.createConnectionFactoryWithoutHA(
            JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY, backupParams));
    jbcfBackup.setBlockOnNonDurableSend(true);
    jbcfBackup.setBlockOnDurableSend(true);
    jbcfBackup.setInitialConnectAttempts(-1);
    jbcfBackup.setReconnectAttempts(-1);

    Connection connLive = jbcfLive.createConnection();

    MyExceptionListener listener = new MyExceptionListener();

    connLive.setExceptionListener(listener);

    Session sessLive = connLive.createSession(false, Session.AUTO_ACKNOWLEDGE);

    ClientSession coreSessionLive = ((ActiveMQSession) sessLive).getCoreSession();

    RemotingConnection coreConnLive = ((ClientSessionInternal) coreSessionLive).getConnection();

    SimpleString jmsQueueName =
        new SimpleString(ActiveMQDestination.JMS_QUEUE_ADDRESS_PREFIX + "myqueue");

    coreSessionLive.createQueue(jmsQueueName, jmsQueueName, null, true);

    Queue queue = sessLive.createQueue("myqueue");

    final int numMessages = 1000;

    MessageProducer producerLive = sessLive.createProducer(queue);

    for (int i = 0; i < numMessages; i++) {
      TextMessage tm = sessLive.createTextMessage("message" + i);

      producerLive.send(tm);
    }

    // Note we block on P send to make sure all messages get to server before failover

    JMSUtil.crash(liveService, coreSessionLive);

    connLive.close();

    // Now recreate on backup

    Connection connBackup = jbcfBackup.createConnection();

    Session sessBackup = connBackup.createSession(false, Session.AUTO_ACKNOWLEDGE);

    MessageConsumer consumerBackup = sessBackup.createConsumer(queue);

    connBackup.start();

    for (int i = 0; i < numMessages; i++) {
      TextMessage tm = (TextMessage) consumerBackup.receive(1000);

      Assert.assertNotNull(tm);

      Assert.assertEquals("message" + i, tm.getText());
    }

    TextMessage tm = (TextMessage) consumerBackup.receiveNoWait();

    Assert.assertNull(tm);

    connBackup.close();
  }
  @Test
  public void testAutomaticFailover() throws Exception {
    ActiveMQConnectionFactory jbcf =
        ActiveMQJMSClient.createConnectionFactoryWithHA(JMSFactoryType.CF, livetc);
    jbcf.setReconnectAttempts(-1);
    jbcf.setBlockOnDurableSend(true);
    jbcf.setBlockOnNonDurableSend(true);

    // Note we set consumer window size to a value so we can verify that consumer credit re-sending
    // works properly on failover
    // The value is small enough that credits will have to be resent several time

    final int numMessages = 10;

    final int bodySize = 1000;

    jbcf.setConsumerWindowSize(numMessages * bodySize / 10);

    Connection conn = JMSUtil.createConnectionAndWaitForTopology(jbcf, 2, 5);

    MyExceptionListener listener = new MyExceptionListener();

    conn.setExceptionListener(listener);

    Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

    ClientSession coreSession = ((ActiveMQSession) sess).getCoreSession();

    SimpleString jmsQueueName =
        new SimpleString(ActiveMQDestination.JMS_QUEUE_ADDRESS_PREFIX + "myqueue");

    coreSession.createQueue(jmsQueueName, jmsQueueName, null, true);

    Queue queue = sess.createQueue("myqueue");

    MessageProducer producer = sess.createProducer(queue);

    producer.setDeliveryMode(DeliveryMode.PERSISTENT);

    MessageConsumer consumer = sess.createConsumer(queue);

    byte[] body = RandomUtil.randomBytes(bodySize);

    for (int i = 0; i < numMessages; i++) {
      BytesMessage bm = sess.createBytesMessage();

      bm.writeBytes(body);

      producer.send(bm);
    }

    conn.start();

    JMSFailoverTest.log.info("sent messages and started connection");

    Thread.sleep(2000);

    JMSUtil.crash(liveService, ((ActiveMQSession) sess).getCoreSession());

    for (int i = 0; i < numMessages; i++) {
      JMSFailoverTest.log.info("got message " + i);

      BytesMessage bm = (BytesMessage) consumer.receive(1000);

      Assert.assertNotNull(bm);

      Assert.assertEquals(body.length, bm.getBodyLength());
    }

    TextMessage tm = (TextMessage) consumer.receiveNoWait();

    Assert.assertNull(tm);

    conn.close();
  }
  protected void testChunks(
      final boolean isXA,
      final boolean restartOnXA,
      final boolean rollbackFirstSend,
      final boolean useStreamOnConsume,
      final boolean realFiles,
      final boolean preAck,
      final boolean sendingBlocking,
      final boolean testBrowser,
      final boolean useMessageConsumer,
      final int numberOfMessages,
      final long numberOfBytes,
      final int waitOnConsumer,
      final long delayDelivery,
      final int producerWindow,
      final int minSize)
      throws Exception {
    clearDataRecreateServerDirs();

    server = createServer(realFiles);
    server.start();

    ServerLocator locator = createInVMNonHALocator();
    try {

      if (sendingBlocking) {
        locator.setBlockOnNonDurableSend(true);
        locator.setBlockOnDurableSend(true);
        locator.setBlockOnAcknowledge(true);
      }

      if (producerWindow > 0) {
        locator.setConfirmationWindowSize(producerWindow);
      }

      locator.setMinLargeMessageSize(minSize);

      ClientSessionFactory sf = locator.createSessionFactory();

      ClientSession session;

      Xid xid = null;
      session = sf.createSession(null, null, isXA, false, false, preAck, 0);

      if (isXA) {
        xid = newXID();
        session.start(xid, XAResource.TMNOFLAGS);
      }

      session.createQueue(ADDRESS, ADDRESS, null, true);

      ClientProducer producer = session.createProducer(ADDRESS);

      if (rollbackFirstSend) {
        sendMessages(numberOfMessages, numberOfBytes, delayDelivery, session, producer);

        if (isXA) {
          session.end(xid, XAResource.TMSUCCESS);
          session.prepare(xid);

          session.close();

          if (realFiles && restartOnXA) {
            server.stop();
            server.start();
            sf = locator.createSessionFactory();
          }

          session = sf.createSession(null, null, isXA, false, false, preAck, 0);

          Xid[] xids = session.recover(XAResource.TMSTARTRSCAN);
          Assert.assertEquals(1, xids.length);
          Assert.assertEquals(xid, xids[0]);

          session.rollback(xid);
          producer = session.createProducer(ADDRESS);
          xid = newXID();
          session.start(xid, XAResource.TMNOFLAGS);
        } else {
          session.rollback();
        }

        validateNoFilesOnLargeDir();
      }

      sendMessages(numberOfMessages, numberOfBytes, delayDelivery, session, producer);

      if (isXA) {
        session.end(xid, XAResource.TMSUCCESS);
        session.prepare(xid);

        session.close();

        if (realFiles && restartOnXA) {
          server.stop();
          server.start();
          // we need to recreate sf's
          sf = locator.createSessionFactory();
        }

        session = sf.createSession(null, null, isXA, false, false, preAck, 0);

        Xid[] xids = session.recover(XAResource.TMSTARTRSCAN);
        Assert.assertEquals(1, xids.length);
        Assert.assertEquals(xid, xids[0]);

        producer = session.createProducer(ADDRESS);

        session.commit(xid, false);
        xid = newXID();
        session.start(xid, XAResource.TMNOFLAGS);
      } else {
        session.commit();
      }

      session.close();

      if (realFiles) {
        server.stop();

        server = createServer(realFiles);
        server.start();

        sf = locator.createSessionFactory();
      }

      session = sf.createSession(null, null, isXA, false, false, preAck, 0);

      if (isXA) {
        xid = newXID();
        session.start(xid, XAResource.TMNOFLAGS);
      }

      ClientConsumer consumer = null;

      for (int iteration = testBrowser ? 0 : 1; iteration < 2; iteration++) {
        session.stop();

        // first time with a browser
        consumer = session.createConsumer(ADDRESS, null, iteration == 0);

        if (useMessageConsumer) {
          final CountDownLatch latchDone = new CountDownLatch(numberOfMessages);
          final AtomicInteger errors = new AtomicInteger(0);

          MessageHandler handler =
              new MessageHandler() {
                int msgCounter;

                public void onMessage(final ClientMessage message) {
                  try {
                    if (delayDelivery > 0) {
                      long originalTime =
                          (Long) message.getObjectProperty(new SimpleString("original-time"));
                      Assert.assertTrue(
                          System.currentTimeMillis() - originalTime + "<" + delayDelivery,
                          System.currentTimeMillis() - originalTime >= delayDelivery);
                    }

                    if (!preAck) {
                      message.acknowledge();
                    }

                    Assert.assertNotNull(message);

                    if (delayDelivery <= 0) {
                      // right now there is no guarantee of ordered delivered on multiple
                      // scheduledMessages with
                      // the same
                      // scheduled delivery time
                      Assert.assertEquals(
                          msgCounter,
                          ((Integer) message.getObjectProperty(new SimpleString("counter-message")))
                              .intValue());
                    }

                    if (useStreamOnConsume) {
                      final AtomicLong bytesRead = new AtomicLong(0);
                      message.saveToOutputStream(
                          new OutputStream() {

                            @Override
                            public void write(final byte[] b) throws IOException {
                              if (b[0] == UnitTestCase.getSamplebyte(bytesRead.get())) {
                                bytesRead.addAndGet(b.length);
                                LargeMessageTestBase.log.debug(
                                    "Read position " + bytesRead.get() + " on consumer");
                              } else {
                                LargeMessageTestBase.log.warn(
                                    "Received invalid packet at position " + bytesRead.get());
                              }
                            }

                            @Override
                            public void write(final int b) throws IOException {
                              if (b == UnitTestCase.getSamplebyte(bytesRead.get())) {
                                bytesRead.incrementAndGet();
                              } else {
                                LargeMessageTestBase.log.warn("byte not as expected!");
                              }
                            }
                          });

                      Assert.assertEquals(numberOfBytes, bytesRead.get());
                    } else {

                      ActiveMQBuffer buffer = message.getBodyBuffer();
                      buffer.resetReaderIndex();
                      for (long b = 0; b < numberOfBytes; b++) {
                        if (b % (1024L * 1024L) == 0) {
                          LargeMessageTestBase.log.debug("Read " + b + " bytes");
                        }

                        Assert.assertEquals(UnitTestCase.getSamplebyte(b), buffer.readByte());
                      }

                      try {
                        buffer.readByte();
                        Assert.fail("Supposed to throw an exception");
                      } catch (Exception e) {
                      }
                    }
                  } catch (Throwable e) {
                    e.printStackTrace();
                    LargeMessageTestBase.log.warn("Got an error", e);
                    errors.incrementAndGet();
                  } finally {
                    latchDone.countDown();
                    msgCounter++;
                  }
                }
              };

          session.start();

          consumer.setMessageHandler(handler);

          Assert.assertTrue(latchDone.await(waitOnConsumer, TimeUnit.SECONDS));
          Assert.assertEquals(0, errors.get());
        } else {

          session.start();

          for (int i = 0; i < numberOfMessages; i++) {
            System.currentTimeMillis();

            ClientMessage message = consumer.receive(waitOnConsumer + delayDelivery);

            Assert.assertNotNull(message);

            System.currentTimeMillis();

            if (delayDelivery > 0) {
              long originalTime =
                  (Long) message.getObjectProperty(new SimpleString("original-time"));
              Assert.assertTrue(
                  System.currentTimeMillis() - originalTime + "<" + delayDelivery,
                  System.currentTimeMillis() - originalTime >= delayDelivery);
            }

            if (!preAck) {
              message.acknowledge();
            }

            Assert.assertNotNull(message);

            if (delayDelivery <= 0) {
              // right now there is no guarantee of ordered delivered on multiple scheduledMessages
              // with the same
              // scheduled delivery time
              Assert.assertEquals(
                  i,
                  ((Integer) message.getObjectProperty(new SimpleString("counter-message")))
                      .intValue());
            }

            if (useStreamOnConsume) {
              final AtomicLong bytesRead = new AtomicLong(0);
              message.saveToOutputStream(
                  new OutputStream() {

                    @Override
                    public void write(final byte[] b) throws IOException {
                      if (b[0] == UnitTestCase.getSamplebyte(bytesRead.get())) {
                        bytesRead.addAndGet(b.length);
                      } else {
                        LargeMessageTestBase.log.warn(
                            "Received invalid packet at position " + bytesRead.get());
                      }
                    }

                    @Override
                    public void write(final int b) throws IOException {
                      if (bytesRead.get() % (1024L * 1024L) == 0) {
                        LargeMessageTestBase.log.debug("Read " + bytesRead.get() + " bytes");
                      }
                      if (b == (byte) 'a') {
                        bytesRead.incrementAndGet();
                      } else {
                        LargeMessageTestBase.log.warn("byte not as expected!");
                      }
                    }
                  });

              Assert.assertEquals(numberOfBytes, bytesRead.get());
            } else {
              ActiveMQBuffer buffer = message.getBodyBuffer();
              buffer.resetReaderIndex();

              for (long b = 0; b < numberOfBytes; b++) {
                if (b % (1024L * 1024L) == 0L) {
                  LargeMessageTestBase.log.debug("Read " + b + " bytes");
                }
                Assert.assertEquals(UnitTestCase.getSamplebyte(b), buffer.readByte());
              }
            }
          }
        }
        consumer.close();

        if (iteration == 0) {
          if (isXA) {
            session.end(xid, XAResource.TMSUCCESS);
            session.rollback(xid);
            xid = newXID();
            session.start(xid, XAResource.TMNOFLAGS);
          } else {
            session.rollback();
          }
        } else {
          if (isXA) {
            session.end(xid, XAResource.TMSUCCESS);
            session.commit(xid, true);
            xid = newXID();
            session.start(xid, XAResource.TMNOFLAGS);
          } else {
            session.commit();
          }
        }
      }

      session.close();

      Assert.assertEquals(
          0,
          ((Queue) server.getPostOffice().getBinding(ADDRESS).getBindable()).getDeliveringCount());
      Assert.assertEquals(
          0, getMessageCount((Queue) server.getPostOffice().getBinding(ADDRESS).getBindable()));

      validateNoFilesOnLargeDir();

    } finally {
      locator.close();
      try {
        server.stop();
      } catch (Throwable ignored) {
      }
    }
  }