Package org.hornetq.tests.integration.client

Source Code of org.hornetq.tests.integration.client.ConsumerWindowSizeTest$FakeOutputStream

/*
* Copyright 2009 Red Hat, Inc.
* Red Hat licenses this file to you under the Apache License, version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*    http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.  See the License for the specific language governing
* permissions and limitations under the License.
*/
package org.hornetq.tests.integration.client;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import junit.framework.Assert;

import org.hornetq.api.core.SimpleString;
import org.hornetq.api.core.client.ClientConsumer;
import org.hornetq.api.core.client.ClientMessage;
import org.hornetq.api.core.client.ClientProducer;
import org.hornetq.api.core.client.ClientSession;
import org.hornetq.api.core.client.ClientSessionFactory;
import org.hornetq.api.core.client.MessageHandler;
import org.hornetq.api.core.client.ServerLocator;
import org.hornetq.core.client.impl.ClientConsumerInternal;
import org.hornetq.core.logging.Logger;
import org.hornetq.core.postoffice.Binding;
import org.hornetq.core.postoffice.Bindings;
import org.hornetq.core.postoffice.QueueBinding;
import org.hornetq.core.server.Consumer;
import org.hornetq.core.server.HornetQServer;
import org.hornetq.core.server.impl.ServerConsumerImpl;
import org.hornetq.core.settings.impl.AddressSettings;
import org.hornetq.tests.util.ServiceTestBase;

/**
* @author <a href="mailto:andy.taylor@jboss.org">Andy Taylor</a>
* @author <a href="mailto:clebert.suconic@jboss.org">Clebert Suconic</a>
*/
public class ConsumerWindowSizeTest extends ServiceTestBase
{
   private final SimpleString addressA = new SimpleString("addressA");

   private final SimpleString queueA = new SimpleString("queueA");

   private final int TIMEOUT = 5;

   private static final Logger log = Logger.getLogger(ConsumerWindowSizeTest.class);

   private static final boolean isTrace = ConsumerWindowSizeTest.log.isTraceEnabled();

   private ServerLocator locator;

   protected boolean isNetty()
   {
      return false;
   }

   @Override
   protected void setUp() throws Exception
   {
      super.setUp();

      locator = createFactory(isNetty());
   }

   @Override
   protected void tearDown() throws Exception
   {
      locator.close();

      super.tearDown();
   }

   private int getMessageEncodeSize(final SimpleString address) throws Exception
   {
      ServerLocator locator = createInVMNonHALocator();
      ClientSessionFactory cf = locator.createSessionFactory();
      ClientSession session = cf.createSession(false, true, true);
      ClientMessage message = session.createMessage(false);
      // we need to set the destination so we can calculate the encodesize correctly
      message.setAddress(address);
      int encodeSize = message.getEncodeSize();
      session.close();
      cf.close();
      return encodeSize;
   }

   // https://jira.jboss.org/jira/browse/HORNETQ-385
   public void testReceiveImmediateWithZeroWindow() throws Exception
   {
      HornetQServer server = createServer(false, isNetty());
      try
      {
         server.start();

         locator.setConsumerWindowSize(0);

         ClientSessionFactory sf = locator.createSessionFactory();

         ClientSession session = sf.createSession(false, false, false);
         session.createQueue("testWindow", "testWindow", true);
         session.close();

         int numConsumers = 5;

         ArrayList<ClientConsumer> consumers = new ArrayList<ClientConsumer>();
         ArrayList<ClientSession> sessions = new ArrayList<ClientSession>();
         for (int i = 0; i < numConsumers; i++)
         {
            System.out.println("created: " + i);
            ClientSession session1 = sf.createSession();
            ClientConsumer consumer = session1.createConsumer("testWindow");
            consumers.add(consumer);
            session1.start();
            sessions.add(session1);
            consumer.receiveImmediate();

         }

         ClientSession senderSession = sf.createSession(false, false);

         ClientProducer producer = senderSession.createProducer("testWindow");

         ClientMessage sent = senderSession.createMessage(true);
         sent.putStringProperty("hello", "world");
         System.out.println("sending message");
         producer.send(sent);

         senderSession.commit();

         senderSession.start();

         ClientConsumer consumer = consumers.get(2);
         ClientMessage received = consumer.receive(1000);
         assertNotNull(received);

         for (ClientSession tmpSess : sessions)
         {
            tmpSess.close();
         }

         senderSession.close();

      }
      finally
      {
         server.stop();
      }

   }

