/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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.apache.activemq;

import javax.jms.*;
import javax.jms.Message;
import java.util.concurrent.CountDownLatch;

/**
 * 
 */
public class JmsSendWithAsyncCallbackTest extends TestSupport {

    private Connection connection;

    protected void setUp() throws Exception {
        super.setUp();
        connection = createConnection();
    }

    /**
     * @see junit.framework.TestCase#tearDown()
     */
    protected void tearDown() throws Exception {
        if (connection != null) {
            connection.close();
            connection = null;
        }
        super.tearDown();
    }
    

    public void testAsyncCallbackIsFaster() throws JMSException, InterruptedException {
        connection.start();

        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue(getName());

        // setup a consumer to drain messages..
        MessageConsumer consumer = session.createConsumer(queue);
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
            }
        });

        // warmup...
        for(int i=0; i < 10; i++) {
            benchmarkNonCallbackRate();
            benchmarkCallbackRate();
        }

        double callbackRate = benchmarkCallbackRate();
        double nonCallbackRate = benchmarkNonCallbackRate();

        System.out.println(String.format("AsyncCallback Send rate: %,.2f m/s", callbackRate));
        System.out.println(String.format("NonAsyncCallback Send rate: %,.2f m/s", nonCallbackRate));

        // The async style HAS to be faster than the non-async style..
        assertTrue( callbackRate/nonCallbackRate > 1.5 );
    }

    private double benchmarkNonCallbackRate() throws JMSException {
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue(getName());
        int count = 1000;
        ActiveMQMessageProducer producer = (ActiveMQMessageProducer) session.createProducer(queue);
        producer.setDeliveryMode(DeliveryMode.PERSISTENT);
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            producer.send(session.createTextMessage("Hello"));
        }
        return 1000.0 * count / (System.currentTimeMillis() - start);
    }

    private double benchmarkCallbackRate() throws JMSException, InterruptedException {
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue(getName());
        int count = 1000;
        final CountDownLatch messagesSent = new CountDownLatch(count);
        ActiveMQMessageProducer producer = (ActiveMQMessageProducer) session.createProducer(queue);
        producer.setDeliveryMode(DeliveryMode.PERSISTENT);
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            producer.send(session.createTextMessage("Hello"), new AsyncCallback() {
                @Override
                public void onSuccess() {
                    messagesSent.countDown();
                }

                @Override
                public void onException(JMSException exception) {
                    exception.printStackTrace();
                }
            });
        }
        messagesSent.await();
        return 1000.0 * count / (System.currentTimeMillis() - start);
    }

}

@@ -842,85 +842,333 @@
 java
-x.jms.*;%0Aimport javax.jms.Message;%0Aimport java.util.concurrent.CountDownLatch
+.util.concurrent.CountDownLatch;%0A%0Aimport javax.jms.Connection;%0Aimport javax.jms.DeliveryMode;%0Aimport javax.jms.JMSException;%0Aimport javax.jms.Message;%0Aimport javax.jms.MessageConsumer;%0Aimport javax.jms.MessageListener;%0Aimport javax.jms.Queue;%0Aimport javax.jms.Session;%0A%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory
 ;%0A%0A/
@@ -1172,17 +1172,16 @@
 %0A%0A/**%0A *
- 
 %0A */%0Apub
@@ -1242,16 +1242,116 @@
 port %7B%0A%0A
+    private static final Logger LOG = LoggerFactory.getLogger(JmsSendWithAsyncCallbackTest.class);%0A%0A
     priv
@@ -1746,21 +1746,16 @@
 );%0A    %7D
-%0A    
 %0A%0A    pu
@@ -2551,34 +2551,24 @@
         
-System.out.println
+LOG.info
 (String.
@@ -2640,26 +2640,16 @@
     
-System.out.println
+LOG.info
 (Str
@@ -4570,11 +4570,10 @@
 ;%0A    %7D%0A
-%0A
 %7D%0A

Remove the System.out lines from the test, use LOG instead.