@Test
 public void testBasicSend2times() throws Exception {
   SimpleString dla = new SimpleString("DLA");
   SimpleString qName = new SimpleString("q1");
   AddressSettings addressSettings =
       new AddressSettings().setMaxDeliveryAttempts(2).setDeadLetterAddress(dla);
   server.getAddressSettingsRepository().addMatch(qName.toString(), addressSettings);
   SimpleString dlq = new SimpleString("DLQ1");
   clientSession.createQueue(dla, dlq, null, false);
   clientSession.createQueue(qName, qName, null, false);
   ClientProducer producer = clientSession.createProducer(qName);
   producer.send(createTextMessage(clientSession, "heyho!"));
   clientSession.start();
   ClientConsumer clientConsumer = clientSession.createConsumer(qName);
   ClientMessage m = clientConsumer.receive(5000);
   m.acknowledge();
   Assert.assertNotNull(m);
   Assert.assertEquals(m.getBodyBuffer().readString(), "heyho!");
   // force a cancel
   clientSession.rollback();
   clientSession.start();
   m = clientConsumer.receive(5000);
   m.acknowledge();
   Assert.assertNotNull(m);
   Assert.assertEquals(m.getBodyBuffer().readString(), "heyho!");
   // force a cancel
   clientSession.rollback();
   m = clientConsumer.receiveImmediate();
   Assert.assertNull(m);
   clientConsumer.close();
   clientConsumer = clientSession.createConsumer(dlq);
   m = clientConsumer.receive(5000);
   Assert.assertNotNull(m);
   Assert.assertEquals(m.getBodyBuffer().readString(), "heyho!");
 }
  @Test
  public void testDeadLetterAddressWithOverridenSublevelAddressSettings() throws Exception {
    int defaultDeliveryAttempt = 3;
    int specificeDeliveryAttempt = defaultDeliveryAttempt + 1;

    SimpleString address = new SimpleString("prefix.address");
    SimpleString queue = RandomUtil.randomSimpleString();
    SimpleString defaultDeadLetterAddress = RandomUtil.randomSimpleString();
    SimpleString defaultDeadLetterQueue = RandomUtil.randomSimpleString();
    SimpleString specificDeadLetterAddress = RandomUtil.randomSimpleString();
    SimpleString specificDeadLetterQueue = RandomUtil.randomSimpleString();

    AddressSettings defaultAddressSettings =
        new AddressSettings()
            .setMaxDeliveryAttempts(defaultDeliveryAttempt)
            .setDeadLetterAddress(defaultDeadLetterAddress);
    server.getAddressSettingsRepository().addMatch("*", defaultAddressSettings);
    AddressSettings specificAddressSettings =
        new AddressSettings()
            .setMaxDeliveryAttempts(specificeDeliveryAttempt)
            .setDeadLetterAddress(specificDeadLetterAddress);
    server.getAddressSettingsRepository().addMatch(address.toString(), specificAddressSettings);

    clientSession.createQueue(address, queue, false);
    clientSession.createQueue(defaultDeadLetterAddress, defaultDeadLetterQueue, false);
    clientSession.createQueue(specificDeadLetterAddress, specificDeadLetterQueue, false);

    ClientProducer producer = clientSession.createProducer(address);
    ClientMessage clientMessage = createTextMessage(clientSession, "heyho!");
    producer.send(clientMessage);

    clientSession.start();
    ClientConsumer clientConsumer = clientSession.createConsumer(queue);
    ClientConsumer defaultDeadLetterConsumer = clientSession.createConsumer(defaultDeadLetterQueue);
    ClientConsumer specificDeadLetterConsumer =
        clientSession.createConsumer(specificDeadLetterQueue);

    for (int i = 0; i < defaultDeliveryAttempt; i++) {
      ClientMessage m = clientConsumer.receive(500);
      Assert.assertNotNull(m);
      Assert.assertEquals(i + 1, m.getDeliveryCount());
      m.acknowledge();
      clientSession.rollback();
    }

    Assert.assertNull(defaultDeadLetterConsumer.receiveImmediate());
    Assert.assertNull(specificDeadLetterConsumer.receiveImmediate());

    // one more redelivery attempt:
    ClientMessage m = clientConsumer.receive(500);
    Assert.assertNotNull(m);
    Assert.assertEquals(specificeDeliveryAttempt, m.getDeliveryCount());
    m.acknowledge();
    clientSession.rollback();

    Assert.assertNull(defaultDeadLetterConsumer.receiveImmediate());
    Assert.assertNotNull(specificDeadLetterConsumer.receive(500));
  }
  @Test
  public void testStopStartMultipleConsumers() throws Exception {
    locator.setConsumerWindowSize(getMessageEncodeSize(QUEUE) * 33);
    ClientSessionFactory sf = createSessionFactory(locator);

    final ClientSession session = sf.createSession(false, true, true);

    session.createQueue(QUEUE, QUEUE, null, false);

    ClientProducer producer = session.createProducer(QUEUE);

    final int numMessages = 100;

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message = createTextMessage(session, "m" + i);
      message.putIntProperty(new SimpleString("i"), i);
      producer.send(message);
    }

    ClientConsumer consumer = session.createConsumer(QUEUE);
    ClientConsumer consumer2 = session.createConsumer(QUEUE);
    ClientConsumer consumer3 = session.createConsumer(QUEUE);

    session.start();

    ClientMessage cm = consumer.receive(5000);
    Assert.assertNotNull(cm);
    cm.acknowledge();
    cm = consumer2.receive(5000);
    Assert.assertNotNull(cm);
    cm.acknowledge();
    cm = consumer3.receive(5000);
    Assert.assertNotNull(cm);
    cm.acknowledge();

    session.stop();
    cm = consumer.receiveImmediate();
    Assert.assertNull(cm);
    cm = consumer2.receiveImmediate();
    Assert.assertNull(cm);
    cm = consumer3.receiveImmediate();
    Assert.assertNull(cm);

    session.start();
    cm = consumer.receive(5000);
    Assert.assertNotNull(cm);
    cm = consumer2.receive(5000);
    Assert.assertNotNull(cm);
    cm = consumer3.receive(5000);
    Assert.assertNotNull(cm);
    session.close();
  }
  @Test
  public void testConsumerBrowserMessageAckDoesNothing() throws Exception {
    ClientSessionFactory sf = createSessionFactory(locator);

    ClientSession session = sf.createSession(false, true, true);

    session.createQueue(QUEUE, QUEUE, null, false);

    ClientProducer producer = session.createProducer(QUEUE);

    final int numMessages = 100;

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message = createTextMessage(session, "m" + i);
      producer.send(message);
    }

    ClientConsumer consumer = session.createConsumer(QUEUE, null, true);

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message2 = consumer.receive(1000);

      message2.acknowledge();

      Assert.assertEquals("m" + i, message2.getBodyBuffer().readString());
    }
    // assert that all the messages are there and none have been acked
    Assert.assertEquals(
        0, ((Queue) server.getPostOffice().getBinding(QUEUE).getBindable()).getDeliveringCount());
    Assert.assertEquals(
        100, getMessageCount(((Queue) server.getPostOffice().getBinding(QUEUE).getBindable())));

    session.close();
  }
  protected static ClientMessage[] consumeMessages(
      final int expected, final ClientConsumer consumer) throws Exception {
    ClientMessage[] messages = new ClientMessage[expected];

    ClientMessage m = null;
    for (int i = 0; i < expected; i++) {
      m = consumer.receive(500);
      if (m != null) {
        for (SimpleString key : m.getPropertyNames()) {
          System.out.println(key + "=" + m.getObjectProperty(key));
        }
      }
      Assert.assertNotNull("expected to received " + expected + " messages, got only " + i, m);
      messages[i] = m;
      m.acknowledge();
    }
    m = consumer.receiveImmediate();
    if (m != null) {
      for (SimpleString key : m.getPropertyNames()) {
        System.out.println(key + "=" + m.getObjectProperty(key));
      }
    }
    Assert.assertNull("received one more message than expected (" + expected + ")", m);

    return messages;
  }
  @Test
  public void testRestartJournal() throws Throwable {
    runExternalProcess(getTestDir(), 0, JournalCrashTest.FIRST_RUN);
    runExternalProcess(getTestDir(), JournalCrashTest.FIRST_RUN, JournalCrashTest.SECOND_RUN);
    runExternalProcess(getTestDir(), JournalCrashTest.SECOND_RUN, JournalCrashTest.THIRD_RUN);
    runExternalProcess(getTestDir(), JournalCrashTest.THIRD_RUN, JournalCrashTest.FOURTH_RUN);

    printJournal();

    startServer();

    try (ClientSession session = factory.createSession(true, true)) {

      ClientConsumer consumer = session.createConsumer(QUEUE);
      session.start();

      for (int i = 0; i < JournalCrashTest.FOURTH_RUN; i++) {
        ClientMessage msg = consumer.receive(5000);

        Assert.assertNotNull("Msg at " + i, msg);

        msg.acknowledge();

        Assert.assertEquals(i, msg.getObjectProperty(new SimpleString("key")));
      }
      session.close();
    }
  }
      @Override
      public void onMessage(final ClientMessage message) {

        try {
          if (!started) {
            failed = true;
          }

          messageReceived++;

          log.info("got message " + messageReceived);

          latch.countDown();

          if (latch.getCount() == 0) {
            message.acknowledge();

            started = false;

            consumer.setMessageHandler(null);
          }

        } catch (Exception e) {
        }
      }
      @Override
      public void onMessage(final ClientMessage message) {
        try {
          Thread.sleep(10);

          message.acknowledge();
        } catch (Exception e) {
        }
      }
  @Test
  public void testStopStartConsumerSyncReceive() throws Exception {
    ClientSessionFactory sf = createSessionFactory(locator);

    final ClientSession session = sf.createSession(false, true, true);

    session.createQueue(QUEUE, QUEUE, null, false);

    ClientProducer producer = session.createProducer(QUEUE);

    final int numMessages = 100;

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message = createTextMessage(session, "m" + i);
      message.putIntProperty(new SimpleString("i"), i);
      producer.send(message);
    }

    final ClientConsumer consumer = session.createConsumer(QUEUE);

    session.start();

    for (int i = 0; i < numMessages / 2; i++) {
      ClientMessage cm = consumer.receive(5000);
      Assert.assertNotNull(cm);
      cm.acknowledge();
    }
    session.stop();
    long time = System.currentTimeMillis();
    ClientMessage cm = consumer.receive(1000);
    long taken = System.currentTimeMillis() - time;
    Assert.assertTrue(taken >= 1000);
    Assert.assertNull(cm);

    session.start();
    for (int i = 0; i < numMessages / 2; i++) {
      cm = consumer.receive(5000);
      Assert.assertNotNull(cm);
      cm.acknowledge();
    }

    session.close();
  }
 public void onMessage(final ClientMessage message) {
   list.add(message);
   if (acknowledge) {
     try {
       message.acknowledge();
     } catch (ActiveMQException e) {
       // ignore
     }
   }
   latch.countDown();
 }
 /**
  * @param consumer
  * @throws Exception
  */
 private void readConsumer(String consumerName, ClientConsumer consumer) throws Exception {
   ClientMessage message = consumer.receive(5000);
   assertNotNull(message);
   System.out.println(
       "consumer = "
           + consumerName
           + " message, color="
           + message.getStringProperty("color")
           + ", msg = "
           + message.getStringProperty("value"));
   message.acknowledge();
 }
  @Test
  public void testPartialQueue() throws Exception {
    ClientSession session = basicSetUp();

    session.createQueue("myAddress", "myQueue1", true);
    session.createQueue("myAddress", "myQueue2", true);

    ClientProducer producer = session.createProducer("myAddress");

    ClientMessage msg = session.createMessage(true);
    producer.send(msg);

    ClientConsumer consumer = session.createConsumer("myQueue1");
    session.start();
    msg = consumer.receive(CONSUMER_TIMEOUT);
    assertNotNull(msg);
    msg.acknowledge();
    consumer.close();

    session.close();
    locator.close();
    server.stop();

    ByteArrayOutputStream xmlOutputStream = new ByteArrayOutputStream();
    XmlDataExporter xmlDataExporter = new XmlDataExporter();
    xmlDataExporter.process(
        xmlOutputStream,
        server.getConfiguration().getBindingsDirectory(),
        server.getConfiguration().getJournalDirectory(),
        server.getConfiguration().getPagingDirectory(),
        server.getConfiguration().getLargeMessagesDirectory());
    System.out.print(new String(xmlOutputStream.toByteArray()));

    clearDataRecreateServerDirs();
    server.start();
    locator = createInVMNonHALocator();
    factory = createSessionFactory(locator);
    session = factory.createSession(false, true, true);

    ByteArrayInputStream xmlInputStream = new ByteArrayInputStream(xmlOutputStream.toByteArray());
    XmlDataImporter xmlDataImporter = new XmlDataImporter();
    xmlDataImporter.process(xmlInputStream, session);
    consumer = session.createConsumer("myQueue1");
    session.start();
    msg = consumer.receive(CONSUMER_TIMEOUT);
    assertNull(msg);
    consumer.close();

    consumer = session.createConsumer("myQueue2");
    msg = consumer.receive(CONSUMER_TIMEOUT);
    assertNotNull(msg);
  }
  @Test
  public void testLoad() throws Throwable {
    ActiveMQServer server2 = createServer(true, false);

    server2.getConfiguration().setJournalFileSize(10 * 1024 * 1024);
    server2.getConfiguration().setJournalMinFiles(10);
    server2.getConfiguration().setJournalCompactMinFiles(3);
    server2.getConfiguration().setJournalCompactPercentage(50);

    for (int i = 0; i < 10; i++) {
      server2.start();

      ServerLocator locator =
          createInVMNonHALocator().setMinLargeMessageSize(1024 * 1024).setBlockOnDurableSend(false);

      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = sf.createSession(true, true);

      try {
        session.createQueue("slow-queue", "slow-queue");
      } catch (Exception ignored) {
      }

      session.start();
      ClientConsumer consumer = session.createConsumer("slow-queue");

      while (true) {
        System.out.println("Received message from previous");
        ClientMessage msg = consumer.receiveImmediate();
        if (msg == null) {
          break;
        }
        msg.acknowledge();
      }

      session.close();

      produceMessages(sf, 30000);

      server2.stop();
    }
  }
  @Test
  public void testLargeMessageFileLeak() throws Exception {
    OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();

    // only run this on *nix systems which will have the
    // com.sun.management.UnixOperatingSystemMXBean (needed to check open file count)
    Assume.assumeTrue(os instanceof UnixOperatingSystemMXBean);

    long fdBaseline = ((UnixOperatingSystemMXBean) os).getOpenFileDescriptorCount();
    final int SIZE = 2 * 1024;
    SimpleString dla = new SimpleString("DLA");
    SimpleString qName = new SimpleString("q1");
    SimpleString adName = new SimpleString("ad1");

    AddressSettings addressSettings =
        new AddressSettings().setMaxDeliveryAttempts(1).setDeadLetterAddress(dla);
    server.getAddressSettingsRepository().addMatch(adName.toString(), addressSettings);
    SimpleString dlq = new SimpleString("DLQ1");
    clientSession.createQueue(dla, dlq, null, false);
    clientSession.createQueue(adName, qName, null, false);
    for (int i = 0; i < 10; i++) {
      ClientProducer producer = clientSession.createProducer(adName);
      ClientMessage clientFile = clientSession.createMessage(true);
      clientFile.setBodyInputStream(ActiveMQTestBase.createFakeLargeStream(SIZE));
      producer.send(clientFile);
      clientSession.start();
      ClientConsumer clientConsumer = clientSession.createConsumer(qName);
      ClientMessage m = clientConsumer.receive(500);
      m.acknowledge();
      Assert.assertNotNull(m);

      // force a cancel
      clientSession.rollback();
      m = clientConsumer.receiveImmediate();
      Assert.assertNull(m);
      clientConsumer.close();
    }
    assertEquals(
        "File descriptors are leaking",
        0,
        ((UnixOperatingSystemMXBean) os).getOpenFileDescriptorCount() - fdBaseline);
  }
      @Override
      public void onMessage(final ClientMessage message) {

        try {
          if (!started) {
            failed = true;
          }
          messageReceived++;
          latch.countDown();

          if (stop && latch.getCount() == 0) {

            message.acknowledge();
            session.stop();
            started = false;
          }

        } catch (Exception e) {
        }
      }
      @Override
      public void onMessage(final ClientMessage message) {

        try {
          if (!started) {
            failed = true;
          }

          count++;

          if (count == 10) {
            message.acknowledge();
            session.stop();
            started = false;
          }

          latch.countDown();
        } catch (Exception e) {
        }
      }
  @Test
  public void testDeadlLetterAddressWithDefaultAddressSettings() throws Exception {
    int deliveryAttempt = 3;

    SimpleString address = RandomUtil.randomSimpleString();
    SimpleString queue = RandomUtil.randomSimpleString();
    SimpleString deadLetterAddress = RandomUtil.randomSimpleString();
    SimpleString deadLetterQueue = RandomUtil.randomSimpleString();
    AddressSettings addressSettings =
        new AddressSettings()
            .setMaxDeliveryAttempts(deliveryAttempt)
            .setDeadLetterAddress(deadLetterAddress);
    server.getAddressSettingsRepository().setDefault(addressSettings);

    clientSession.createQueue(address, queue, false);
    clientSession.createQueue(deadLetterAddress, deadLetterQueue, false);

    ClientProducer producer = clientSession.createProducer(address);
    ClientMessage clientMessage = createTextMessage(clientSession, "heyho!");
    producer.send(clientMessage);

    clientSession.start();
    ClientConsumer clientConsumer = clientSession.createConsumer(queue);
    for (int i = 0; i < deliveryAttempt; i++) {
      ClientMessage m = clientConsumer.receive(500);
      Assert.assertNotNull(m);
      DeadLetterAddressTest.log.info("i is " + i);
      DeadLetterAddressTest.log.info("delivery cout is " + m.getDeliveryCount());
      Assert.assertEquals(i + 1, m.getDeliveryCount());
      m.acknowledge();
      clientSession.rollback();
    }
    ClientMessage m = clientConsumer.receive(500);
    Assert.assertNull("not expecting a message", m);
    clientConsumer.close();

    clientConsumer = clientSession.createConsumer(deadLetterQueue);
    m = clientConsumer.receive(500);
    Assert.assertNotNull(m);
    Assert.assertEquals(m.getBodyBuffer().readString(), "heyho!");
  }
  private ClientSession sendAndConsume(final ClientSessionFactory sf, final boolean createQueue)
      throws Exception {
    ClientSession session = sf.createSession(false, true, true);

    if (createQueue) {
      session.createQueue(ADDRESS, ADDRESS, null, false);
    }

    ClientProducer producer = session.createProducer(ADDRESS);

    final int numMessages = 1000;

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message =
          session.createMessage(
              ActiveMQTextMessage.TYPE, false, 0, System.currentTimeMillis(), (byte) 1);
      message.putIntProperty(new SimpleString("count"), i);
      message.getBodyBuffer().writeString("aardvarks");
      producer.send(message);
    }

    ClientConsumer consumer = session.createConsumer(ADDRESS);

    session.start();

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message2 = consumer.receive();

      assertEquals("aardvarks", message2.getBodyBuffer().readString());

      assertEquals(i, message2.getObjectProperty(new SimpleString("count")));

      message2.acknowledge();
    }

    ClientMessage message3 = consumer.receiveImmediate();

    assertNull(message3);

    return session;
  }
  private ClientMessage receiveMessage() throws Exception {
    final ClientSessionFactory sf = createSessionFactory(locator);
    ClientSession session = sf.createSession(null, null, false, true, true, false, 0);

    session.start();
    ClientConsumer consumer = session.createConsumer(ADDRESS);

    ClientMessage message = consumer.receive(1000);

    session.commit();

    if (message != null) {
      message.acknowledge();
    }

    consumer.close();

    session.close();

    return message;
  }
    @Override
    public void run() {
      ClientSession session = null;
      latchReady.countDown();
      try {
        ActiveMQTestBase.waitForLatch(latchStart);
        session = sf.createSession(false, false);
        session.start();
        ClientConsumer cons = session.createConsumer(QUEUE);
        for (int i = 0; i < numberOfMessages; i++) {
          ClientMessage msg = cons.receive(60 * 1000);
          msg.acknowledge();
          if (i % commitInterval == 0) {
            session.commit();
          }
          if (i % 1000 == 0) {
            // System.out.println(Thread.currentThread().getName() + "::sent #" + i);
          }
        }

        System.out.println(
            "Thread "
                + Thread.currentThread().getName()
                + " received "
                + numberOfMessages
                + " messages");

        session.commit();
      } catch (Throwable e) {
        this.e = e;
      } finally {
        try {
          session.close();
        } catch (Throwable e) {
          this.e = e;
        }
      }
    }
    public void receiveMessages(String queueName, int num, boolean checkDup)
        throws ActiveMQException {
      ClientSession session = sessionFactory.createSession();
      session.start();
      ClientConsumer consumer = session.createConsumer("jms.queue." + queueName);
      for (int i = 0; i < num; i++) {
        ClientMessage m = consumer.receive(30000);
        assertNotNull("i=" + i, m);
        assertNotNull(m.getStringProperty("bridge-message"));
        m.acknowledge();
      }

      ClientMessage m = consumer.receive(500);
      if (checkDup) {
        assertNull(m);
      } else {
        // drain messages
        while (m != null) {
          m = consumer.receive(200);
        }
      }

      session.close();
    }
  @Test
  public void testDurableNonDurable() throws Exception {
    final String testAddress = "testAddress";

    final String queueName1 = "queue1";

    final String queueName2 = "queue2";

    CoreQueueConfiguration queue1 =
        new CoreQueueConfiguration().setAddress(testAddress).setName(queueName1).setDurable(false);

    CoreQueueConfiguration queue2 =
        new CoreQueueConfiguration().setAddress(testAddress).setName(queueName2);

    List<CoreQueueConfiguration> queueConfs = new ArrayList<CoreQueueConfiguration>();

    queueConfs.add(queue1);
    queueConfs.add(queue2);

    configuration.addQueueConfiguration(queue1).addQueueConfiguration(queue2);

    ActiveMQServer server = addServer(ActiveMQServers.newActiveMQServer(configuration));

    server.start();

    ServerLocator locator = createInVMNonHALocator();

    ClientSessionFactory sf = createSessionFactory(locator);

    ClientSession session = addClientSession(sf.createSession(false, true, true));

    ClientProducer producer = session.createProducer(new SimpleString(testAddress));

    final SimpleString propKey = new SimpleString("testkey");

    final int numMessages = 1;

    PredefinedQueueTest.log.info("sending messages");

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message = session.createMessage(true);

      message.putIntProperty(propKey, i);

      producer.send(message);
    }

    session.close();

    PredefinedQueueTest.log.info("stopping");

    sf.close();

    server.stop();

    server.start();

    sf = createSessionFactory(locator);

    session = addClientSession(sf.createSession(false, true, true));

    session.start();

    ClientConsumer consumer1 = session.createConsumer(queueName1);

    ClientConsumer consumer2 = session.createConsumer(queueName2);

    ClientMessage message = consumer1.receiveImmediate();

    Assert.assertNull(message);

    for (int i = 0; i < numMessages; i++) {
      message = consumer2.receive(200);
      Assert.assertNotNull(message);
      Assert.assertEquals(i, message.getObjectProperty(propKey));
      message.acknowledge();
    }

    Assert.assertNull(consumer1.receiveImmediate());
    Assert.assertNull(consumer2.receiveImmediate());
  }
  @Test
  public void testProduceAndConsume() throws Throwable {
    int numberOfConsumers = 5;
    // this test assumes numberOfConsumers == numberOfProducers
    int numberOfProducers = numberOfConsumers;
    int produceMessage = 10000;
    int commitIntervalProduce = 100;
    int consumeMessage = (int) (produceMessage * 0.9);
    int commitIntervalConsume = 100;

    ClientSession session = sf.createSession(false, false);
    session.createQueue("compact", "compact-queue", true);

    ClientProducer producer = session.createProducer("compact");

    for (int i = 0; i < 100; i++) {
      producer.send(session.createMessage(true));
    }

    session.commit();

    // Number of messages expected to be received after restart
    int numberOfMessagesExpected = (produceMessage - consumeMessage) * numberOfConsumers;

    CountDownLatch latchReady = new CountDownLatch(numberOfConsumers + numberOfProducers);

    CountDownLatch latchStart = new CountDownLatch(1);

    ArrayList<BaseThread> threads = new ArrayList<BaseThread>();

    ProducerThread[] prod = new ProducerThread[numberOfProducers];
    for (int i = 0; i < numberOfProducers; i++) {
      prod[i] =
          new ProducerThread(i, latchReady, latchStart, produceMessage, commitIntervalProduce);
      prod[i].start();
      threads.add(prod[i]);
    }

    ConsumerThread[] cons = new ConsumerThread[numberOfConsumers];

    for (int i = 0; i < numberOfConsumers; i++) {
      cons[i] =
          new ConsumerThread(i, latchReady, latchStart, consumeMessage, commitIntervalConsume);
      cons[i].start();
      threads.add(cons[i]);
    }

    ActiveMQTestBase.waitForLatch(latchReady);
    latchStart.countDown();

    for (BaseThread t : threads) {
      t.join();
      if (t.e != null) {
        throw t.e;
      }
    }

    server.stop();

    setupServer(JournalType.NIO);

    ClientSession sess = sf.createSession(true, true);

    ClientConsumer consumer = sess.createConsumer(QUEUE);

    sess.start();

    for (int i = 0; i < numberOfMessagesExpected; i++) {
      ClientMessage msg = consumer.receive(5000);
      Assert.assertNotNull(msg);

      if (i % 1000 == 0) {
        System.out.println("Received #" + i + "  on thread before end");
      }
      msg.acknowledge();
    }

    Assert.assertNull(consumer.receiveImmediate());

    sess.close();
  }
  /** In this method we apply the JMS acknowledgement and redelivery semantics as per JMS spec */
  @Override
  public void onMessage(final ClientMessage message) {
    ActiveMQMessage msg = ActiveMQMessage.createMessage(message, session.getCoreSession());

    if (individualACK) {
      msg.setIndividualAcknowledge();
    }

    try {
      msg.doBeforeReceive();
    } catch (Exception e) {
      ActiveMQJMSClientLogger.LOGGER.errorPreparingMessageForReceipt(
          msg.getCoreMessage().toString(), e);

      return;
    }

    if (transactedOrClientAck) {
      try {
        message.acknowledge();
      } catch (ActiveMQException e) {
        ((ClientSessionInternal) session.getCoreSession()).markRollbackOnly();
        ActiveMQJMSClientLogger.LOGGER.errorProcessingMessage(e);
      }
    }

    try {
      connection.getThreadAwareContext().setCurrentThread(false);
      listener.onMessage(msg);
    } catch (RuntimeException e) {
      // See JMS 1.1 spec, section 4.5.2

      ActiveMQJMSClientLogger.LOGGER.onMessageError(e);

      if (!transactedOrClientAck) {
        try {
          if (individualACK) {
            message.individualAcknowledge();
          }

          session.getCoreSession().rollback(true);

          session.setRecoverCalled(true);
        } catch (Exception e2) {
          ActiveMQJMSClientLogger.LOGGER.errorRecoveringSession(e2);
        }
      }
    } finally {
      connection.getThreadAwareContext().clearCurrentThread(false);
    }
    if (!session.isRecoverCalled() && !individualACK) {
      try {
        // We don't want to call this if the consumer was closed from inside onMessage
        if (!consumer.isClosed() && !transactedOrClientAck) {
          message.acknowledge();
        }
      } catch (ActiveMQException e) {
        ((ClientSessionInternal) session.getCoreSession()).markRollbackOnly();
        ActiveMQJMSClientLogger.LOGGER.errorProcessingMessage(e);
      }
    }

    session.setRecoverCalled(false);
  }
  @Test
  public void testLargeMessage() throws Exception {
    server = createServer(true);
    server.start();
    locator = createInVMNonHALocator();
    factory = createSessionFactory(locator);
    ClientSession session = factory.createSession(false, false);

    LargeServerMessageImpl fileMessage =
        new LargeServerMessageImpl((JournalStorageManager) server.getStorageManager());

    fileMessage.setMessageID(1005);
    fileMessage.setDurable(true);

    for (int i = 0; i < 2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE; i++) {
      fileMessage.addBytes(new byte[] {getSamplebyte(i)});
    }

    fileMessage.putLongProperty(
        Message.HDR_LARGE_BODY_SIZE, 2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);

    fileMessage.releaseResources();

    session.createQueue("A", "A", true);

    ClientProducer prod = session.createProducer("A");

    prod.send(fileMessage);

    fileMessage.deleteFile();

    session.commit();

    session.close();
    locator.close();
    server.stop();

    ByteArrayOutputStream xmlOutputStream = new ByteArrayOutputStream();
    XmlDataExporter xmlDataExporter = new XmlDataExporter();
    xmlDataExporter.process(
        xmlOutputStream,
        server.getConfiguration().getBindingsDirectory(),
        server.getConfiguration().getJournalDirectory(),
        server.getConfiguration().getPagingDirectory(),
        server.getConfiguration().getLargeMessagesDirectory());
    System.out.print(new String(xmlOutputStream.toByteArray()));

    clearDataRecreateServerDirs();
    server.start();
    locator = createInVMNonHALocator();
    factory = createSessionFactory(locator);
    session = factory.createSession(false, true, true);

    ByteArrayInputStream xmlInputStream = new ByteArrayInputStream(xmlOutputStream.toByteArray());
    XmlDataImporter xmlDataImporter = new XmlDataImporter();
    xmlDataImporter.process(xmlInputStream, session);
    session.close();
    session = factory.createSession(false, false);
    session.start();

    ClientConsumer cons = session.createConsumer("A");

    ClientMessage msg = cons.receive(CONSUMER_TIMEOUT);

    assertNotNull(msg);

    assertEquals(2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, msg.getBodySize());

    for (int i = 0; i < 2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE; i++) {
      assertEquals(getSamplebyte(i), msg.getBodyBuffer().readByte());
    }

    msg.acknowledge();
    session.commit();
  }
  private void doTestTransactional(final TestRunner runner) throws Throwable {
    // For duplication detection
    int executionId = 0;

    while (!runner.isFailed()) {
      ClientSession session = null;

      executionId++;

      log.info("#test doTestTransactional starting now. Execution " + executionId);

      try {

        boolean retry = false;

        final int numMessages = 1000;

        session = sf.createSession(false, false);

        listener = new CountDownSessionFailureListener(session);
        session.addFailureListener(listener);

        do {
          try {
            ClientProducer producer = session.createProducer(FailoverTestBase.ADDRESS);

            for (int i = 0; i < numMessages; i++) {
              ClientMessage message = session.createMessage(true);

              message.getBodyBuffer().writeString("message" + i);

              message.putIntProperty("counter", i);

              message.putStringProperty(
                  Message.HDR_DUPLICATE_DETECTION_ID,
                  new SimpleString("id:" + i + ",exec:" + executionId));

              addPayload(message);

              if (log.isDebugEnabled()) {
                log.debug("Sending message " + message);
              }

              producer.send(message);
            }

            log.debug("Sending commit");
            session.commit();

            retry = false;
          } catch (ActiveMQDuplicateIdException die) {
            logAndSystemOut("#test duplicate id rejected on sending");
            break;
          } catch (ActiveMQTransactionRolledBackException trbe) {
            log.info("#test transaction rollback retrying on sending");
            // OK
            retry = true;
          } catch (ActiveMQUnBlockedException ube) {
            log.info("#test transaction rollback retrying on sending");
            // OK
            retry = true;
          } catch (ActiveMQTransactionOutcomeUnknownException toue) {
            log.info("#test transaction rollback retrying on sending");
            // OK
            retry = true;
          } catch (ActiveMQException e) {
            log.info("#test Exception " + e, e);
            throw e;
          }
        } while (retry);

        logAndSystemOut("#test Finished sending, starting consumption now");

        boolean blocked = false;

        retry = false;

        ClientConsumer consumer = null;
        do {
          ArrayList<Integer> msgs = new ArrayList<>();
          try {
            if (consumer == null) {
              consumer = session.createConsumer(FailoverTestBase.ADDRESS);
              session.start();
            }

            for (int i = 0; i < numMessages; i++) {
              if (log.isDebugEnabled()) {
                log.debug("Consumer receiving message " + i);
              }
              ClientMessage message = consumer.receive(10000);
              if (message == null) {
                break;
              }

              if (log.isDebugEnabled()) {
                log.debug("Received message " + message);
              }

              int count = message.getIntProperty("counter");

              if (count != i) {
                log.warn("count was received out of order, " + count + "!=" + i);
              }

              msgs.add(count);

              message.acknowledge();
            }

            log.info("#test commit");
            try {
              session.commit();
            } catch (ActiveMQTransactionRolledBackException trbe) {
              // we know the tx has been rolled back so we just consume again
              retry = true;
              continue;
            } catch (ActiveMQException e) {
              // This could eventually happen
              // We will get rid of this when we implement 2 phase commit on failover
              log.warn("exception during commit, it will be ignored for now" + e.getMessage(), e);
            }

            try {
              if (blocked) {
                assertTrue(
                    "msgs.size is expected to be 0 or "
                        + numMessages
                        + " but it was "
                        + msgs.size(),
                    msgs.size() == 0 || msgs.size() == numMessages);
              } else {
                assertTrue(
                    "msgs.size is expected to be " + numMessages + " but it was " + msgs.size(),
                    msgs.size() == numMessages);
              }
            } catch (Throwable e) {
              log.info(threadDump("Thread dump, messagesReceived = " + msgs.size()));
              logAndSystemOut(e.getMessage() + " messages received");
              for (Integer msg : msgs) {
                logAndSystemOut(msg.toString());
              }
              throw e;
            }

            int i = 0;
            for (Integer msg : msgs) {
              assertEquals(i++, (int) msg);
            }

            retry = false;
            blocked = false;
          } catch (ActiveMQTransactionRolledBackException trbe) {
            logAndSystemOut("Transaction rolled back with " + msgs.size(), trbe);
            // TODO: https://jira.jboss.org/jira/browse/HORNETQ-369
            // ATM RolledBack exception is being called with the transaction is committed.
            // the test will fail if you remove this next line
            blocked = true;
            retry = true;
          } catch (ActiveMQTransactionOutcomeUnknownException tou) {
            logAndSystemOut("Transaction rolled back with " + msgs.size(), tou);
            // TODO: https://jira.jboss.org/jira/browse/HORNETQ-369
            // ATM RolledBack exception is being called with the transaction is committed.
            // the test will fail if you remove this next line
            blocked = true;
            retry = true;
          } catch (ActiveMQUnBlockedException ube) {
            logAndSystemOut("Unblocked with " + msgs.size(), ube);
            // TODO: https://jira.jboss.org/jira/browse/HORNETQ-369
            // This part of the test is never being called.
            blocked = true;
            retry = true;
          } catch (ActiveMQException e) {
            logAndSystemOut(e.getMessage(), e);
            throw e;
          }
        } while (retry);
      } finally {
        if (session != null) {
          session.close();
        }
      }

      listener = null;
    }
  }
  private void doTestNonTransactional(final TestRunner runner) throws Exception {
    while (!runner.isFailed()) {
      AsynchronousFailoverTest.log.info("looping");

      ClientSession session = sf.createSession(true, true, 0);

      listener = new CountDownSessionFailureListener(session);

      session.addFailureListener(listener);

      ClientProducer producer = session.createProducer(FailoverTestBase.ADDRESS);

      final int numMessages = 1000;

      for (int i = 0; i < numMessages; i++) {
        boolean retry = false;
        do {
          try {
            ClientMessage message = session.createMessage(true);

            message.getBodyBuffer().writeString("message" + i);

            message.putIntProperty("counter", i);

            addPayload(message);

            producer.send(message);

            retry = false;
          } catch (ActiveMQUnBlockedException ube) {
            AsynchronousFailoverTest.log.info("exception when sending message with counter " + i);

            ube.printStackTrace();

            retry = true;

          } catch (ActiveMQException e) {
            fail("Invalid Exception type:" + e.getType());
          }
        } while (retry);
      }

      // create the consumer with retry if failover occurs during createConsumer call
      ClientConsumer consumer = null;
      boolean retry = false;
      do {
        try {
          consumer = session.createConsumer(FailoverTestBase.ADDRESS);

          retry = false;
        } catch (ActiveMQUnBlockedException ube) {
          AsynchronousFailoverTest.log.info("exception when creating consumer");

          retry = true;

        } catch (ActiveMQException e) {
          fail("Invalid Exception type:" + e.getType());
        }
      } while (retry);

      session.start();

      List<Integer> counts = new ArrayList<>(1000);
      int lastCount = -1;
      boolean counterGap = false;
      while (true) {
        ClientMessage message = consumer.receive(500);

        if (message == null) {
          break;
        }

        // messages must remain ordered but there could be a "jump" if messages
        // are missing or duplicated
        int count = message.getIntProperty("counter");
        counts.add(count);
        if (count != lastCount + 1) {
          if (counterGap) {
            Assert.fail("got another counter gap at " + count + ": " + counts);
          } else {
            if (lastCount != -1) {
              AsynchronousFailoverTest.log.info("got first counter gap at " + count);
              counterGap = true;
            }
          }
        }

        lastCount = count;

        message.acknowledge();
      }

      session.close();

      this.listener = null;
    }
  }
  protected void sendCrashReceive() throws Exception {
    ServerLocator[] locators = new ServerLocator[liveServers.size()];
    try {
      for (int i = 0; i < locators.length; i++) {
        locators[i] = getServerLocator(i);
      }

      ClientSessionFactory[] factories = new ClientSessionFactory[liveServers.size()];
      for (int i = 0; i < factories.length; i++) {
        factories[i] = createSessionFactory(locators[i]);
      }

      ClientSession[] sessions = new ClientSession[liveServers.size()];
      for (int i = 0; i < factories.length; i++) {
        sessions[i] = createSession(factories[i], true, true);
        sessions[i].createQueue(ADDRESS, ADDRESS, null, true);
      }

      // make sure bindings are ready before sending messages
      for (int i = 0; i < liveServers.size(); i++) {
        this.waitForBindings(liveServers.get(i).getServer(), ADDRESS.toString(), true, 1, 0, 2000);
        this.waitForBindings(liveServers.get(i).getServer(), ADDRESS.toString(), false, 1, 0, 2000);
      }

      ClientProducer producer = sessions[0].createProducer(ADDRESS);

      for (int i = 0; i < liveServers.size() * 100; i++) {
        ClientMessage message = sessions[0].createMessage(true);

        setBody(i, message);

        message.putIntProperty("counter", i);

        producer.send(message);
      }

      producer.close();

      for (TestableServer liveServer : liveServers) {
        waitForDistribution(ADDRESS, liveServer.getServer(), 100);
      }

      for (TestableServer liveServer : liveServers) {
        liveServer.crash();
      }
      ClientConsumer[] consumers = new ClientConsumer[liveServers.size()];
      for (int i = 0; i < factories.length; i++) {
        consumers[i] = sessions[i].createConsumer(ADDRESS);
        sessions[i].start();
      }

      for (int i = 0; i < 100; i++) {
        for (ClientConsumer consumer : consumers) {
          ClientMessage message = consumer.receive(1000);
          assertNotNull("expecting durable msg " + i, message);
          message.acknowledge();
        }
      }
    } finally {
      for (ServerLocator locator : locators) {
        if (locator != null) {
          try {
            locator.close();
          } catch (Exception e) {
            // ignore
          }
        }
      }
    }
  }
  @Test
  public void testStopStartConsumerAsyncSync() throws Exception {
    ClientSessionFactory sf = createSessionFactory(locator);

    final ClientSession session = sf.createSession(false, true, true);

    session.createQueue(QUEUE, QUEUE, null, false);

    ClientProducer producer = session.createProducer(QUEUE);

    final int numMessages = 100;

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message = createTextMessage(session, "m" + i);
      message.putIntProperty(new SimpleString("i"), i);
      producer.send(message);
    }

    final ClientConsumer consumer = session.createConsumer(QUEUE);

    session.start();

    final CountDownLatch latch = new CountDownLatch(10);

    // Message should be in consumer

    class MyHandler implements MessageHandler {

      boolean failed;

      boolean started = true;

      @Override
      public void onMessage(final ClientMessage message) {

        try {
          if (!started) {
            failed = true;
          }

          latch.countDown();

          if (latch.getCount() == 0) {

            message.acknowledge();
            started = false;
            consumer.setMessageHandler(null);
          }

        } catch (Exception e) {
        }
      }
    }

    MyHandler handler = new MyHandler();

    consumer.setMessageHandler(handler);

    waitForLatch(latch);

    try {
      session.stop();
    } catch (Exception e) {
      SessionStopStartTest.log.warn(e.getMessage(), e);
      throw e;
    }

    Assert.assertFalse(handler.failed);

    // Make sure no exceptions were thrown from onMessage
    Assert.assertNull(consumer.getLastException());
    consumer.setMessageHandler(null);
    session.start();
    for (int i = 0; i < 90; i++) {
      ClientMessage msg = consumer.receive(1000);
      if (msg == null) {
        System.out.println("ClientConsumerTest.testStopConsumer");
      }
      Assert.assertNotNull("message " + i, msg);
      msg.acknowledge();
    }

    Assert.assertNull(consumer.receiveImmediate());

    session.close();
  }
  @Test
  public void testDeployWithFilter() throws Exception {
    final String testAddress = "testAddress";

    final String queueName1 = "queue1";

    final String filter = "cheese='camembert'";

    CoreQueueConfiguration queue1 =
        new CoreQueueConfiguration()
            .setAddress(testAddress)
            .setName(queueName1)
            .setFilterString(filter)
            .setDurable(false);

    configuration.addQueueConfiguration(queue1);

    ActiveMQServer server = addServer(ActiveMQServers.newActiveMQServer(configuration, false));

    server.start();

    ServerLocator locator = createInVMNonHALocator();

    ClientSessionFactory sf = createSessionFactory(locator);

    ClientSession session = addClientSession(sf.createSession(false, true, true));

    ClientProducer producer = session.createProducer(new SimpleString(testAddress));

    final SimpleString propKey = new SimpleString("testkey");

    final int numMessages = 1;

    PredefinedQueueTest.log.info("sending messages");

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message = session.createMessage(true);

      message.putStringProperty(new SimpleString("cheese"), new SimpleString("camembert"));

      message.putIntProperty(propKey, i);

      producer.send(message);
    }

    session.start();

    ClientConsumer consumer1 = session.createConsumer(queueName1);

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message = consumer1.receive(200);
      Assert.assertNotNull(message);
      Assert.assertEquals(i, message.getObjectProperty(propKey));
      message.acknowledge();
    }

    Assert.assertNull(consumer1.receiveImmediate());

    for (int i = 0; i < numMessages; i++) {
      ClientMessage message = session.createMessage(true);

      message.putStringProperty(new SimpleString("cheese"), new SimpleString("roquefort"));

      message.putIntProperty(propKey, i);

      producer.send(message);
    }

    Assert.assertNull(consumer1.receiveImmediate());
  }