   // https://jira.jboss.org/jira/browse/HORNETQ-385
   public void testReceiveImmediateWithZeroWindow2() throws Exception
   {
      HornetQServer server = createServer(true);
      ServerLocator locator = createInVMNonHALocator();
      try
      {
         server.start();

         locator.setConsumerWindowSize(0);

         ClientSessionFactory sf = locator.createSessionFactory();
         ClientSession session = sf.createSession(false, false, false);
         session.createQueue("testReceive", "testReceive", true);
         session.close();

         ClientSession sessionProd = sf.createSession(false, false);
         ClientMessage msg = sessionProd.createMessage(true);
         msg.putStringProperty("hello", "world");
         ClientProducer prod = sessionProd.createProducer("testReceive");

         prod.send(msg);
         sessionProd.commit();

         ClientSession session1 = sf.createSession();
         ClientConsumer consumer = session1.createConsumer("testReceive");
         session1.start();

         Thread.sleep(1000);
         ClientMessage message = null;
         message = consumer.receiveImmediate();
         // message = consumer.receive(1000); // the test will pass if used receive(1000) instead of receiveImmediate
         assertNotNull(message);
         System.out.println(message.getStringProperty("hello"));
         message.acknowledge();

         prod.send(msg);
         sessionProd.commit();

         message = consumer.receive(10000);
         assertNotNull(message);
         System.out.println(message.getStringProperty("hello"));
         message.acknowledge();

         session.close();
         session1.close();
         sessionProd.close();
      }
      finally
      {
         locator.close();
         server.stop();
      }
   }

   // https://jira.jboss.org/jira/browse/HORNETQ-385
   public void testReceiveImmediateWithZeroWindow3() throws Exception
   {
      HornetQServer server = createServer(false, isNetty());
      try
      {
         server.start();

         locator.setConsumerWindowSize(0);

         ClientSessionFactory sf = locator.createSessionFactory();

         ClientSession session = sf.createSession(false, false, false);
         session.createQueue("testWindow", "testWindow", true);
         session.close();

         int numConsumers = 5;

         ArrayList<ClientConsumer> consumers = new ArrayList<ClientConsumer>();
         ArrayList<ClientSession> sessions = new ArrayList<ClientSession>();
         for (int i = 0; i < numConsumers; i++)
         {
            System.out.println("created: " + i);
            ClientSession session1 = sf.createSession();
            ClientConsumer consumer = session1.createConsumer("testWindow");
            consumers.add(consumer);
            session1.start();
            sessions.add(session1);
            consumer.receive(10);

         }

         ClientSession senderSession = sf.createSession(false, false);

         ClientProducer producer = senderSession.createProducer("testWindow");

         ClientMessage sent = senderSession.createMessage(true);
         sent.putStringProperty("hello", "world");

         producer.send(sent);

         senderSession.commit();

         senderSession.start();

         ClientConsumer consumer = consumers.get(2);
         ClientMessage received = consumer.receive(1000);
         assertNotNull(received);

         for (ClientSession tmpSess : sessions)
         {
            tmpSess.close();
         }

         senderSession.close();

      }
      finally
      {
         server.stop();
      }

   }

   public void testReceiveImmediateWithZeroWindow4() throws Exception
   {
      HornetQServer server = createServer(false, isNetty());
      try
      {
         server.start();

         locator.setConsumerWindowSize(0);

         ClientSessionFactory sf = locator.createSessionFactory();

         ClientSession session = sf.createSession(false, false, false);
         session.createQueue("testWindow", "testWindow", true);
         session.close();

         int numConsumers = 5;

         ArrayList<ClientConsumer> consumers = new ArrayList<ClientConsumer>();
         ArrayList<ClientSession> sessions = new ArrayList<ClientSession>();
         for (int i = 0; i < numConsumers; i++)
         {
            System.out.println("created: " + i);
            ClientSession session1 = sf.createSession();
            ClientConsumer consumer = session1.createConsumer("testWindow");
            consumers.add(consumer);
            session1.start();
            sessions.add(session1);
            consumer.receive(10);

         }

         ClientSession senderSession = sf.createSession(false, false);

         ClientProducer producer = senderSession.createProducer("testWindow");

         ClientMessage sent = senderSession.createMessage(true);
         sent.putStringProperty("hello", "world");

         producer.send(sent);

         senderSession.commit();

         senderSession.start();

         ClientConsumer consumer = consumers.get(2);
         ClientMessage received = consumer.receiveImmediate();
         assertNotNull(received);

         for (ClientSession tmpSess : sessions)
         {
            tmpSess.close();
         }

         senderSession.close();

      }
      finally
      {
         server.stop();
      }

   }

