public void assertOneConsumerReceivedAllMessages(int messageCount) throws Exception {
    boolean found = false;
    for (Iterator<MessageConsumer> i = consumers.keySet().iterator(); i.hasNext(); ) {
      MessageIdList messageIdList = consumers.get(i.next());
      int count = messageIdList.getMessageCount();
      if (count > 0) {
        if (found) {
          fail("No other consumers should have received any messages");
        } else {
          assertEquals("Consumer should have received all messages.", messageCount, count);
          found = true;
        }
      }
    }

    if (!found) {
      fail("At least one consumer should have received all messages");
    }
  }
  public void testLoadBalancing() throws Exception {
    bridgeBrokers("BrokerA", "BrokerB");
    bridgeBrokers("BrokerB", "BrokerA");

    startAllBrokers();
    waitForBridgeFormation();

    // Setup destination
    Destination dest = createDestination("TEST.FOO", false);

    // Setup consumers
    MessageConsumer clientA = createConsumer("BrokerA", dest);

    // Setup consumers
    MessageConsumer clientB = createConsumer("BrokerB", dest);

    // Send messages
    sendMessages("BrokerA", dest, 5000);

    // Send messages
    sendMessages("BrokerB", dest, 1000);

    // Get message count
    final MessageIdList msgsA = getConsumerMessages("BrokerA", clientA);
    final MessageIdList msgsB = getConsumerMessages("BrokerB", clientB);

    Wait.waitFor(
        new Wait.Condition() {
          public boolean isSatisified() throws Exception {
            return msgsA.getMessageCount() + msgsB.getMessageCount() == 6000;
          }
        });

    LOG.info("A got: " + msgsA.getMessageCount());
    LOG.info("B got: " + msgsB.getMessageCount());

    assertTrue("B got is fair share: " + msgsB.getMessageCount(), msgsB.getMessageCount() > 2000);
  }
  public void testSelectorAwareForwarding() throws Exception {
    clearSelectorCacheFiles();
    // borkerA is local and brokerB is remote
    bridgeAndConfigureBrokers("BrokerA", "BrokerB");
    startAllBrokers();
    waitForBridgeFormation();

    final BrokerService brokerB = brokers.get("BrokerB").broker;
    final BrokerService brokerA = brokers.get("BrokerA").broker;

    // Create the remote virtual topic consumer with selector
    MessageConsumer remoteConsumer =
        createConsumer(
            "BrokerB",
            createDestination("Consumer.B.VirtualTopic.tempTopic", false),
            "foo = 'bar'");

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 1;
          }
        },
        500);

    ActiveMQQueue queueB = new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic");
    Destination destination = getDestination(brokers.get("BrokerB").broker, queueB);
    assertEquals(1, destination.getConsumers().size());

    ActiveMQTopic virtualTopic = new ActiveMQTopic("VirtualTopic.tempTopic");
    assertNull(getDestination(brokers.get("BrokerA").broker, virtualTopic));
    assertNull(getDestination(brokers.get("BrokerB").broker, virtualTopic));

    // send two types of messages, one unwanted and the other wanted
    sendMessages("BrokerA", virtualTopic, 1, asMap("foo", "bar"));
    sendMessages("BrokerA", virtualTopic, 1, asMap("ceposta", "redhat"));

    MessageIdList msgsB = getConsumerMessages("BrokerB", remoteConsumer);
    // wait for the wanted one to arrive at the remote consumer
    msgsB.waitForMessagesToArrive(1);

    // ensure we don't get any more messages
    msgsB.waitForMessagesToArrive(1, 1000);

    // remote consumer should only get one of the messages
    assertEquals(1, msgsB.getMessageCount());

    // and the enqueue count for the remote queue should only be 1
    assertEquals(
        1,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());

    // now let's remove the consumer on broker B and recreate it with new selector
    remoteConsumer.close();

    // now let's shut down broker A and clear its persistent selector cache
    brokerA.stop();
    brokerA.waitUntilStopped();
    deleteSelectorCacheFile("BrokerA");

    assertEquals(0, destination.getConsumers().size());

    remoteConsumer =
        createConsumer(
            "BrokerB",
            createDestination("Consumer.B.VirtualTopic.tempTopic", false),
            "ceposta = 'redhat'");

    assertEquals(1, destination.getConsumers().size());

    // now let's start broker A back up
    brokerA.start(true);
    brokerA.waitUntilStarted();

    System.out.println(brokerA.getNetworkConnectors());

    // give a sec to let advisories propogate
    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 1;
          }
        },
        500);

    // send two types of messages, one unwanted and the other wanted
    sendMessages("BrokerA", virtualTopic, 1, asMap("foo", "bar"));
    sendMessages("BrokerB", virtualTopic, 1, asMap("foo", "bar"));
    sendMessages("BrokerA", virtualTopic, 1, asMap("ceposta", "redhat"));
    sendMessages("BrokerB", virtualTopic, 1, asMap("ceposta", "redhat"));

    // lets get messages on consumer B
    msgsB = getConsumerMessages("BrokerB", remoteConsumer);
    msgsB.waitForMessagesToArrive(2);

    // ensure we don't get any more messages
    msgsB.waitForMessagesToArrive(1, 1000);

    // remote consumer should only get 10 of the messages
    assertEquals(2, msgsB.getMessageCount());

    // queue should be drained
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());
    // and the enqueue count for the remote queue should only be 1
    assertEquals(
        3,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
  }
  public void testSelectorsAndNonSelectors() throws Exception {
    clearSelectorCacheFiles();
    // borkerA is local and brokerB is remote
    bridgeAndConfigureBrokers("BrokerA", "BrokerB");
    startAllBrokers();
    waitForBridgeFormation();

    final BrokerService brokerA = brokers.get("BrokerA").broker;
    final BrokerService brokerB = brokers.get("BrokerB").broker;

    // Create the remote virtual topic consumer with selector
    ActiveMQDestination consumerBQueue =
        createDestination("Consumer.B.VirtualTopic.tempTopic", false);

    MessageConsumer selectingConsumer = createConsumer("BrokerB", consumerBQueue, "foo = 'bar'");
    MessageConsumer nonSelectingConsumer = createConsumer("BrokerB", consumerBQueue);

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 2;
          }
        },
        500);

    Destination destination = getDestination(brokerB, consumerBQueue);
    assertEquals(2, destination.getConsumers().size());

    // publisher publishes to this
    ActiveMQTopic virtualTopic = new ActiveMQTopic("VirtualTopic.tempTopic");
    sendMessages("BrokerA", virtualTopic, 10, asMap("foo", "bar"));
    sendMessages("BrokerA", virtualTopic, 10);

    MessageIdList selectingConsumerMessages = getConsumerMessages("BrokerB", selectingConsumer);

    MessageIdList nonSelectingConsumerMessages =
        getConsumerMessages("BrokerB", nonSelectingConsumer);

    // we only expect half of the messages that get sent with the selector, because they get load
    // balanced
    selectingConsumerMessages.waitForMessagesToArrive(5, 1000L);
    assertEquals(5, selectingConsumerMessages.getMessageCount());

    nonSelectingConsumerMessages.waitForMessagesToArrive(15, 1000L);
    assertEquals(15, nonSelectingConsumerMessages.getMessageCount());

    // assert broker A stats
    waitForMessagesToBeConsumed(brokerA, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // assert broker B stats
    waitForMessagesToBeConsumed(brokerB, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // now let's close the consumer without the selector
    nonSelectingConsumer.close();

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 1;
          }
        },
        500);

    // and let's send messages with a selector that doesnt' match
    selectingConsumerMessages.flushMessages();

    sendMessages("BrokerA", virtualTopic, 10, asMap("ceposta", "redhat"));

    selectingConsumerMessages = getConsumerMessages("BrokerB", selectingConsumer);
    selectingConsumerMessages.waitForMessagesToArrive(1, 1000L);
    assertEquals(0, selectingConsumerMessages.getMessageCount());

    // assert broker A stats
    waitForMessagesToBeConsumed(brokerA, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // assert broker B stats
    waitForMessagesToBeConsumed(brokerB, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // now lets disconect the selecting consumer for a sec and send messages with a selector that
    // DOES match
    selectingConsumer.close();

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 0;
          }
        },
        500);

    selectingConsumerMessages.flushMessages();

    sendMessages("BrokerA", virtualTopic, 10, asMap("foo", "bar"));

    // assert broker A stats
    waitForMessagesToBeConsumed(brokerA, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        30,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        10,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // assert broker B stats
    waitForMessagesToBeConsumed(brokerB, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    selectingConsumer = createConsumer("BrokerB", consumerBQueue, "foo = 'bar'");
    selectingConsumerMessages = getConsumerMessages("BrokerB", selectingConsumer);
    selectingConsumerMessages.waitForMessagesToArrive(10);
    assertEquals(10, selectingConsumerMessages.getMessageCount());

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 1;
          }
        },
        500);

    // assert broker A stats
    waitForMessagesToBeConsumed(brokerA, "Consumer.B.VirtualTopic.tempTopic", false, 30, 30, 5000);
    assertEquals(
        30,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        30,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // assert broker B stats
    waitForMessagesToBeConsumed(brokerB, "Consumer.B.VirtualTopic.tempTopic", false, 30, 30, 5000);
    assertEquals(
        30,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        30,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());
  }
  public void testSelectorConsumptionWithNoMatchAtHeadOfQueue() throws Exception {
    clearSelectorCacheFiles();
    startAllBrokers();

    BrokerService brokerA = brokers.get("BrokerA").broker;

    // Create the remote virtual topic consumer with selector
    ActiveMQDestination consumerQueue =
        createDestination("Consumer.B.VirtualTopic.tempTopic", false);

    // create it so that the queue is there and messages don't get lost
    MessageConsumer selectingConsumer = establishConsumer("BrokerA", consumerQueue);

    // send messages with NO selection criteria first, and then with a property to be selected
    // this should put messages at the head of the queue that don't match selection
    ActiveMQTopic virtualTopic = new ActiveMQTopic("VirtualTopic.tempTopic");
    sendMessages("BrokerA", virtualTopic, 1);

    // close the consumer w/out consuming any messages; they'll be marked redelivered
    selectingConsumer.close();

    selectingConsumer = createConsumer("BrokerA", consumerQueue, "foo = 'bar'");

    sendMessages("BrokerA", virtualTopic, 1, asMap("foo", "bar"));

    MessageIdList selectingConsumerMessages = getConsumerMessages("BrokerA", selectingConsumer);
    selectingConsumerMessages.waitForMessagesToArrive(1, 1000L);

    assertEquals(1, selectingConsumerMessages.getMessageCount());
    selectingConsumerMessages.waitForMessagesToArrive(10, 1000L);
    assertEquals(1, selectingConsumerMessages.getMessageCount());

    // assert broker A stats
    waitForMessagesToBeConsumed(brokerA, "Consumer.B.VirtualTopic.tempTopic", false, 2, 1, 5000);
    assertEquals(
        1,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getConsumers()
            .size());
    assertEquals(
        2,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        1,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        1,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());
  }
  public void testMessageLeaks() throws Exception {
    clearSelectorCacheFiles();
    startAllBrokers();

    final BrokerService brokerA = brokers.get("BrokerA").broker;

    // Create the remote virtual topic consumer with selector
    ActiveMQDestination consumerQueue =
        createDestination("Consumer.B.VirtualTopic.tempTopic", false);
    // create it so that the queue is there and messages don't get lost
    MessageConsumer consumer1 = createConsumer("BrokerA", consumerQueue, "SYMBOL = 'AAPL'");
    MessageConsumer consumer2 = createConsumer("BrokerA", consumerQueue, "SYMBOL = 'AAPL'");

    ActiveMQTopic virtualTopic = new ActiveMQTopic("VirtualTopic.tempTopic");
    ProducerThreadTester producerTester = createProducerTester("BrokerA", virtualTopic);
    producerTester.setRunIndefinitely(true);
    producerTester.setSleep(5);
    producerTester.addMessageProperty("AAPL");
    producerTester.addMessageProperty("VIX");
    producerTester.start();

    int currentCount = producerTester.getSentCount();
    LOG.info(
        ">>>> currently sent: total="
            + currentCount
            + ", AAPL="
            + producerTester.getCountForProperty("AAPL")
            + ", VIX="
            + producerTester.getCountForProperty("VIX"));

    // let some messages get sent
    Thread.sleep(2000);

    MessageIdList consumer1Messages = getConsumerMessages("BrokerA", consumer1);
    consumer1Messages.waitForMessagesToArrive(50, 1000);

    // switch one of the consumers to SYMBOL = 'VIX'
    consumer1.close();
    consumer1 = createConsumer("BrokerA", consumerQueue, "SYMBOL = 'VIX'");

    // wait till new consumer is on board
    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return brokerA
                    .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
                    .getConsumers()
                    .size()
                == 2;
          }
        });

    currentCount = producerTester.getSentCount();
    LOG.info(
        ">>>> currently sent: total="
            + currentCount
            + ", AAPL="
            + producerTester.getCountForProperty("AAPL")
            + ", VIX="
            + producerTester.getCountForProperty("VIX"));

    // let some messages get sent
    Thread.sleep(2000);

    // switch the other consumer to SYMBOL = 'VIX'
    consumer2.close();
    consumer2 = createConsumer("BrokerA", consumerQueue, "SYMBOL = 'VIX'");

    // wait till new consumer is on board
    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return brokerA
                    .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
                    .getConsumers()
                    .size()
                == 2;
          }
        });

    currentCount = producerTester.getSentCount();
    LOG.info(
        ">>>> currently sent: total="
            + currentCount
            + ", AAPL="
            + producerTester.getCountForProperty("AAPL")
            + ", VIX="
            + producerTester.getCountForProperty("VIX"));

    // let some messages get sent
    Thread.sleep(2000);

    currentCount = producerTester.getSentCount();
    LOG.info(
        ">>>> currently sent: total="
            + currentCount
            + ", AAPL="
            + producerTester.getCountForProperty("AAPL")
            + ", VIX="
            + producerTester.getCountForProperty("VIX"));

    // make sure if there are messages that are orphaned in the queue that this number doesn't
    // grow...
    final long currentDepth =
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount();

    LOG.info(">>>>> Orphaned messages? " + currentDepth);

    // wait 5s to see if we can get a growth in the depth of the queue
    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return brokerA
                    .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
                    .getDestinationStatistics()
                    .getMessages()
                    .getCount()
                > currentDepth;
          }
        },
        5000);

    // stop producers
    producerTester.setRunning(false);
    producerTester.join();

    // pause to let consumers catch up
    Thread.sleep(1000);

    assertTrue(
        brokerA
                .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
                .getDestinationStatistics()
                .getMessages()
                .getCount()
            <= currentDepth);
  }