   /*
   * tests send window size. we do this by having 2 receivers on the q. since we roundrobin the consumer for delivery we
   * know if consumer 1 has received n messages then consumer 2 must have also have received n messages or at least up
   * to its window size
   * */
   public void testSendWindowSize() throws Exception
   {
      HornetQServer messagingService = createServer(false, isNetty());
      locator.setBlockOnNonDurableSend(false);
      try
      {
         messagingService.start();
         int numMessage = 100;
         locator.setConsumerWindowSize(numMessage * getMessageEncodeSize(addressA));
         ClientSessionFactory cf = locator.createSessionFactory();
         ClientSession sendSession = cf.createSession(false, true, true);
         ClientSession receiveSession = cf.createSession(false, true, true);
         sendSession.createQueue(addressA, queueA, false);
         ClientConsumer receivingConsumer = receiveSession.createConsumer(queueA);

         ClientSession session = cf.createSession(false, true, true);
         ClientProducer cp = sendSession.createProducer(addressA);
         ClientConsumer cc = session.createConsumer(queueA);
         session.start();
         receiveSession.start();
         for (int i = 0; i < numMessage * 4; i++)
         {
            cp.send(sendSession.createMessage(false));
         }

         for (int i = 0; i < numMessage * 2; i++)
         {
            ClientMessage m = receivingConsumer.receive(5000);
            Assert.assertNotNull(m);
            m.acknowledge();
         }
         receiveSession.close();

         for (int i = 0; i < numMessage * 2; i++)
         {
            ClientMessage m = cc.receive(5000);
            Assert.assertNotNull(m);
            m.acknowledge();
         }

         session.close();
         sendSession.close();

         Assert.assertEquals(0, getMessageCount(messagingService, queueA.toString()));

      }
      finally
      {
         if (messagingService.isStarted())
         {
            messagingService.stop();
         }
      }
   }

   public void testSlowConsumerBufferingOne() throws Exception
   {
      HornetQServer server = createServer(false, isNetty());

      ClientSession sessionB = null;
      ClientSession session = null;

      try
      {
         final int numberOfMessages = 100;

         server.start();

         locator.setConsumerWindowSize(1);

         ClientSessionFactory sf = locator.createSessionFactory();

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

         SimpleString ADDRESS = addressA;

         session.createQueue(ADDRESS, ADDRESS, true);

         sessionB = sf.createSession(false, true, true);
         sessionB.start();

         session.start();

         ClientConsumer consNeverUsed = sessionB.createConsumer(ADDRESS);

         ClientConsumer cons1 = session.createConsumer(ADDRESS);

         ClientProducer prod = session.createProducer(ADDRESS);

         for (int i = 0; i < numberOfMessages; i++)
         {
            prod.send(createTextMessage(session, "Msg" + i));
         }

         for (int i = 0; i < numberOfMessages - 1; i++)
         {
            ClientMessage msg = cons1.receive(1000);
            Assert.assertNotNull("expected message at i = " + i, msg);
            msg.acknowledge();
         }

         ClientMessage msg = consNeverUsed.receive(500);
         Assert.assertNotNull(msg);
         msg.acknowledge();

         session.close();
         session = null;

         sessionB.close();
         sessionB = null;

         Assert.assertEquals(0, getMessageCount(server, ADDRESS.toString()));

      }
      finally
      {
         try
         {
            if (session != null)
            {
               session.close();
            }
            if (sessionB != null)
            {
               sessionB.close();
            }
         }
         catch (Exception ignored)
         {
         }

         if (server.isStarted())
         {
            server.stop();
         }
      }
   }

   public void testSlowConsumerNoBuffer() throws Exception
   {
      internalTestSlowConsumerNoBuffer(false);
   }

   // I believe this test became invalid after we started using another thread to deliver the large message
   public void disabled_testSlowConsumerNoBufferLargeMessages() throws Exception
   {
      internalTestSlowConsumerNoBuffer(true);
   }

   private void internalTestSlowConsumerNoBuffer(final boolean largeMessages) throws Exception
   {
      HornetQServer server = createServer(false, isNetty());

      ClientSession sessionB = null;
      ClientSession session = null;

      try
      {
         final int numberOfMessages = 100;

         server.start();

         locator.setConsumerWindowSize(0);

         ClientSessionFactory sf = locator.createSessionFactory();

         if (largeMessages)
         {
            sf.getServerLocator().setMinLargeMessageSize(100);
         }

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

         SimpleString ADDRESS = addressA;

         session.createQueue(ADDRESS, ADDRESS, true);

         sessionB = sf.createSession(false, true, true);
         sessionB.start();

         session.start();

         ClientConsumerInternal consNeverUsed = (ClientConsumerInternal)sessionB.createConsumer(ADDRESS);

         ClientProducer prod = session.createProducer(ADDRESS);

         // This will force a credit to be sent, but if the message wasn't received we need to take out that credit from
         // the server
         // or the client will be buffering messages
         Assert.assertNull(consNeverUsed.receive(1));

         ClientMessage msg = createTextMessage(session, "This one will expire");
         if (largeMessages)
         {
            msg.getBodyBuffer().writeBytes(new byte[600]);
         }

         msg.setExpiration(System.currentTimeMillis() + 100);
         prod.send(msg);

         msg = createTextMessage(session, "First-on-non-buffered");

         prod.send(msg);

         Thread.sleep(110);

         // It will be able to receive another message, but it shouldn't send a credit again, as the credit was already
         // sent
         msg = consNeverUsed.receive(TIMEOUT * 1000);
         Assert.assertNotNull(msg);
         Assert.assertEquals("First-on-non-buffered", getTextMessage(msg));
         msg.acknowledge();

         ClientConsumer cons1 = session.createConsumer(ADDRESS);

         for (int i = 0; i < numberOfMessages; i++)
         {
            msg = createTextMessage(session, "Msg" + i);

            if (largeMessages)
            {
               msg.getBodyBuffer().writeBytes(new byte[600]);
            }

            prod.send(msg);
         }

         for (int i = 0; i < numberOfMessages; i++)
         {
            msg = cons1.receive(1000);
            Assert.assertNotNull("expected message at i = " + i, msg);
            Assert.assertEquals("Msg" + i, getTextMessage(msg));
            msg.acknowledge();
         }

         Assert.assertEquals(0, consNeverUsed.getBufferSize());

         session.close();
         session = null;

         sessionB.close();
         sessionB = null;

         Assert.assertEquals(0, getMessageCount(server, ADDRESS.toString()));

      }
      finally
      {
         try
         {
            if (session != null)
            {
               session.close();
            }
            if (sessionB != null)
            {
               sessionB.close();
            }
         }
         catch (Exception ignored)
         {
         }

         if (server.isStarted())
         {
            server.stop();
         }
      }
   }

   public void testSlowConsumerNoBuffer2() throws Exception
   {
      internalTestSlowConsumerNoBuffer2(false);
   }

   public void testSlowConsumerNoBuffer2LargeMessages() throws Exception
   {
      internalTestSlowConsumerNoBuffer2(true);
   }

   private void internalTestSlowConsumerNoBuffer2(final boolean largeMessages) throws Exception
   {
      HornetQServer server = createServer(false, isNetty());

      ClientSession session1 = null;
      ClientSession session2 = null;

      try
      {
         final int numberOfMessages = 10;

         server.start();

         locator.setConsumerWindowSize(0);

         if (largeMessages)
         {
            locator.setMinLargeMessageSize(100);
         }

         ClientSessionFactory sf = locator.createSessionFactory();

         session1 = sf.createSession(false, true, true);

         session2 = sf.createSession(false, true, true);

         session1.start();

         session2.start();

         SimpleString ADDRESS = new SimpleString("some-queue");

         session1.createQueue(ADDRESS, ADDRESS, true);

         ClientConsumerInternal cons1 = (ClientConsumerInternal)session1.createConsumer(ADDRESS);

         // Note we make sure we send the messages *before* cons2 is created

         ClientProducer prod = session1.createProducer(ADDRESS);

         for (int i = 0; i < numberOfMessages; i++)
         {
            ClientMessage msg = createTextMessage(session1, "Msg" + i);
            if (largeMessages)
            {
               msg.getBodyBuffer().writeBytes(new byte[600]);
            }
            prod.send(msg);
         }

         ClientConsumerInternal cons2 = (ClientConsumerInternal)session2.createConsumer(ADDRESS);

         for (int i = 0; i < numberOfMessages / 2; i++)
         {
            ClientMessage msg = cons1.receive(1000);
            Assert.assertNotNull("expected message at i = " + i, msg);

            String str = getTextMessage(msg);
            Assert.assertEquals("Msg" + i, str);

            log.info("got msg " + str);

            msg.acknowledge();

            Assert.assertEquals("A slow consumer shouldn't buffer anything on the client side!",
                                0,
                                cons1.getBufferSize());
         }

         for (int i = numberOfMessages / 2; i < numberOfMessages; i++)
         {
            ClientMessage msg = cons2.receive(1000);

            Assert.assertNotNull("expected message at i = " + i, msg);

            String str = getTextMessage(msg);

            log.info("got msg " + str);

            Assert.assertEquals("Msg" + i, str);

            msg.acknowledge();

            Assert.assertEquals("A slow consumer shouldn't buffer anything on the client side!",
                                0,
                                cons2.getBufferSize());
         }

         session1.close(); // just to make sure everything is flushed and no pending packets on the sending buffer, or
         // the getMessageCount would fail
         session2.close();

         session1 = sf.createSession(false, true, true);
         session1.start();
         session2 = sf.createSession(false, true, true);
         session2.start();

         prod = session1.createProducer(ADDRESS);

         Assert.assertEquals(0, getMessageCount(server, ADDRESS.toString()));

         // This should also work the other way around

         cons1.close();

         cons2.close();

         cons1 = (ClientConsumerInternal)session1.createConsumer(ADDRESS);

         // Note we make sure we send the messages *before* cons2 is created

         for (int i = 0; i < numberOfMessages; i++)
         {
            ClientMessage msg = createTextMessage(session1, "Msg" + i);
            if (largeMessages)
            {
               msg.getBodyBuffer().writeBytes(new byte[600]);
            }
            prod.send(msg);
         }

         cons2 = (ClientConsumerInternal)session2.createConsumer(ADDRESS);

         // Now we receive on cons2 first

         for (int i = 0; i < numberOfMessages / 2; i++)
         {
            ClientMessage msg = cons2.receive(1000);
            Assert.assertNotNull("expected message at i = " + i, msg);

            Assert.assertEquals("Msg" + i, msg.getBodyBuffer().readString());

            msg.acknowledge();

            Assert.assertEquals("A slow consumer shouldn't buffer anything on the client side!",
                                0,
                                cons2.getBufferSize());

         }

         for (int i = numberOfMessages / 2; i < numberOfMessages; i++)
         {
            ClientMessage msg = cons1.receive(1000);

            Assert.assertNotNull("expected message at i = " + i, msg);

            Assert.assertEquals("Msg" + i, msg.getBodyBuffer().readString());

            msg.acknowledge();

            Assert.assertEquals("A slow consumer shouldn't buffer anything on the client side!",
                                0,
                                cons1.getBufferSize());
         }

         session1.close();
         session1 = null;
         session2.close();
         session2 = null;
         Assert.assertEquals(0, getMessageCount(server, ADDRESS.toString()));

      }
      finally
      {
         try
         {
            if (session1 != null)
            {
               session1.close();
            }
            if (session2 != null)
            {
               session2.close();
            }
         }
         catch (Exception ignored)
         {
         }

         if (server.isStarted())
         {
            server.stop();
         }
      }
   }

   public void testSaveBuffersOnLargeMessage() throws Exception
   {
      HornetQServer server = createServer(false, isNetty());

      ClientSession session1 = null;

      try
      {
         final int numberOfMessages = 10;

         server.start();

         locator.setConsumerWindowSize(0);

         locator.setMinLargeMessageSize(100);

         ClientSessionFactory sf = locator.createSessionFactory();

         session1 = sf.createSession(false, true, true);

         session1.start();

         SimpleString ADDRESS = new SimpleString("some-queue");

         session1.createQueue(ADDRESS, ADDRESS, true);

         ClientConsumerInternal cons1 = (ClientConsumerInternal)session1.createConsumer(ADDRESS);

         // Note we make sure we send the messages *before* cons2 is created

         ClientProducer prod = session1.createProducer(ADDRESS);

         for (int i = 0; i < numberOfMessages; i++)
         {
            ClientMessage msg = session1.createMessage(true);
            msg.getBodyBuffer().writeBytes(new byte[600]);
            prod.send(msg);
         }

         for (int i = 0; i < numberOfMessages; i++)
         {
            ClientMessage msg = cons1.receive(1000);
            Assert.assertNotNull("expected message at i = " + i, msg);

            msg.saveToOutputStream(new FakeOutputStream());

            msg.acknowledge();

            Assert.assertEquals("A slow consumer shouldn't buffer anything on the client side!",
                                0,
                                cons1.getBufferSize());
         }

         session1.close(); // just to make sure everything is flushed and no pending packets on the sending buffer, or
         session1.close();
         session1 = null;
         Assert.assertEquals(0, getMessageCount(server, ADDRESS.toString()));

      }
      finally
      {
         try
         {
            if (session1 != null)
            {
               session1.close();
            }
         }
         catch (Exception ignored)
         {
         }

         if (server.isStarted())
         {
            server.stop();
         }
      }
   }

   class FakeOutputStream extends OutputStream
   {

      /* (non-Javadoc)
       * @see java.io.OutputStream#write(int)
       */
      @Override
      public void write(int b) throws IOException
      {
      }

   }

   public void testSlowConsumerOnMessageHandlerNoBuffers() throws Exception
   {
      internalTestSlowConsumerOnMessageHandlerNoBuffers(false);
   }

   public void testSlowConsumerOnMessageHandlerNoBuffersLargeMessage() throws Exception
   {
      internalTestSlowConsumerOnMessageHandlerNoBuffers(true);
   }

   public void testFlowControl() throws Exception
   {
      internalTestFlowControlOnRollback(false);
   }
  
   public void testFlowControlLargeMessage() throws Exception
   {
      internalTestFlowControlOnRollback(true);
   }
  
   private void internalTestFlowControlOnRollback(final boolean isLargeMessage) throws Exception
   {

      HornetQServer server = createServer(false, isNetty());
     
      AddressSettings settings = new AddressSettings();
      settings.setMaxDeliveryAttempts(-1);
      server.getAddressSettingsRepository().addMatch("#", settings);

      ClientSession session = null;

      try
      {
         final int numberOfMessages = 100;

         server.start();

         locator.setConsumerWindowSize(300000);
        
         if (isLargeMessage)
         {
            // something to ensure we are using large messages
            locator.setMinLargeMessageSize(100);
         }
         else
         {
            // To make sure large messages won't kick in, we set anything large
            locator.setMinLargeMessageSize(Integer.MAX_VALUE);
         }

         ClientSessionFactory sf = locator.createSessionFactory();

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

         SimpleString ADDRESS = new SimpleString("some-queue");

         session.createQueue(ADDRESS, ADDRESS, true);
        
        
         ClientProducer producer = session.createProducer(ADDRESS);
        
         for (int i = 0 ; i < numberOfMessages; i++)
         {
            ClientMessage msg = session.createMessage(true);
            msg.putIntProperty("count", i);
            msg.getBodyBuffer().writeBytes(new byte[1024]);
            producer.send(msg);
         }
        
         session.commit();
        
         ClientConsumerInternal consumer = (ClientConsumerInternal)session.createConsumer(ADDRESS);
        
         session.start();

         for (int repeat = 0; repeat < 100; repeat ++)
         {
            System.out.println("Repeat " + repeat);
            long timeout = System.currentTimeMillis() + 2000;
            // At least 10 messages on the buffer
            while (timeout > System.currentTimeMillis() && consumer.getBufferSize() <= 10)
            {
               Thread.sleep(10);
            }
            assertTrue(consumer.getBufferSize() >= 10);
           
            ClientMessage msg = consumer.receive(500);
            msg.getBodyBuffer().readByte();
            assertNotNull(msg);
            msg.acknowledge();
            session.rollback();
         }
        
        
         for (int i = 0 ; i < numberOfMessages; i++)
         {
            ClientMessage msg = consumer.receive(5000);
            assertNotNull(msg);
            System.out.println("msg " + msg);
            msg.getBodyBuffer().readByte();
            msg.acknowledge();
            session.commit();
         }

      }
      finally
      {
         try
         {
            if (session != null)
            {
               session.close();
            }
         }
         catch (Exception ignored)
         {
         }

         if (server.isStarted())
         {
            server.stop();
         }
      }
   }



   public void internalTestSlowConsumerOnMessageHandlerNoBuffers(final boolean largeMessages) throws Exception
   {

      HornetQServer server = createServer(false, isNetty());

      ClientSession sessionB = null;
      ClientSession session = null;

      try
      {
         final int numberOfMessages = 100;

         server.start();

         locator.setConsumerWindowSize(0);

         if (largeMessages)
         {
            locator.setMinLargeMessageSize(100);
         }

         ClientSessionFactory sf = locator.createSessionFactory();

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

         SimpleString ADDRESS = new SimpleString("some-queue");

         session.createQueue(ADDRESS, ADDRESS, true);

         sessionB = sf.createSession(false, true, true);
         sessionB.start();

         session.start();

         ClientConsumerInternal consReceiveOneAndHold = (ClientConsumerInternal)sessionB.createConsumer(ADDRESS);

         final CountDownLatch latchReceived = new CountDownLatch(2);

         final CountDownLatch latchDone = new CountDownLatch(1);

         // It can't close the session while the large message is being read
         final CountDownLatch latchRead = new CountDownLatch(1);

         // It should receive two messages and then give up
         class LocalHandler implements MessageHandler
         {
            boolean failed = false;

            int count = 0;

            /* (non-Javadoc)
             * @see org.hornetq.api.core.client.MessageHandler#onMessage(org.hornetq.api.core.client.ClientMessage)
             */
            public synchronized void onMessage(final ClientMessage message)
            {
               try
               {
                  String str = getTextMessage(message);

                  failed = failed || !str.equals("Msg" + count);

                  message.acknowledge();
                  latchReceived.countDown();

                  if (count++ == 1)
                  {
                     // it will hold here for a while
                     if (!latchDone.await(TIMEOUT, TimeUnit.SECONDS)) // a timed wait, so if the test fails, one less
                     // thread around
                     {
                        new Exception("ClientConsuemrWindowSizeTest Handler couldn't receive signal in less than 5 seconds").printStackTrace();
                        failed = true;
                     }

                     if (largeMessages)
                     {
                        message.getBodyBuffer().readBytes(new byte[600]);
                     }

                     latchRead.countDown();
                  }
               }
               catch (Exception e)
               {
                  e.printStackTrace(); // Hudson / JUnit report
                  failed = true;
               }
            }
         }

         LocalHandler handler = new LocalHandler();

         ClientConsumer cons1 = session.createConsumer(ADDRESS);

         ClientProducer prod = session.createProducer(ADDRESS);

         for (int i = 0; i < numberOfMessages; i++)
         {
            ClientMessage msg = createTextMessage(session, "Msg" + i);
            if (largeMessages)
            {
               msg.getBodyBuffer().writeBytes(new byte[600]);
            }
            prod.send(msg);
         }

         consReceiveOneAndHold.setMessageHandler(handler);

         Assert.assertTrue(latchReceived.await(TIMEOUT, TimeUnit.SECONDS));

         Assert.assertEquals(0, consReceiveOneAndHold.getBufferSize());

         for (int i = 2; i < numberOfMessages; i++)
         {
            ClientMessage msg = cons1.receive(1000);
            Assert.assertNotNull("expected message at i = " + i, msg);
            Assert.assertEquals("Msg" + i, getTextMessage(msg));
            msg.acknowledge();
         }

         Assert.assertEquals(0, consReceiveOneAndHold.getBufferSize());

         latchDone.countDown();

         // The test can' t close the session while the message is still being read, or it could interrupt the data
         Assert.assertTrue(latchRead.await(10, TimeUnit.SECONDS));

         session.close();
         session = null;

         sessionB.close();
         sessionB = null;

         Assert.assertEquals(0, getMessageCount(server, ADDRESS.toString()));

         Assert.assertFalse("MessageHandler received a failure", handler.failed);

      }
      finally
      {
         try
         {
            if (session != null)
            {
               session.close();
            }
            if (sessionB != null)
            {
               sessionB.close();
            }
         }
         catch (Exception ignored)
         {
         }

         if (server.isStarted())
         {
            server.stop();
         }
      }
   }

   public void testSlowConsumerOnMessageHandlerBufferOne() throws Exception
   {
      internalTestSlowConsumerOnMessageHandlerBufferOne(false);
   }

   private void internalTestSlowConsumerOnMessageHandlerBufferOne(final boolean largeMessage) throws Exception
   {
      HornetQServer server = createServer(false, isNetty());

      ClientSession sessionB = null;
      ClientSession session = null;

      try
      {
         final int numberOfMessages = 100;

         server.start();

         locator.setConsumerWindowSize(1);

         if (largeMessage)
         {
            locator.setMinLargeMessageSize(100);
         }

         ClientSessionFactory sf = locator.createSessionFactory();

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

         SimpleString ADDRESS = new SimpleString("some-queue");

         session.createQueue(ADDRESS, ADDRESS, true);

         sessionB = sf.createSession(false, true, true);
         sessionB.start();

         session.start();

         ClientConsumerInternal consReceiveOneAndHold = (ClientConsumerInternal)sessionB.createConsumer(ADDRESS);

         final CountDownLatch latchReceived = new CountDownLatch(2);
         final CountDownLatch latchReceivedBuffered = new CountDownLatch(3);

         final CountDownLatch latchDone = new CountDownLatch(1);

         // It should receive two messages and then give up
         class LocalHandler implements MessageHandler
         {
            boolean failed = false;

            int count = 0;

            /* (non-Javadoc)
             * @see org.hornetq.api.core.client.MessageHandler#onMessage(org.hornetq.api.core.client.ClientMessage)
             */
            public synchronized void onMessage(final ClientMessage message)
            {
               try
               {
                  log.info("received msg " + message);
                  String str = getTextMessage(message);
                  if (ConsumerWindowSizeTest.isTrace)
                  {
                     ConsumerWindowSizeTest.log.trace("Received message " + str);
                  }

                  ConsumerWindowSizeTest.log.info("Received message " + str);

                  failed = failed || !str.equals("Msg" + count);

                  message.acknowledge();
                  latchReceived.countDown();
                  latchReceivedBuffered.countDown();

                  if (count++ == 1)
                  {
                     // it will hold here for a while
                     if (!latchDone.await(TIMEOUT, TimeUnit.SECONDS))
                     {
                        new Exception("ClientConsuemrWindowSizeTest Handler couldn't receive signal in less than 5 seconds").printStackTrace();
                        failed = true;
                     }
                  }
               }
               catch (Exception e)
               {
                  e.printStackTrace(); // Hudson / JUnit report
                  failed = true;
               }
            }
         }

         LocalHandler handler = new LocalHandler();

         ClientProducer prod = session.createProducer(ADDRESS);

         for (int i = 0; i < numberOfMessages; i++)
         {
            ClientMessage msg = createTextMessage(session, "Msg" + i);
            if (largeMessage)
            {
               msg.getBodyBuffer().writeBytes(new byte[600]);
            }
            prod.send(msg);
         }

         consReceiveOneAndHold.setMessageHandler(handler);

         Assert.assertTrue(latchReceived.await(TIMEOUT, TimeUnit.SECONDS));

         log.info("bs " + consReceiveOneAndHold.getBufferSize());

         long timeout = System.currentTimeMillis() + 1000 * TIMEOUT;
         while (consReceiveOneAndHold.getBufferSize() == 0 && System.currentTimeMillis() < timeout)
         {
            log.info("bs " + consReceiveOneAndHold.getBufferSize());
            Thread.sleep(10);
         }

         Assert.assertEquals(1, consReceiveOneAndHold.getBufferSize());

         ClientConsumer cons1 = session.createConsumer(ADDRESS);

         for (int i = 3; i < numberOfMessages; i++)
         {
            ClientMessage msg = cons1.receive(1000);
            Assert.assertNotNull("expected message at i = " + i, msg);
            String text = getTextMessage(msg);
            Assert.assertEquals("Msg" + i, text);
            msg.acknowledge();
         }

         latchDone.countDown();

         Assert.assertTrue(latchReceivedBuffered.await(TIMEOUT, TimeUnit.SECONDS));

         session.close();
         session = null;

         sessionB.close();
         sessionB = null;

         Assert.assertEquals(0, getMessageCount(server, ADDRESS.toString()));

         Assert.assertFalse("MessageHandler received a failure", handler.failed);

      }
      finally
      {
         try
         {
            if (session != null)
            {
               session.close();
            }
            if (sessionB != null)
            {
               sessionB.close();
            }
         }
         catch (Exception ignored)
         {
            ignored.printStackTrace();
         }

         if (server.isStarted())
         {
            server.stop();
         }
      }
   }

   public void testNoWindowRoundRobin() throws Exception
   {
      testNoWindowRoundRobin(false);
   }

   private void testNoWindowRoundRobin(final boolean largeMessages) throws Exception
   {

      HornetQServer server = createServer(false, isNetty());

      ClientSession sessionA = null;
      ClientSession sessionB = null;

      try
      {
         final int numberOfMessages = 100;

         server.start();

         locator.setConsumerWindowSize(-1);
         if (largeMessages)
         {
            locator.setMinLargeMessageSize(100);
         }

         ClientSessionFactory sf = locator.createSessionFactory();

         sessionA = sf.createSession(false, true, true);

         SimpleString ADDRESS = new SimpleString("some-queue");

         sessionA.createQueue(ADDRESS, ADDRESS, true);

         sessionB = sf.createSession(false, true, true);

         sessionA.start();
         sessionB.start();

         ClientConsumerInternal consA = (ClientConsumerInternal)sessionA.createConsumer(ADDRESS);

         ClientConsumerInternal consB = (ClientConsumerInternal)sessionB.createConsumer(ADDRESS);

         {
            // We can only guarantee round robing with WindowSize = -1, after the ServerConsumer object received
            // SessionConsumerFlowCreditMessage(-1)
            // Since that is done asynchronously we verify that the information was received before we proceed on
            // sending messages or else the distribution won't be
            // even as expected by the test
            Bindings bindings = server.getPostOffice().getBindingsForAddress(ADDRESS);

            Assert.assertEquals(1, bindings.getBindings().size());

            for (Binding binding : bindings.getBindings())
            {
               Collection<Consumer> consumers = ((QueueBinding)binding).getQueue().getConsumers();

               for (Consumer consumer : consumers)
               {
                  ServerConsumerImpl consumerImpl = (ServerConsumerImpl)consumer;
                  long timeout = System.currentTimeMillis() + 5000;
                  while (timeout > System.currentTimeMillis() && consumerImpl.getAvailableCredits() != null)
                  {
                     Thread.sleep(10);
                  }

                  Assert.assertNull(consumerImpl.getAvailableCredits());
               }
            }
         }

         ClientProducer prod = sessionA.createProducer(ADDRESS);

         for (int i = 0; i < numberOfMessages; i++)
         {
            ClientMessage msg = createTextMessage(sessionA, "Msg" + i);
            if (largeMessages)
            {
               msg.getBodyBuffer().writeBytes(new byte[600]);
            }
            prod.send(msg);
         }

         long timeout = System.currentTimeMillis() + TIMEOUT * 1000;

         boolean foundA = false;
         boolean foundB = false;

         do
         {
            foundA = consA.getBufferSize() == numberOfMessages / 2;
            foundB = consB.getBufferSize() == numberOfMessages / 2;

            Thread.sleep(10);
         }
         while ((!foundA || !foundB) && System.currentTimeMillis() < timeout);

         Assert.assertTrue("ConsumerA didn't receive the expected number of messages on buffer (consA=" + consA.getBufferSize() +
                                    ", consB=" +
                                    consB.getBufferSize() +
                                    ") foundA = " +
                                    foundA +
                                    " foundB = " +
                                    foundB,
                           foundA);
         Assert.assertTrue("ConsumerB didn't receive the expected number of messages on buffer (consA=" + consA.getBufferSize() +
                                    ", consB=" +
                                    consB.getBufferSize() +
                                    ") foundA = " +
                                    foundA +
                                    " foundB = " +
                                    foundB,
                           foundB);

      }
      finally
      {
         try
         {
            if (sessionA != null)
            {
               sessionA.close();
            }
            if (sessionB != null)
            {
               sessionB.close();
            }
         }
         catch (Exception ignored)
         {
         }

         if (server.isStarted())
         {
            server.stop();
         }
      }
   }

}
TOP

Related Classes of org.hornetq.tests.integration.client.ConsumerWindowSizeTest$FakeOutputStream

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.