summaryrefslogtreecommitdiff
path: root/qpid
diff options
context:
space:
mode:
authorMartin Ritchie <ritchiem@apache.org>2007-02-02 15:28:08 +0000
committerMartin Ritchie <ritchiem@apache.org>2007-02-02 15:28:08 +0000
commit7e9021835265bf6afaeb203b90e8af678593e6b3 (patch)
tree0880854c41e7290f6c58718c66601dd6ec449c60 /qpid
parenta09a5215aecde0d2080db436fc657e84145fa661 (diff)
downloadqpid-python-7e9021835265bf6afaeb203b90e8af678593e6b3.tar.gz
Handpatched branch
Revision: 502576 Author: ritchiem Date: 11:13:13, 02 February 2007 Message: QPID-343 Performance test suite doesn't output missing message count on failure. Updated PingAsyncTestPerf to output missing messsage count. Updated PingPongProducer so it doesn't use AMQShortStringx. ---- Modified : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java Modified : /incubator/qpid/trunk/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java Revision: 502271 Author: ritchiem Date: 16:36:54, 01 February 2007 Message: QPID-341 When using Queues and Topics defined via JNDI settings are not preserved. Removed extraction of destination/queue name and used BindingURL directly to create Destination. ---- Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java Revision: 502268 Author: ritchiem Date: 16:32:56, 01 February 2007 Message: Increased logging on a failure to attain state ---- Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java Revision: 502261 Author: ritchiem Date: 16:25:57, 01 February 2007 Message: QPID-339 DispatcherTest.java was broker now it actually tests correctly. Added test to Check changing message listeners ---- Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java Modified : /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java Added : /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java Revision: 502253 Author: ritchiem Date: 16:01:14, 01 February 2007 Message: QPID-339 Java client hangs when starting up (intermittently) Patched the problem where the dispatcher would hang. The previous logic was flawed. Patch worked on by Robert Godfrey and Martin Ritchie. Added test to ensure that the connection is not automatically started. (Only added the test last time by mistake. This is the actual fix) With a test for the DispatcherTest ---- Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java Added : /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java Revision: 502249 Author: ritchiem Date: 15:50:52, 01 February 2007 Message: QPID-330 Clients occasionally fail to notice connect The AMQConnection.java constructor now deals with the full connection process. The failover thread should not be started. This allows the connection method to be simplified and not Thread.sleep waiting for the connection. ---- Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java Revision: 502248 Author: ritchiem Date: 15:47:17, 01 February 2007 Message: QPID-339 Java client hangs when starting up (intermittently) Patched the problem where the dispatcher would hang. The previous logic was flawed. Patch worked on by Robert Godfrey and Martin Ritchie. Added test to ensure that the connection is not automatically started. ---- Added : /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java Revision: 502182 Author: rgreig Date: 10:18:36, 01 February 2007 Message: (Submitted by Rupert Smith) Added comments as a reminder of improvements to be made to the tests. ---- Modified : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java Revision: 502179 Author: rgreig Date: 10:13:21, 01 February 2007 Message: (Submitted by Rupert Smith) Added comments as a reminder of improvements to be made to the tests. ---- Modified : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java Revision: 502172 Author: ritchiem Date: 09:37:39, 01 February 2007 Message: QPID-333 Committed test class rename to stop it being picked up by Surefire AMQTopic.java - whitespace ---- Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java Added : /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/message/NonQpidObjectMessage.java(Copy from path: /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/message/TestNonQpidTextMessage.java, Revision, 501823 Deleted : /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/message/TestNonQpidTextMessage.java Modified : /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java Revision: 501920 Author: ritchiem Date: 17:43:45, 31 January 2007 Message: Unused so removing ---- Deleted : /incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent Revision: 501917 Author: ritchiem Date: 17:31:04, 31 January 2007 Message: QPID-333 Message Properties on non Qpid Messages are not preserved Updated MessageConverter to have a constructor that takes a Message type. Updated MessageConverterTest to use the new NonQpidMessage to test it out. JMSHeaderAdapter.java - whitespace changes and comment noting that null return is required. ---- Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java Modified : /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java Added : /incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/NonQpidMessage.java Revision: 501804 Author: rgreig Date: 11:29:33, 31 January 2007 Message: (Patch submitted by Rupert Smith) Added a ping latency test. Uploaded new junit-toolkit snapshot for self timed tests. ---- Deleted : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.jar Deleted : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.jar.md5 Deleted : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.jar.sha1 Deleted : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.pom Deleted : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.pom.md5 Deleted : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.pom.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070131.112634-1.jar Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070131.112634-1.jar.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070131.112634-1.jar.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070131.112634-1.pom Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070131.112634-1.pom.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070131.112634-1.pom.sha1 Modified : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml Modified : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.md5 Modified : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.sha1 Modified : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml Modified : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.md5 Modified : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.sha1 Modified : /incubator/qpid/trunk/qpid/java/perftests/pom.xml Modified : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java Added : /incubator/qpid/trunk/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingLatencyTestPerf.java Revision: 501465 Author: rgreig Date: 16:53:41, 30 January 2007 Message: (Submitted by Rupert Smith) Updated the README.txt to give a fuller explanation for the creation of the temporary local maven repository. ---- Modified : /incubator/qpid/trunk/qpid/java/mvn-repo/README.txt Revision: 501457 Author: rgreig Date: 16:42:37, 30 January 2007 Message: (Submitted by Rupert Smith) Added PingClient.java which was forgotten from last commit. ---- Added : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java Revision: 501455 Author: rgreig Date: 16:40:20, 30 January 2007 Message: (Submitted by Rupert Smith) Ping tests refactored. Unused ping test classes removed. JUnit-toolkit 0.5-SNAPSHOT added to the build. ---- Added : /incubator/qpid/trunk/qpid/java/mvn-repo Added : /incubator/qpid/trunk/qpid/java/mvn-repo/README.txt Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.jar Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.jar.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.jar.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.pom Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.pom.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/junit-toolkit-0.5-20070130.111852-1.pom.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/junit-toolkit-maven-plugin-0.5-20070130.111904-1.jar Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/junit-toolkit-maven-plugin-0.5-20070130.111904-1.jar.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/junit-toolkit-maven-plugin-0.5-20070130.111904-1.jar.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/junit-toolkit-maven-plugin-0.5-20070130.111904-1.pom Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/junit-toolkit-maven-plugin-0.5-20070130.111904-1.pom.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/junit-toolkit-maven-plugin-0.5-20070130.111904-1.pom.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.sha1 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/maven-metadata.xml Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/maven-metadata.xml.md5 Added : /incubator/qpid/trunk/qpid/java/mvn-repo/uk/co/thebadgerset/maven-metadata.xml.sha1 Deleted : /incubator/qpid/trunk/qpid/java/perftests/bin Modified : /incubator/qpid/trunk/qpid/java/perftests/pom.xml Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingClient.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingProducer.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingClient.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingItself.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingProducer.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingPublisher.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingSubscriber.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/ping/Throttle.java Modified : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java Modified : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceProvidingClient.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceRequestingClient.java Modified : /incubator/qpid/trunk/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java Modified : /incubator/qpid/trunk/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingTestPerf.java Deleted : /incubator/qpid/trunk/qpid/java/perftests/src/test/java/org/apache/qpid/ping/ThrottleTestPerf.java Modified : /incubator/qpid/trunk/qpid/java/perftests/src/test/java/org/apache/qpid/requestreply/PingPongTestPerf.java Modified : /incubator/qpid/trunk/qpid/java/pom.xml Revision: 501096 Author: rgreig Date: 16:37:13, 29 January 2007 Message: QPID-327 : Patch supplied by Rob Godfrey - [race condition] PoolingFilter : Possible race condition when completing a Job ---- Modified : /incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java Modified : /incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java Modified : /incubator/qpid/trunk/qpid/java/client/src/old_test/java/org/apache/qpid/mina/AcceptorTest.java Modified : /incubator/qpid/trunk/qpid/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java Modified : /incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java Modified : /incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java Modified : /incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java Modified : /incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java Modified : /incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java Modified : /incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java Modified : /incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/session/TestSession.java Modified : /incubator/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/ack/TxAckTest.java Modified : /incubator/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java Modified : /incubator/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java Modified : /incubator/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/AckTest.java Modified : /incubator/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MessageTestHelper.java Modified : /incubator/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java Modified : /incubator/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SkeletonMessageStore.java Modified : /incubator/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/store/TestReferenceCounting.java Revision: 501011 Author: rgreig Date: 11:13:23, 29 January 2007 Message: QPID-313 : Patch supplied by Rob Godfrey - Call to attainState in makeBrokerConnection can miss the notification of state change. ---- Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java Revision: 501010 Author: rgreig Date: 11:11:29, 29 January 2007 Message: QPID-322 : Patch supplied by Rob Godfrey - Message reference count not being incremented when message added to UnacknowledgeMap ---- Modified : /incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java Revision: 501004 Author: rgreig Date: 11:02:57, 29 January 2007 Message: QPID-320 : Patch supplied by Rob Godfrey - Simplify logic to deal with setting MessageListener only after connection start has been called ---- Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java Modified : /incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java Revision: 500284 Author: ritchiem Date: 17:02:58, 26 January 2007 Message: Updated script details and added guard for trafficlight being null. ---- Modified : /incubator/qpid/trunk/qpid/java/perftests/pom.xml Modified : /incubator/qpid/trunk/qpid/java/perftests/src/main/java/perftests.log4j Modified : /incubator/qpid/trunk/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/perftesting@502624 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid')
-rw-r--r--qpid/java/AppliedPatches.txt40
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java29
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java16
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java40
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java4
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java409
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java105
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java4
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java27
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java13
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java14
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java63
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java2
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java2
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java258
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/client/message/NonQpidObjectMessage.java (renamed from qpid/java/client/src/test/java/org/apache/qpid/client/message/TestNonQpidTextMessage.java)4
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java173
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java5
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java92
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/NonQpidMessage.java410
-rw-r--r--qpid/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java2
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java11
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java31
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java32
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java55
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java34
-rw-r--r--qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java14
-rw-r--r--qpid/java/common/src/test/java/org/apache/qpid/session/TestSession.java22
-rw-r--r--qpid/java/mvn-repo/README.txt4
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml4
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.md52
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.sha12
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml2
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.md52
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.sha12
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml4
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.md52
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.sha12
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml2
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.md52
-rw-r--r--qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.sha12
-rw-r--r--qpid/java/perftests/pom.xml147
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingClient.java204
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingProducer.java523
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java90
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingClient.java192
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingItself.java223
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingProducer.java249
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingPublisher.java197
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingSubscriber.java134
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/Throttle.java67
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java206
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java1175
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceProvidingClient.java235
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceRequestingClient.java428
-rw-r--r--qpid/java/perftests/src/main/java/perftests.log4j8
-rw-r--r--qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java432
-rw-r--r--qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingLatencyTestPerf.java317
-rw-r--r--qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingTestPerf.java332
-rw-r--r--qpid/java/perftests/src/test/java/org/apache/qpid/ping/ThrottleTestPerf.java63
-rw-r--r--qpid/java/perftests/src/test/java/org/apache/qpid/requestreply/PingPongTestPerf.java301
-rw-r--r--qpid/java/pom.xml2
63 files changed, 3342 insertions, 4129 deletions
diff --git a/qpid/java/AppliedPatches.txt b/qpid/java/AppliedPatches.txt
index 86f9cb4e50..e9284f6d28 100644
--- a/qpid/java/AppliedPatches.txt
+++ b/qpid/java/AppliedPatches.txt
@@ -1,10 +1,26 @@
-Notes-
Update includes local fix for AMQQueueMBeanTest.getQueueDepth resolved by r501003
+ - Hard coded to return 0
-Latest Revision-
-499979
+502576.499979
-Not Done-
+
+502269 MNGMNT lets user copy and paste host details
+502180 QPID-331 MNGMENT setting default values on parameters
+502178 Virtual host string corrected.
+501945 QPID-332 patch
+501914 QPID-334 WeakReferenceMessageHandle bug.
+501412 MNGMNT fixed null pointer if there are no messges in the queue.
+501411 MNGMNT clearing the subscribed noticication map on unsubscribe
+501009 QPID-320 Imporve performance by remembering protocol version
+501008 QPID-324 change sending of destination to byte representing T/Q/Other
+501007 QPID-322 Test may habg isntead of fail of messages doesn't get through
+501005 QPID-324 change sending of destination to byte representing T/Q/Other
+501003 QPID-320 Imporve performance by remembering protocol version
+500310 Patch to TransactedTest to clean up messages
+500264 Change to Transacted Test
499874 QPID-319 management console update (QPID-50)
499851 QPID-318 removed hard coding (New Feature)
499628 QPID-318 removed hard coding (New Feature)
@@ -50,6 +66,28 @@ Update includes local fix for AMQQueueMBeanTest.getQueueDepth resolved by r50100
494650 QPID-268 Improvements to performance of generated code
-Done-
+502576 QPID-343 performacne test suite doesn't output missing message count
+502271 QPID-341 When using Queues and Topics via JNDI properties not maintained.
+502268 Increased logging on StateManager
+502261 QPID-339 DispatcherTest was failing ..
+502253 QPID-339 Client hangs when starting
+502249 QPID-330 Client occasionally fails to notice connect
+502248 QPID-339 Client hangs when starting
+502182 comments for the remained of changes to be made to tests
+502179 comments for the remained of changes to be made to tests
+502172 QPID-333 class rename
+501920 removed unused classes
+501917 QPID-333 Messsage Properties in MessageConverter lost on jms.Message-s
+501804 added ping latency test
+501465 Updated readme for local temp mvn repo
+501457 added pingclient
+501455 ping tests refactored
+501096 QPID-327 Pooling Filter Race condition
+501011 QPID-313 attain state in makeBrokerConenection missing state change.
+501010 QPID-322 Message reference count not incremented when added to unackMap.
+501004 QPID-320 Simplify MessageListener setup
+500284 Updated script details and added guard for traffic light being null
+-
499979 QPID-315 Test classes to reproduce missing correlation id
499975 QPID-315 Moved message converstion to MessageConverter.
499781 Fixed race that caused duplicate date in log file
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
index ffd25de0b4..3c4b4f8718 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
@@ -60,7 +60,6 @@ import java.util.StringTokenizer;
/**
* Main entry point for AMQPD.
- *
*/
public class Main implements ProtocolVersionList, Managable
{
@@ -119,10 +118,10 @@ public class Main implements ProtocolVersionList, Managable
Option bind = OptionBuilder.withArgName("bind").hasArg().withDescription("bind to the specified address. Overrides any value in the config file").
withLongOpt("bind").create("b");
Option logconfig = OptionBuilder.withArgName("logconfig").hasArg().withDescription("use the specified log4j xml configuration file. By " +
- "default looks for a file named " + DEFAULT_LOG_CONFIG_FILENAME + " in the same directory as the configuration file").
+ "default looks for a file named " + DEFAULT_LOG_CONFIG_FILENAME + " in the same directory as the configuration file").
withLongOpt("logconfig").create("l");
Option logwatchconfig = OptionBuilder.withArgName("logwatch").hasArg().withDescription("monitor the log file configuration file for changes. Units are seconds. " +
- "Zero means do not check for changes.").withLongOpt("logwatch").create("w");
+ "Zero means do not check for changes.").withLongOpt("logwatch").create("w");
options.addOption(help);
options.addOption(version);
@@ -146,10 +145,12 @@ public class Main implements ProtocolVersionList, Managable
{
String ver = "Qpid 0.9.0.0";
String protocol = "AMQP version(s) [major.minor]: ";
- for (int i=0; i<pv.length; i++)
+ for (int i = 0; i < pv.length; i++)
{
if (i > 0)
+ {
protocol += ", ";
+ }
protocol += pv[i][PROTOCOL_MAJOR] + "." + pv[i][PROTOCOL_MINOR];
}
System.out.println(ver + " (" + protocol + ")");
@@ -255,12 +256,12 @@ public class Main implements ProtocolVersionList, Managable
int totalVHosts = ((Collection) virtualHosts).size();
for (int vhost = 0; vhost < totalVHosts; vhost++)
{
- setupVirtualHosts(configFile.getParent() , (String)((List)virtualHosts).get(vhost));
+ setupVirtualHosts(configFile.getParent(), (String) ((List) virtualHosts).get(vhost));
}
}
else
{
- setupVirtualHosts(configFile.getParent() , (String)virtualHosts);
+ setupVirtualHosts(configFile.getParent(), (String) virtualHosts);
}
}
bind(port, connectorConfig);
@@ -277,7 +278,7 @@ public class Main implements ProtocolVersionList, Managable
configFilePath = configFileParent + configFilePath.substring(configVar.length());
}
- if (configFilePath.indexOf(".xml") != -1 )
+ if (configFilePath.indexOf(".xml") != -1)
{
VirtualHostConfiguration vHostConfig = new VirtualHostConfiguration(configFilePath);
vHostConfig.performBindings();
@@ -290,11 +291,11 @@ public class Main implements ProtocolVersionList, Managable
String[] fileNames = virtualHostDir.list();
- for (int each=0; each < fileNames.length; each++)
+ for (int each = 0; each < fileNames.length; each++)
{
if (fileNames[each].endsWith(".xml"))
{
- VirtualHostConfiguration vHostConfig = new VirtualHostConfiguration(configFilePath+"/"+fileNames[each]);
+ VirtualHostConfiguration vHostConfig = new VirtualHostConfiguration(configFilePath + "/" + fileNames[each]);
vHostConfig.performBindings();
}
}
@@ -324,7 +325,7 @@ public class Main implements ProtocolVersionList, Managable
// implementation provided by MINA
if (connectorConfig.enableExecutorPool)
{
- sconfig.setThreadModel(new ReadWriteThreadModel());
+ sconfig.setThreadModel(ReadWriteThreadModel.getInstance());
}
if (connectorConfig.enableNonSSL)
@@ -405,7 +406,7 @@ public class Main implements ProtocolVersionList, Managable
catch (NumberFormatException e)
{
System.err.println("Log watch configuration value of " + logWatchConfig + " is invalid. Must be " +
- "a non-negative integer. Using default of zero (no watching configured");
+ "a non-negative integer. Using default of zero (no watching configured");
}
if (logConfigFile.exists() && logConfigFile.canRead())
{
@@ -413,7 +414,7 @@ public class Main implements ProtocolVersionList, Managable
if (logWatchTime > 0)
{
System.out.println("log file " + logConfigFile.getAbsolutePath() + " will be checked for changes every " +
- logWatchTime + " seconds");
+ logWatchTime + " seconds");
// log4j expects the watch interval in milliseconds
DOMConfigurator.configureAndWatch(logConfigFile.getAbsolutePath(), logWatchTime * 1000);
}
@@ -439,12 +440,12 @@ public class Main implements ProtocolVersionList, Managable
}
catch (JMException ex)
{
- throw new AMQException("Exception occured in creating AMQBrokerManager MBean");
+ throw new AMQException("Exception occured in creating AMQBrokerManager MBean");
}
}
public ManagedObject getManagedObject()
{
return _mbean;
- }
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java
index 0eff5a3cca..6f72239555 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java
@@ -30,13 +30,14 @@ public class UnacknowledgedMessage
public final String consumerTag;
public final long deliveryTag;
public AMQQueue queue;
-
+
public UnacknowledgedMessage(AMQQueue queue, AMQMessage message, String consumerTag, long deliveryTag)
{
this.queue = queue;
this.message = message;
this.consumerTag = consumerTag;
this.deliveryTag = deliveryTag;
+ message.incrementReference();
}
public void discard() throws AMQException
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
index 831117d2c6..89807fb043 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
@@ -23,9 +23,11 @@ package org.apache.qpid.server.protocol;
import org.apache.log4j.Logger;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoServiceConfig;
import org.apache.mina.transport.vmpipe.VmPipeAddress;
import org.apache.qpid.AMQChannelException;
import org.apache.qpid.AMQException;
+import org.apache.qpid.pool.ReadWriteThreadModel;
import org.apache.qpid.framing.AMQDataBlock;
import org.apache.qpid.framing.ProtocolInitiation;
import org.apache.qpid.framing.ConnectionStartBody;
@@ -123,6 +125,20 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
_codecFactory = codecFactory;
_managedObject = createMBean();
_managedObject.register();
+
+ try
+ {
+ IoServiceConfig config = session.getServiceConfig();
+ ReadWriteThreadModel threadModel = (ReadWriteThreadModel) config.getThreadModel();
+ threadModel.getAsynchronousReadFilter().createNewJobForSession(session);
+ threadModel.getAsynchronousWriteFilter().createNewJobForSession(session);
+ }
+ catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ // throw e;
+
+ }
}
private AMQProtocolSessionMBean createMBean() throws AMQException
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
index 7903ef4d10..3379b092ae 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
@@ -209,12 +209,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
Exception lastException = new Exception();
lastException.initCause(new ConnectException());
- while (lastException != null && checkException(lastException) && _failoverPolicy.failoverAllowed())
+ while (!_connected && _failoverPolicy.failoverAllowed())
{
try
{
makeBrokerConnection(_failoverPolicy.getNextBrokerDetails());
lastException = null;
+ _connected = true;
}
catch (Exception e)
{
@@ -226,35 +227,9 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
_logger.debug("Are we connected:" + _connected);
- // Then the Failover Thread will handle conneciton
- if (_failoverPolicy.failoverAllowed())
- {
- //TODO this needs to be redone so that we are not spinning.
- // A suitable object should be set that is then waited on
- // and only notified when a connection is made or when
- // the AMQConnection gets closed.
- while (!_connected && !_closed.get())
- {
- try
- {
- _logger.debug("Sleeping.");
- Thread.sleep(100);
- }
- catch (InterruptedException ie)
- {
- _logger.debug("Woken up.");
- }
- }
- if (!_failoverPolicy.failoverAllowed() || _failoverPolicy.getCurrentBrokerDetails() == null)
- {
- if (_lastAMQException != null)
- {
- throw _lastAMQException;
- }
- }
- }
- else
+ if (!_connected)
{
+
String message = null;
if (lastException != null)
@@ -275,7 +250,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
AMQException e = new AMQConnectionFailureException(message);
-
+
if (lastException != null)
{
if (lastException instanceof UnresolvedAddressException)
@@ -792,6 +767,11 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
return _protocolHandler;
}
+
+ public boolean started()
+ {
+ return _started;
+ }
public void bytesSent(long writtenBytes)
{
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
index b2d2d2bec3..e9791d7126 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
@@ -334,7 +334,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
if (addr != null)
{
- return new AMQQueue(new AMQBindingURL((String) addr.getContent()).getQueueName());
+ return new AMQQueue(new AMQBindingURL((String) addr.getContent()));
}
}
@@ -344,7 +344,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
if (addr != null)
{
- return new AMQTopic(new AMQBindingURL((String) addr.getContent()).getDestinationName());
+ return new AMQTopic(new AMQBindingURL((String) addr.getContent()));
}
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
index 394f356b77..ff7bf4fd26 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
@@ -70,6 +70,8 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
private int _defaultPrefetchHighMark = DEFAULT_PREFETCH_HIGH_MARK;
private int _defaultPrefetchLowMark = DEFAULT_PREFETCH_LOW_MARK;
+ private AtomicBoolean _startedAtLeastOnce = new AtomicBoolean(false);
+
/**
* Used to reference durable subscribers so they requests for unsubscribe can be handled
* correctly. Note this only keeps a record of subscriptions which have been created
@@ -92,8 +94,6 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
*/
private final FlowControllingBlockingQueue _queue;
- private final java.util.Queue<MessageConsumerPair> _reprocessQueue;
-
private Dispatcher _dispatcher;
private MessageFactoryRegistry _messageFactoryRegistry;
@@ -136,37 +136,14 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
private long _nextProducerId;
/**
- * Track the 'stopped' state of the dispatcher, a session starts in the stopped state.
- */
- private volatile AtomicBoolean _stopped = new AtomicBoolean(true);
-
- /**
- * Used to signal 'pausing' the dispatcher when setting a message listener on a consumer
- */
- private final AtomicBoolean _pausing = new AtomicBoolean(false);
-
- /**
- * Used to signal 'pausing' the dispatcher when setting a message listener on a consumer
- */
- private final AtomicBoolean _paused = new AtomicBoolean(false);
-
- /**
* Set when recover is called. This is to handle the case where recover() is called by application code
* during onMessage() processing. We need to make sure we do not send an auto ack if recover was called.
*/
private boolean _inRecovery;
- public void doDispatcherTask(DispatcherCallback dispatcherCallback)
- {
- synchronized (this)
- {
- _dispatcher.pause();
+ private boolean _connectionStopped;
- dispatcherCallback.whilePaused(_reprocessQueue);
-
- _dispatcher.reprocess();
- }
- }
+ private boolean _hasMessageListeners;
/**
@@ -174,7 +151,12 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
*/
private class Dispatcher extends Thread
{
- private final Logger _logger = Logger.getLogger(Dispatcher.class);
+ /**
+ * Track the 'stopped' state of the dispatcher, a session starts in the stopped state.
+ */
+ private final AtomicBoolean _closed = new AtomicBoolean(false);
+
+ private final Object _lock = new Object();
public Dispatcher()
{
@@ -183,105 +165,54 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public void run()
{
- _stopped.set(false);
- while (!_stopped.get())
+ UnprocessedMessage message;
+
+ try
{
- if (_pausing.get())
+ while (!_closed.get() && (message = (UnprocessedMessage) _queue.take()) != null)
{
- try
+ synchronized (_lock)
{
- //Wait for unpausing
- synchronized (_pausing)
+
+ while (connectionStopped())
{
- synchronized (_paused)
- {
- _paused.notify();
- }
-
- _logger.info("dispatcher paused");
-
- _pausing.wait();
- _logger.info("dispatcher notified");
+ _lock.wait();
}
- }
- catch (InterruptedException e)
- {
- //do nothing... occurs when a pause request occurs will already
- // be here if another pause event is pending
- _logger.info("dispacher interrupted");
- }
-
- doReDispatch();
+ dispatchMessage(message);
- }
- else
- {
- doNormalDispatch();
- }
- }
+ while (connectionStopped())
+ {
+ _lock.wait();
+ }
- _logger.info("Dispatcher thread terminating for channel " + _channelId);
- }
+ }
- private void doNormalDispatch()
- {
- UnprocessedMessage message;
- try
- {
- while (!_stopped.get() && !_pausing.get() && (message = (UnprocessedMessage) _queue.take()) != null)
- {
- dispatchMessage(message);
}
}
catch (InterruptedException e)
{
- _logger.info("dispatcher normal dispatch interrupted");
+ ;
}
-
+ _logger.info("Dispatcher thread terminating for channel " + _channelId);
}
- private void doReDispatch()
+ // only call while holding lock
+ final boolean connectionStopped()
{
- _logger.info("doRedispatching");
-
- MessageConsumerPair messageConsumerPair;
-
- if (_reprocessQueue != null)
- {
- _logger.info("Reprocess Queue has size:" + _reprocessQueue.size());
- while (!_stopped.get() && ((messageConsumerPair = _reprocessQueue.poll()) != null))
- {
- reDispatchMessage(messageConsumerPair);
- }
- }
-
- if (_reprocessQueue == null || _reprocessQueue.isEmpty())
- {
- _logger.info("Reprocess Queue emptied");
- _pausing.set(false);
- }
- else
- {
- _logger.info("Reprocess Queue still contains contains:" + _reprocessQueue.size());
- }
-
+ return _connectionStopped;
}
- private void reDispatchMessage(MessageConsumerPair consumerPair)
+ void setConnectionStopped(boolean connectionStopped)
{
- if (consumerPair.getItem() instanceof AbstractJMSMessage)
+ synchronized (_lock)
{
- _logger.info("do renotify:" + consumerPair.getItem());
- consumerPair.getConsumer().notifyMessage((AbstractJMSMessage) consumerPair.getItem(), _channelId);
+ _connectionStopped = connectionStopped;
+ _lock.notify();
}
-
- // BasicMessageConsumer.notifyError(Throwable cause)
- // will put the cause in to the list which could come out here... need to watch this.
}
-
private void dispatchMessage(UnprocessedMessage message)
{
if (message.deliverBody != null)
@@ -337,40 +268,13 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
}
}
- public void stopDispatcher()
+ public void close()
{
- _stopped.set(true);
- interrupt();
- }
-
- public void pause()
- {
- _logger.info("pausing");
- _pausing.set(true);
-
-
+ _closed.set(true);
interrupt();
- synchronized (_paused)
- {
- try
- {
- _paused.wait();
- }
- catch (InterruptedException e)
- {
- //do nothing
- }
- }
- }
+ //fixme awaitTermination
- public void reprocess()
- {
- synchronized (_pausing)
- {
- _logger.info("reprocessing");
- _pausing.notify();
- }
}
}
@@ -404,8 +308,6 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
_defaultPrefetchHighMark = defaultPrefetchHighMark;
_defaultPrefetchLowMark = defaultPrefetchLowMark;
- _reprocessQueue = new ConcurrentLinkedQueue<MessageConsumerPair>();
-
if (_acknowledgeMode == NO_ACKNOWLEDGE)
{
_queue = new FlowControllingBlockingQueue(_defaultPrefetchHighMark, _defaultPrefetchLowMark,
@@ -458,7 +360,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public BytesMessage createBytesMessage() throws JMSException
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
checkNotClosed();
try
@@ -474,7 +376,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public MapMessage createMapMessage() throws JMSException
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
checkNotClosed();
try
@@ -490,7 +392,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public javax.jms.Message createMessage() throws JMSException
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
checkNotClosed();
try
@@ -506,7 +408,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public ObjectMessage createObjectMessage() throws JMSException
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
checkNotClosed();
try
@@ -522,7 +424,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public ObjectMessage createObjectMessage(Serializable object) throws JMSException
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
checkNotClosed();
try
@@ -540,7 +442,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public StreamMessage createStreamMessage() throws JMSException
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
checkNotClosed();
@@ -557,7 +459,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public TextMessage createTextMessage() throws JMSException
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
checkNotClosed();
@@ -574,7 +476,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public TextMessage createTextMessage(String text) throws JMSException
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
checkNotClosed();
try
@@ -619,7 +521,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
- _connection.getProtocolHandler().syncWrite(TxCommitBody.createAMQFrame(_channelId, (byte)8, (byte)0), TxCommitOkBody.class);
+ _connection.getProtocolHandler().syncWrite(TxCommitBody.createAMQFrame(_channelId, (byte) 8, (byte) 0), TxCommitOkBody.class);
}
catch (AMQException e)
{
@@ -638,7 +540,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
_connection.getProtocolHandler().syncWrite(
- TxRollbackBody.createAMQFrame(_channelId, (byte)8, (byte)0), TxRollbackOkBody.class);
+ TxRollbackBody.createAMQFrame(_channelId, (byte) 8, (byte) 0), TxRollbackOkBody.class);
}
catch (AMQException e)
{
@@ -650,7 +552,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
{
// We must close down all producers and consumers in an orderly fashion. This is the only method
// that can be called from a different thread of control from the one controlling the session
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
//Ensure we only try and close an open session.
if (!_closed.getAndSet(true))
@@ -661,15 +563,15 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
try
{
_connection.getProtocolHandler().closeSession(this);
- // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
- // TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
- // Be aware of possible changes to parameter order as versions change.
+ // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
+ // TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
+ // Be aware of possible changes to parameter order as versions change.
final AMQFrame frame = ChannelCloseBody.createAMQFrame(getChannelId(),
- (byte)8, (byte)0, // AMQP version (major, minor)
- 0, // classId
- 0, // methodId
- AMQConstant.REPLY_SUCCESS.getCode(), // replyCode
- "JMS client closing channel"); // replyText
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ 0, // classId
+ 0, // methodId
+ AMQConstant.REPLY_SUCCESS.getCode(), // replyCode
+ "JMS client closing channel"); // replyText
_connection.getProtocolHandler().syncWrite(frame, ChannelCloseOkBody.class);
// When control resumes at this point, a reply will have been received that
// indicates the broker has closed the channel successfully
@@ -722,7 +624,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
*/
public void closed(Throwable e)
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
// An AMQException has an error code and message already and will be passed in when closure occurs as a
// result of a channel close request
@@ -803,7 +705,8 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
{
if (_dispatcher != null)
{
- _dispatcher.stopDispatcher();
+ _dispatcher.close();
+ _dispatcher = null;
}
// we need to clone the list of consumers since the close() method updates the _consumers collection
// which would result in a concurrent modification exception
@@ -829,7 +732,8 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
{
if (_dispatcher != null)
{
- _dispatcher.stopDispatcher();
+ _dispatcher.close();
+ _dispatcher = null;
}
// we need to clone the list of consumers since the close() method updates the _consumers collection
// which would result in a concurrent modification exception
@@ -863,8 +767,8 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
_connection.getProtocolHandler().writeFrame(BasicRecoverBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- false)); // requeue
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ false)); // requeue
}
boolean isInRecovery()
@@ -1035,8 +939,8 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
}
public MessageConsumer createBrowserConsumer(Destination destination,
- String messageSelector,
- boolean noLocal)
+ String messageSelector,
+ boolean noLocal)
throws JMSException
{
checkValidDestination(destination);
@@ -1149,7 +1053,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
throw ex;
}
- synchronized(destination)
+ synchronized (destination)
{
_destinationConsumerCount.putIfAbsent(destination, new AtomicInteger());
_destinationConsumerCount.get(destination).incrementAndGet();
@@ -1200,16 +1104,16 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame frame = ExchangeDeclareBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- null, // arguments
- false, // autoDelete
- false, // durable
- name, // exchange
- false, // internal
- false, // nowait
- false, // passive
- 0, // ticket
- type); // type
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ null, // arguments
+ false, // autoDelete
+ false, // durable
+ name, // exchange
+ false, // internal
+ false, // nowait
+ false, // passive
+ 0, // ticket
+ type); // type
_connection.getProtocolHandler().syncWrite(frame, ExchangeDeclareOkBody.class);
}
@@ -1224,16 +1128,16 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame exchangeDeclare = ExchangeDeclareBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- null, // arguments
- false, // autoDelete
- false, // durable
- name, // exchange
- false, // internal
- true, // nowait
- false, // passive
- 0, // ticket
- type); // type
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ null, // arguments
+ false, // autoDelete
+ false, // durable
+ name, // exchange
+ false, // internal
+ true, // nowait
+ false, // passive
+ 0, // ticket
+ type); // type
protocolHandler.writeFrame(exchangeDeclare);
}
@@ -1259,15 +1163,15 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame queueDeclare = QueueDeclareBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- null, // arguments
- amqd.isAutoDelete(), // autoDelete
- amqd.isDurable(), // durable
- amqd.isExclusive(), // exclusive
- true, // nowait
- false, // passive
- amqd.getQueueName(), // queue
- 0); // ticket
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ null, // arguments
+ amqd.isAutoDelete(), // autoDelete
+ amqd.isDurable(), // durable
+ amqd.isExclusive(), // exclusive
+ true, // nowait
+ false, // passive
+ amqd.getQueueName(), // queue
+ 0); // ticket
protocolHandler.writeFrame(queueDeclare);
return amqd.getQueueName();
@@ -1279,13 +1183,13 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame queueBind = QueueBindBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- ft, // arguments
- amqd.getExchangeName(), // exchange
- true, // nowait
- queueName, // queue
- amqd.getRoutingKey(), // routingKey
- 0); // ticket
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ ft, // arguments
+ amqd.getExchangeName(), // exchange
+ true, // nowait
+ queueName, // queue
+ amqd.getRoutingKey(), // routingKey
+ 0); // ticket
protocolHandler.writeFrame(queueBind);
}
@@ -1308,11 +1212,11 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
{
arguments.put(AMQPFilterTypes.JMS_SELECTOR.getValue(), messageSelector);
}
- if(consumer.isAutoClose())
+ if (consumer.isAutoClose())
{
arguments.put(AMQPFilterTypes.AUTO_CLOSE.getValue(), Boolean.TRUE);
}
- if(consumer.isNoConsume())
+ if (consumer.isNoConsume())
{
arguments.put(AMQPFilterTypes.NO_CONSUME.getValue(), Boolean.TRUE);
}
@@ -1327,15 +1231,15 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame jmsConsume = BasicConsumeBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- arguments, // arguments
- tag, // consumerTag
- consumer.isExclusive(), // exclusive
- consumer.getAcknowledgeMode() == Session.NO_ACKNOWLEDGE, // noAck
- consumer.isNoLocal(), // noLocal
- nowait, // nowait
- queueName, // queue
- 0); // ticket
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ arguments, // arguments
+ tag, // consumerTag
+ consumer.isExclusive(), // exclusive
+ consumer.getAcknowledgeMode() == Session.NO_ACKNOWLEDGE, // noAck
+ consumer.isNoLocal(), // noLocal
+ nowait, // nowait
+ queueName, // queue
+ 0); // ticket
if (nowait)
{
protocolHandler.writeFrame(jmsConsume);
@@ -1516,12 +1420,12 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame queueDeleteFrame = QueueDeleteBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- false, // ifEmpty
- false, // ifUnused
- true, // nowait
- queueName, // queue
- 0); // ticket
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ false, // ifEmpty
+ false, // ifUnused
+ true, // nowait
+ queueName, // queue
+ 0); // ticket
_connection.getProtocolHandler().syncWrite(queueDeleteFrame, QueueDeleteOkBody.class);
}
catch (AMQException e)
@@ -1561,7 +1465,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
{
checkNotClosed();
checkValidQueue(queue);
- return new AMQQueueBrowser(this, (AMQQueue) queue,messageSelector);
+ return new AMQQueueBrowser(this, (AMQQueue) queue, messageSelector);
}
public TemporaryQueue createTemporaryQueue() throws JMSException
@@ -1611,10 +1515,10 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame boundFrame = ExchangeBoundBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- ExchangeDefaults.TOPIC_EXCHANGE_NAME, // exchange
- queueName, // queue
- routingKey); // routingKey
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ ExchangeDefaults.TOPIC_EXCHANGE_NAME, // exchange
+ queueName, // queue
+ routingKey); // routingKey
AMQMethodEvent response = null;
try
{
@@ -1675,9 +1579,9 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
final AMQFrame ackFrame = BasicAckBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- deliveryTag, // deliveryTag
- multiple); // multiple
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ deliveryTag, // deliveryTag
+ multiple); // multiple
if (_logger.isDebugEnabled())
{
_logger.debug("Sending ack for delivery tag " + deliveryTag + " on channel " + _channelId);
@@ -1707,28 +1611,55 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
void start()
{
- if (_dispatcher != null)
+ //fixme This should be controlled by _stopped as it pairs with the stop method
+ //fixme or check the FlowControlledBlockingQueue _queue to see if we have flow controlled.
+ //will result in sending Flow messages for each subsequent call to flow.. only need to do this
+ // if we have called stop.
+ if (_startedAtLeastOnce.getAndSet(true))
{
//then we stopped this and are restarting, so signal server to resume delivery
unsuspendChannel();
}
- _dispatcher = new Dispatcher();
- _dispatcher.setDaemon(true);
- _dispatcher.start();
+
+ if (hasMessageListeners())
+ {
+ startDistpatcherIfNecessary();
+ }
}
- void stop()
+ private boolean hasMessageListeners()
{
- //stop the server delivering messages to this session
- suspendChannel();
+ return _hasMessageListeners;
+ }
- //stop the dispatcher thread
- _stopped.set(true);
+ void setHasMessageListeners()
+ {
+ _hasMessageListeners = true;
}
- boolean isStopped()
+ synchronized void startDistpatcherIfNecessary()
{
- return _stopped.get();
+ if (_dispatcher == null)
+ {
+ _dispatcher = new Dispatcher();
+ _dispatcher.setDaemon(true);
+ _dispatcher.start();
+ }
+ else
+ {
+ _dispatcher.setConnectionStopped(false);
+ }
+ }
+
+ void stop()
+ {
+ //stop the server delivering messages to this session
+ suspendChannel();
+
+ if (_dispatcher != null)
+ {
+ _dispatcher.setConnectionStopped(true);
+ }
}
/**
@@ -1775,7 +1706,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
}
Destination dest = consumer.getDestination();
- synchronized(dest)
+ synchronized (dest)
{
if (_destinationConsumerCount.get(dest).decrementAndGet() == 0)
{
@@ -1840,8 +1771,8 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame channelFlowFrame = ChannelFlowBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- false); // active
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ false); // active
_connection.getProtocolHandler().writeFrame(channelFlowFrame);
}
@@ -1852,15 +1783,15 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame channelFlowFrame = ChannelFlowBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- true); // active
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ true); // active
_connection.getProtocolHandler().writeFrame(channelFlowFrame);
}
public void confirmConsumerCancelled(String consumerTag)
{
BasicMessageConsumer consumer = (BasicMessageConsumer) _consumers.get(consumerTag);
- if((consumer != null) && (consumer.isAutoClose()))
+ if ((consumer != null) && (consumer.isAutoClose()))
{
consumer.closeWhenNoMessages(true);
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
index bdf26e6a5e..c5e57d2d1c 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
@@ -189,7 +189,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
public String getMessageSelector() throws JMSException
{
- checkPreConditions();
+ checkPreConditions();
return _messageSelector;
}
@@ -211,22 +211,27 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
public void setMessageListener(final MessageListener messageListener) throws JMSException
{
- checkPreConditions();
+ checkPreConditions();
//if the current listener is non-null and the session is not stopped, then
//it is an error to call this method.
//i.e. it is only valid to call this method if
//
- // (a) the session is stopped, in which case the dispatcher is not running
+ // (a) the connection is stopped, in which case the dispatcher is not running
// OR
// (b) the listener is null AND we are not receiving synchronously at present
//
- if (_session.isStopped())
+ if (!_session.getAMQConnection().started())
{
_messageListener.set(messageListener);
- _logger.debug("Session stopped : Message listener set for destination " + _destination);
+ _session.setHasMessageListeners();
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Session stopped : Message listener(" + messageListener + ") set for destination " + _destination);
+ }
}
else
{
@@ -247,25 +252,9 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
synchronized (_session)
{
- //Pause Dispatcher
- _session.doDispatcherTask(new DispatcherCallback(this)
- {
- public void whilePaused(Queue<MessageConsumerPair> reprocessQueue)
- {
- // Prepend messages in _synchronousQueue to dispatcher queue
- _logger.debug("ReprocessQueue current size:" + reprocessQueue.size());
- for (Object item : _synchronousQueue)
- {
- reprocessQueue.offer(new MessageConsumerPair(_consumer, item));
- }
- _logger.debug("Added items to reprocessQueue:" + reprocessQueue.size());
-
- // Set Message Listener
- _logger.debug("Set Message Listener");
- _messageListener.set(messageListener);
- }
- }
- );
+ _messageListener.set(messageListener);
+ _session.setHasMessageListeners();
+ _session.startDistpatcherIfNecessary();
}
}
}
@@ -273,7 +262,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
private void preApplicationProcessing(AbstractJMSMessage jmsMsg) throws JMSException
{
- if(_session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
+ if (_session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
{
_unacknowledgedDeliveryTags.add(jmsMsg.getDeliveryTag());
String url = jmsMsg.getStringProperty(CustomJMXProperty.JMSX_QPID_JMSDESTINATIONURL.toString());
@@ -286,7 +275,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
_logger.warn("Unable to parse the supplied destination header: " + url);
}
-
+
}
_session.setInRecovery(false);
}
@@ -347,13 +336,15 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
public Message receive(long l) throws JMSException
{
- checkPreConditions();
+ checkPreConditions();
acquireReceiving();
+ _session.startDistpatcherIfNecessary();
+
try
{
- if(closeOnAutoClose())
+ if (closeOnAutoClose())
{
return null;
}
@@ -388,7 +379,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
private boolean closeOnAutoClose() throws JMSException
{
- if(isAutoClose() && _closeWhenNoMessages && _synchronousQueue.isEmpty())
+ if (isAutoClose() && _closeWhenNoMessages && _synchronousQueue.isEmpty())
{
close(false);
return true;
@@ -401,13 +392,15 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
public Message receiveNoWait() throws JMSException
{
- checkPreConditions();
+ checkPreConditions();
acquireReceiving();
+ _session.startDistpatcherIfNecessary();
+
try
{
- if(closeOnAutoClose())
+ if (closeOnAutoClose())
{
return null;
}
@@ -463,19 +456,19 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
public void close(boolean sendClose) throws JMSException
{
- synchronized(_connection.getFailoverMutex())
+ synchronized (_connection.getFailoverMutex())
{
if (!_closed.getAndSet(true))
{
- if(sendClose)
+ if (sendClose)
{
// AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
final AMQFrame cancelFrame = BasicCancelBody.createAMQFrame(_channelId,
- (byte)8, (byte)0, // AMQP version (major, minor)
- _consumerTag, // consumerTag
- false); // nowait
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ _consumerTag, // consumerTag
+ false); // nowait
try
{
@@ -572,8 +565,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
postDeliver(jmsMessage);
}
else
- {
- //This shouldn't be possible.
+ {
_synchronousQueue.put(jmsMessage);
}
}
@@ -607,7 +599,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
private void postDeliver(AbstractJMSMessage msg) throws JMSException
{
- msg.setJMSDestination(_destination);
+ msg.setJMSDestination(_destination);
switch (_acknowledgeMode)
{
case Session.CLIENT_ACKNOWLEDGE:
@@ -691,7 +683,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
*/
private void deregisterConsumer()
{
- _session.deregisterConsumer(this);
+ _session.deregisterConsumer(this);
}
public String getConsumerTag()
@@ -704,26 +696,29 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
_consumerTag = consumerTag;
}
- public AMQSession getSession() {
- return _session;
- }
+ public AMQSession getSession()
+ {
+ return _session;
+ }
- private void checkPreConditions() throws JMSException{
+ private void checkPreConditions() throws JMSException
+ {
- this.checkNotClosed();
+ this.checkNotClosed();
- if(_session == null || _session.isClosed()){
- throw new javax.jms.IllegalStateException("Invalid Session");
- }
- }
+ if (_session == null || _session.isClosed())
+ {
+ throw new javax.jms.IllegalStateException("Invalid Session");
+ }
+ }
public void acknowledge() throws JMSException
{
- if(!isClosed())
+ if (!isClosed())
{
Iterator<Long> tags = _unacknowledgedDeliveryTags.iterator();
- while(tags.hasNext())
+ while (tags.hasNext())
{
_session.acknowledgeMessage(tags.next(), false);
tags.remove();
@@ -758,10 +753,10 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
_closeWhenNoMessages = b;
- if(_closeWhenNoMessages
- && _synchronousQueue.isEmpty()
- && _receiving.get()
- && _messageListener != null)
+ if (_closeWhenNoMessages
+ && _synchronousQueue.isEmpty()
+ && _receiving.get()
+ && _messageListener != null)
{
_receivingThread.interrupt();
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
index 74b91c3c30..a567427b26 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
@@ -389,9 +389,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
}
else
{
- //TODO; Do we really want to create an empty message here ?
- newMessage = (AbstractJMSMessage) _session.createMessage();
- return new MessageConverter(newMessage).getConvertedMessage();
+ newMessage = new MessageConverter(message).getConvertedMessage();
}
if (newMessage != null)
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
index 8640bbb999..ac63345473 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
@@ -121,20 +121,27 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
FieldTable clientProperties = FieldTableFactory.newFieldTable();
-
- clientProperties.put(ClientProperties.instance.toString(), ps.getClientID());
- clientProperties.put(ClientProperties.product.toString(), QpidProperties.getProductName());
- clientProperties.put(ClientProperties.version.toString(), QpidProperties.getReleaseVersion());
- clientProperties.put(ClientProperties.platform.toString(), getFullSystemInfo());
+
+ try
+ {
+ clientProperties.put(ClientProperties.instance.toString(), ps.getClientID());
+ clientProperties.put(ClientProperties.product.toString(), QpidProperties.getProductName());
+ clientProperties.put(ClientProperties.version.toString(), QpidProperties.getReleaseVersion());
+ clientProperties.put(ClientProperties.platform.toString(), getFullSystemInfo());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
// AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
ps.writeFrame(ConnectionStartOkBody.createAMQFrame(evt.getChannelId(),
- (byte)8, (byte)0, // AMQP version (major, minor)
- clientProperties, // clientProperties
- selectedLocale, // locale
- mechanism, // mechanism
- saslResponse)); // response
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ clientProperties, // clientProperties
+ selectedLocale, // locale
+ mechanism, // mechanism
+ saslResponse)); // response
}
catch (UnsupportedEncodingException e)
{
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java b/qpid/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java
index 58089f595b..7dcee74a1d 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java
@@ -25,7 +25,8 @@ import org.apache.log4j.Logger;
import javax.jms.*;
import java.util.Enumeration;
-public class MessageConverter {
+public class MessageConverter
+{
/**
* Log4J logger
@@ -117,6 +118,16 @@ public class MessageConverter {
_newMessage = (AbstractJMSMessage) nativeMessage;
setMessageProperties(message);
}
+
+ public MessageConverter(Message message) throws JMSException
+ {
+ //Send a message with just properties.
+ // Throwing away content
+ BytesMessage nativeMessage = new JMSBytesMessage();
+
+ _newMessage = (AbstractJMSMessage) nativeMessage;
+ setMessageProperties(message);
+ }
public AbstractJMSMessage getConvertedMessage()
{
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
index fbf5451b3b..09a6f3be38 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
@@ -29,6 +29,7 @@ import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.qpid.AMQConnectionClosedException;
import org.apache.qpid.AMQDisconnectedException;
import org.apache.qpid.AMQException;
+import org.apache.qpid.pool.ReadWriteThreadModel;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.failover.FailoverHandler;
@@ -147,6 +148,19 @@ public class AMQProtocolHandler extends IoHandlerAdapter
session.getFilterChain().addBefore("protocolFilter", "ssl", sslFilter);
}
+ try
+ {
+
+ ReadWriteThreadModel threadModel = ReadWriteThreadModel.getInstance();
+ threadModel.getAsynchronousReadFilter().createNewJobForSession(session);
+ threadModel.getAsynchronousWriteFilter().createNewJobForSession(session);
+ }
+ catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ }
+
+
_protocolSession = new AMQProtocolSession(this, session, _connection);
_protocolSession.init();
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java b/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
index 50bd1667f9..56b49230ff 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
@@ -53,6 +53,8 @@ public class AMQStateManager implements AMQMethodListener
private final Map _state2HandlersMap = new HashMap();
private final CopyOnWriteArraySet _stateListeners = new CopyOnWriteArraySet();
+ private final Object _stateLock = new Object();
+ private static final long MAXIMUM_STATE_WAIT_TIME = 30000l;
public AMQStateManager()
{
@@ -62,7 +64,7 @@ public class AMQStateManager implements AMQMethodListener
protected AMQStateManager(AMQState state, boolean register)
{
_currentState = state;
- if(register)
+ if (register)
{
registerListeners();
}
@@ -118,17 +120,10 @@ public class AMQStateManager implements AMQMethodListener
public void changeState(AMQState newState) throws AMQException
{
_logger.debug("State changing to " + newState + " from old state " + _currentState);
- final AMQState oldState = _currentState;
- _currentState = newState;
-
- synchronized (_stateListeners)
+ synchronized (_stateLock)
{
- final Iterator it = _stateListeners.iterator();
- while (it.hasNext())
- {
- final StateListener l = (StateListener) it.next();
- l.stateChanged(oldState, newState);
- }
+ _currentState = newState;
+ _stateLock.notifyAll();
}
}
@@ -195,36 +190,34 @@ public class AMQStateManager implements AMQMethodListener
}
}
- public void addStateListener(StateListener listener)
- {
- _logger.debug("Adding state listener");
- _stateListeners.add(listener);
- }
-
- public void removeStateListener(StateListener listener)
+ public void attainState(final AMQState s) throws AMQException
{
- _stateListeners.remove(listener);
- }
-
- public void attainState(AMQState s) throws AMQException
- {
- boolean needToWait = false;
- StateWaiter sw = null;
- synchronized (_stateListeners)
+ synchronized (_stateLock)
{
+ final long waitUntilTime = System.currentTimeMillis() + MAXIMUM_STATE_WAIT_TIME;
+ long waitTime = MAXIMUM_STATE_WAIT_TIME;
+
+ while (_currentState != s && waitTime > 0)
+ {
+ try
+ {
+ _stateLock.wait(MAXIMUM_STATE_WAIT_TIME);
+ }
+ catch (InterruptedException e)
+ {
+ _logger.warn("Thread interrupted");
+ }
+ if (_currentState != s)
+ {
+ waitTime = waitUntilTime - System.currentTimeMillis();
+ }
+ }
if (_currentState != s)
{
- _logger.debug("Adding state wait to reach state " + s);
- sw = new StateWaiter(s);
- addStateListener(sw);
- // we use a boolean since we must release the lock before starting to wait
- needToWait = true;
+ _logger.warn("State not achieved within permitted time. Current state " + _currentState + ", desired state: " + s);
+ throw new AMQException("State not achieved within permitted time. Current state " + _currentState + ", desired state: " + s);
}
}
- if (needToWait)
- {
- sw.waituntilStateHasChanged();
- }
// at this point the state will have changed.
}
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java
index d6364f45b0..5e6244d7cc 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java
@@ -71,7 +71,7 @@ public class SocketTransportConnection implements ITransportConnection
boolean readWriteThreading = Boolean.getBoolean("amqj.shared_read_write_pool");
if (readWriteThreading)
{
- cfg.setThreadModel(new ReadWriteThreadModel());
+ cfg.setThreadModel(ReadWriteThreadModel.getInstance());
}
SocketSessionConfig scfg = (SocketSessionConfig) cfg.getSessionConfig();
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
index e9e23aefdb..99a4c5f30d 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
@@ -70,7 +70,7 @@ public class TransportConnection
IoServiceConfig config = _acceptor.getDefaultConfig();
- config.setThreadModel(new ReadWriteThreadModel());
+ config.setThreadModel(ReadWriteThreadModel.getInstance());
}
public static ITransportConnection getInstance() throws AMQTransportConnectionException
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java b/qpid/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java
new file mode 100644
index 0000000000..ecc8f1d1e9
--- /dev/null
+++ b/qpid/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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.qpid.client;
+
+import junit.framework.TestCase;
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
+
+import javax.jms.Connection;
+import javax.jms.Session;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.Message;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.naming.Context;
+import javax.naming.spi.InitialContextFactory;
+import java.util.Hashtable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery queue
+ * <p/>
+ * The message delivery process:
+ * Mina puts a message on _queue in AMQSession and the dispatcher thread take()s
+ * from here and dispatches to the _consumers. If the _consumer doesn't have a message listener set at connection start
+ * then messages are stored on _synchronousQueue (which needs to be > 1 to pass JMS TCK as multiple consumers on a
+ * session can run in any order and a synchronous put/poll will block the dispatcher).
+ * <p/>
+ * When setting the message listener later the _synchronousQueue is just poll()'ed and the first message delivered
+ * the remaining messages will be left on the queue and lost, subsequent messages on the session will arrive first.
+ */
+public class DispatcherTest extends TestCase
+{
+ private static final Logger _logger = Logger.getLogger(DispatcherTest.class);
+
+ Context _context;
+
+ private static final int MSG_COUNT = 6;
+ private int _receivedCount = 0;
+ private int _receivedCountWhileStopped = 0;
+ private Connection _clientConnection, _producerConnection;
+ private MessageConsumer _consumer;
+ MessageProducer _producer;
+ Session _clientSession, _producerSession;
+
+ private final CountDownLatch _allFirstMessagesSent = new CountDownLatch(1); //all messages Sent Lock
+ private final CountDownLatch _allSecondMessagesSent = new CountDownLatch(1); //all messages Sent Lock
+
+ private volatile boolean _connectionStopped = false;
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ TransportConnection.createVMBroker(1);
+
+ InitialContextFactory factory = new PropertiesFileInitialContextFactory();
+
+ Hashtable<String, String> env = new Hashtable<String, String>();
+
+ env.put("connectionfactory.connection", "amqp://client:client@MLT_ID/test?brokerlist='vm://:1'");
+ env.put("queue.queue", "direct://amq.direct//MessageListenerTest");
+
+ _context = factory.getInitialContext(env);
+
+ Queue queue = (Queue) _context.lookup("queue");
+
+ //Create Client 1
+ _clientConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection();
+
+ _clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ _consumer = _clientSession.createConsumer(queue);
+
+ //Create Producer
+ _producerConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection();
+
+ _producerConnection.start();
+
+ _producerSession = _producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ _producer = _producerSession.createProducer(queue);
+
+ for (int msg = 0; msg < MSG_COUNT; msg++)
+ {
+ _producer.send(_producerSession.createTextMessage("Message " + msg));
+ }
+
+ }
+
+ protected void tearDown() throws Exception
+ {
+
+ _clientConnection.close();
+
+ _producerConnection.close();
+ super.tearDown();
+ TransportConnection.killAllVMBrokers();
+ }
+
+
+ public void testAsynchronousRecieve()
+ {
+
+ _logger.info("Test Start");
+
+
+ assertTrue(!((AMQConnection) _clientConnection).started());
+
+ //Set default Message Listener
+ try
+ {
+ _consumer.setMessageListener(new MessageListener()
+ {
+ public void onMessage(Message message)
+ {
+ _logger.info("Client 1 ML 1 Received Message(" + _receivedCount + "):" + message);
+
+ _receivedCount++;
+
+ if (_receivedCount == MSG_COUNT)
+ {
+ _allFirstMessagesSent.countDown();
+ }
+
+ if (_connectionStopped)
+ {
+ _logger.info("Running with Message:" + _receivedCount);
+ }
+
+ if (_connectionStopped && _allFirstMessagesSent.getCount() == 0)
+ {
+ _receivedCountWhileStopped++;
+ }
+
+ if (_allFirstMessagesSent.getCount() == 0)
+ {
+ if (_receivedCount == MSG_COUNT * 2)
+ {
+ _allSecondMessagesSent.countDown();
+ }
+ }
+ }
+ });
+
+ assertTrue("Connecion should not be started", !((AMQConnection) _clientConnection).started());
+ _clientConnection.start();
+ }
+ catch (JMSException e)
+ {
+ _logger.error("Error Setting Default ML on consumer1");
+ }
+
+
+ try
+ {
+ _allFirstMessagesSent.await(1000, TimeUnit.MILLISECONDS);
+ }
+ catch (InterruptedException e)
+ {
+ //do nothing
+ }
+
+ try
+ {
+ assertTrue("Connecion should be started", ((AMQConnection) _clientConnection).started());
+ _clientConnection.stop();
+ _connectionStopped = true;
+ }
+ catch (JMSException e)
+ {
+ _logger.error("Error stopping connection");
+ }
+
+
+ try
+ {
+ _logger.error("Send additional messages");
+
+ for (int msg = 0; msg < MSG_COUNT; msg++)
+ {
+ _producer.send(_producerSession.createTextMessage("Message " + msg));
+ }
+ }
+ catch (JMSException e)
+ {
+ _logger.error("Unable to send additional messages", e);
+ }
+
+
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e)
+ {
+ //ignore
+ }
+
+ try
+ {
+ _logger.info("Restarting connection");
+
+ _connectionStopped = false;
+ _clientConnection.start();
+ }
+ catch (JMSException e)
+ {
+ _logger.error("Error Setting Better ML on consumer1", e);
+ }
+
+
+ _logger.info("Waiting upto 2 seconds for messages");
+
+ try
+ {
+ _allSecondMessagesSent.await(1000, TimeUnit.MILLISECONDS);
+ }
+ catch (InterruptedException e)
+ {
+ //do nothing
+ }
+
+ assertEquals("Messages not received correctly", 0, _allFirstMessagesSent.getCount());
+ assertEquals("Messages not received correctly", 0, _allSecondMessagesSent.getCount());
+ assertEquals("Client didn't get all messages", MSG_COUNT * 2, _receivedCount);
+ assertEquals("Messages received while stopped is not 0", 0, _receivedCountWhileStopped);
+
+ }
+
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(DispatcherTest.class);
+ }
+} \ No newline at end of file
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/message/TestNonQpidTextMessage.java b/qpid/java/client/src/test/java/org/apache/qpid/client/message/NonQpidObjectMessage.java
index f7bea1b36a..c3434164d8 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/client/message/TestNonQpidTextMessage.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/client/message/NonQpidObjectMessage.java
@@ -24,7 +24,7 @@ import javax.jms.*;
import java.util.Enumeration;
import java.io.Serializable;
-public class TestNonQpidTextMessage implements ObjectMessage {
+public class NonQpidObjectMessage implements ObjectMessage {
private JMSObjectMessage _realMessage;
private String _contentString;
@@ -34,7 +34,7 @@ public class TestNonQpidTextMessage implements ObjectMessage {
* does not inherit from the Qpid message superclasses
* and expand our unit testing of MessageConverter et al
*/
- public TestNonQpidTextMessage()
+ public NonQpidObjectMessage()
{
_realMessage = new JMSObjectMessage();
}
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java
new file mode 100644
index 0000000000..48208193ce
--- /dev/null
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java
@@ -0,0 +1,173 @@
+/*
+ *
+ * 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.qpid.test.unit.client.connection;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQAuthenticationException;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.message.AMQMessage;
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQConnectionException;
+import org.apache.qpid.AMQUnresolvedAddressException;
+import org.apache.qpid.AMQConnectionFailureException;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+import javax.jms.MessageProducer;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.TextMessage;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class ConnectionStartTest extends TestCase
+{
+
+ String _broker = "vm://:1";
+
+ AMQConnection _connection;
+ private Session _consumerSess;
+ private MessageConsumer _consumer;
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ TransportConnection.createVMBroker(1);
+
+ try
+ {
+ AMQQueue queue = new AMQQueue("ConnectionStartTest");
+
+ AMQConnection pubCon = new AMQConnection(_broker, "guest", "guest", "fred", "/test");
+
+ Session pubSess = pubCon.createSession(false, AMQSession.AUTO_ACKNOWLEDGE);
+
+ MessageProducer pub = pubSess.createProducer(queue);
+
+ pub.send(pubSess.createTextMessage("Initial Message"));
+
+ _connection = new AMQConnection(_broker, "guest", "guest", "fred", "/" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "test");
+
+ _consumerSess = _connection.createSession(false, AMQSession.AUTO_ACKNOWLEDGE);
+
+ _consumer = _consumerSess.createConsumer(queue);
+
+ pubCon.close();
+
+ }
+ catch (Exception e)
+ {
+ fail("Connection to " + _broker + " should succeed. Reason: " + e);
+ }
+ }
+
+ protected void tearDown() throws Exception
+ {
+ _connection.close();
+ TransportConnection.killVMBroker(1);
+ }
+
+ public void testSimpleReceiveConnection()
+ {
+ try
+ {
+ assertTrue("Connection should not be started", !_connection.started());
+ //Note that this next line will start the dispatcher in the session
+ // should really not be called before _connection start
+ assertTrue("There should not be messages waiting for the consumer", _consumer.receiveNoWait() == null);
+ _connection.start();
+ assertTrue("There should be messages waiting for the consumer", _consumer.receiveNoWait() == null);
+ assertTrue("Connection should be started", _connection.started());
+
+ }
+ catch (JMSException e)
+ {
+ fail("An error occured during test because:" + e);
+ }
+
+ }
+
+ public void testMessageListenerConnection()
+ {
+ final CountDownLatch _gotMessage = new CountDownLatch(1);
+
+ try
+ {
+ assertTrue("Connection should not be started", !_connection.started());
+ _consumer.setMessageListener(new MessageListener()
+ {
+ public void onMessage(Message message)
+ {
+ try
+ {
+ assertTrue("Connection should be started", _connection.started());
+ assertEquals("Mesage Received", "Initial Message", ((TextMessage) message).getText());
+ _gotMessage.countDown();
+ }
+ catch (JMSException e)
+ {
+ fail("Couldn't get message text because:" + e.getCause());
+ }
+ }
+ });
+
+ assertTrue("Connection should not be started", !_connection.started());
+ _connection.start();
+ assertTrue("Connection should be started", _connection.started());
+
+ try
+ {
+ _gotMessage.await(1000, TimeUnit.MILLISECONDS);
+ }
+ catch (InterruptedException e)
+ {
+ fail("Timed out awaiting message via onMessage");
+ }
+
+ }
+ catch (JMSException e)
+ {
+ fail("Failed because:" + e.getCause());
+ }
+
+ }
+
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(ConnectionStartTest.class);
+ }
+}
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java
index 456748e0d2..b0d06ae148 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java
@@ -26,7 +26,8 @@ import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.message.TestNonQpidTextMessage;
+import org.apache.qpid.client.message.NonQpidObjectMessage;
+
import javax.jms.*;
@@ -70,7 +71,7 @@ public class JMSPropertiesTest extends TestCase
MessageProducer producer = producerSession.createProducer(queue);
//create a test message to send
- ObjectMessage sentMsg = new TestNonQpidTextMessage();
+ ObjectMessage sentMsg = new NonQpidObjectMessage();
sentMsg.setJMSCorrelationID(JMS_CORR_ID);
sentMsg.setJMSDeliveryMode(JMS_DELIV_MODE);
sentMsg.setJMSType(JMS_TYPE);
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java
index 6a335b8627..a8a5c7d8b2 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java
@@ -31,10 +31,12 @@ import javax.jms.Message;
import javax.jms.Destination;
import javax.jms.TextMessage;
import javax.jms.MapMessage;
+import javax.jms.JMSException;
import java.util.HashMap;
-public class MessageConverterTest extends TestCase {
+public class MessageConverterTest extends TestCase
+{
public static final String JMS_CORR_ID = "QPIDID_01";
public static final int JMS_DELIV_MODE = 1;
@@ -50,53 +52,79 @@ public class MessageConverterTest extends TestCase {
super.setUp();
testTextMessage = new JMSTextMessage();
- //Add JMSProperties
- testTextMessage.setJMSCorrelationID(JMS_CORR_ID);
- testTextMessage.setJMSDeliveryMode(JMS_DELIV_MODE);
- testTextMessage.setJMSType(JMS_TYPE);
- testTextMessage.setJMSReplyTo(JMS_REPLY_TO);
+ //Set Message Text
testTextMessage.setText("testTextMessage text");
-
- //Add non-JMS properties
- testTextMessage.setStringProperty("testProp1","testValue1");
- testTextMessage.setDoubleProperty("testProp2",Double.MIN_VALUE);
+ setMessageProperties(testTextMessage);
testMapMessage = new JMSMapMessage();
- testMapMessage.setString("testMapString","testMapStringValue");
- testMapMessage.setDouble("testMapDouble",Double.MAX_VALUE);
+ testMapMessage.setString("testMapString", "testMapStringValue");
+ testMapMessage.setDouble("testMapDouble", Double.MAX_VALUE);
}
public void testSetProperties() throws Exception
{
- AbstractJMSMessage newMessage = new MessageConverter((TextMessage)testTextMessage).getConvertedMessage();
-
- //check JMS prop values on newMessage match
- assertEquals("JMS Correlation ID mismatch",testTextMessage.getJMSCorrelationID(),newMessage.getJMSCorrelationID());
- assertEquals("JMS Delivery mode mismatch",testTextMessage.getJMSDeliveryMode(),newMessage.getJMSDeliveryMode());
- assertEquals("JMS Type mismatch",testTextMessage.getJMSType(),newMessage.getJMSType());
- assertEquals("JMS Reply To mismatch",testTextMessage.getJMSReplyTo(),newMessage.getJMSReplyTo());
-
- //check non-JMS standard props ok too
- assertEquals("Test String prop value mismatch",testTextMessage.getStringProperty("testProp1"),
- newMessage.getStringProperty("testProp1"));
- assertEquals("Test Double prop value mismatch",testTextMessage.getDoubleProperty("testProp2"),
- newMessage.getDoubleProperty("testProp2"));
+ AbstractJMSMessage newMessage = new MessageConverter((TextMessage) testTextMessage).getConvertedMessage();
+ mesagePropertiesTest(testTextMessage, newMessage);
}
public void testJMSTextMessageConversion() throws Exception
{
- AbstractJMSMessage newMessage = new MessageConverter((TextMessage)testTextMessage).getConvertedMessage();
- assertEquals("Converted message text mismatch",((JMSTextMessage)newMessage).getText(),testTextMessage.getText());
+ AbstractJMSMessage newMessage = new MessageConverter((TextMessage) testTextMessage).getConvertedMessage();
+ assertEquals("Converted message text mismatch", ((JMSTextMessage) newMessage).getText(), testTextMessage.getText());
}
public void testJMSMapMessageConversion() throws Exception
{
- AbstractJMSMessage newMessage = new MessageConverter((MapMessage)testMapMessage).getConvertedMessage();
- assertEquals("Converted map message String mismatch",((JMSMapMessage)newMessage).getString("testMapString"),
- testMapMessage.getString("testMapString"));
- assertEquals("Converted map message Double mismatch",((JMSMapMessage)newMessage).getDouble("testMapDouble"),
- testMapMessage.getDouble("testMapDouble"));
+ AbstractJMSMessage newMessage = new MessageConverter((MapMessage) testMapMessage).getConvertedMessage();
+ assertEquals("Converted map message String mismatch", ((JMSMapMessage) newMessage).getString("testMapString"),
+ testMapMessage.getString("testMapString"));
+ assertEquals("Converted map message Double mismatch", ((JMSMapMessage) newMessage).getDouble("testMapDouble"),
+ testMapMessage.getDouble("testMapDouble"));
+
+ }
+
+ public void testMessageConversion() throws Exception
+ {
+ Message newMessage = new NonQpidMessage();
+ setMessageProperties(newMessage);
+ mesagePropertiesTest(testTextMessage, newMessage);
+ }
+
+ private void setMessageProperties(Message message) throws JMSException
+ {
+ message.setJMSCorrelationID(JMS_CORR_ID);
+ message.setJMSDeliveryMode(JMS_DELIV_MODE);
+ message.setJMSType(JMS_TYPE);
+ message.setJMSReplyTo(JMS_REPLY_TO);
+ //Add non-JMS properties
+ message.setStringProperty("testProp1", "testValue1");
+ message.setDoubleProperty("testProp2", Double.MIN_VALUE);
+ }
+
+
+ private void mesagePropertiesTest(Message expectedMessage, Message actualMessage)
+ {
+ try
+ {
+ //check JMS prop values on newMessage match
+ assertEquals("JMS Correlation ID mismatch", expectedMessage.getJMSCorrelationID(), actualMessage.getJMSCorrelationID());
+ assertEquals("JMS Delivery mode mismatch", expectedMessage.getJMSDeliveryMode(), actualMessage.getJMSDeliveryMode());
+ assertEquals("JMS Type mismatch", expectedMessage.getJMSType(), actualMessage.getJMSType());
+ assertEquals("JMS Reply To mismatch", expectedMessage.getJMSReplyTo(), actualMessage.getJMSReplyTo());
+
+ //check non-JMS standard props ok too
+ assertEquals("Test String prop value mismatch", expectedMessage.getStringProperty("testProp1"),
+ actualMessage.getStringProperty("testProp1"));
+
+ assertEquals("Test Double prop value mismatch", expectedMessage.getDoubleProperty("testProp2"),
+ actualMessage.getDoubleProperty("testProp2"));
+ }
+ catch (JMSException e)
+ {
+ fail("An error occured testing the property values" + e.getCause());
+ e.printStackTrace();
+ }
}
protected void tearDown() throws Exception
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/NonQpidMessage.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/NonQpidMessage.java
new file mode 100644
index 0000000000..e992290513
--- /dev/null
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/NonQpidMessage.java
@@ -0,0 +1,410 @@
+/*
+ * 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.qpid.test.unit.message;
+
+import javax.jms.Message;
+import javax.jms.JMSException;
+import javax.jms.Destination;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+public class NonQpidMessage implements Message
+{
+ private String _JMSMessageID;
+ private long _JMSTimestamp;
+ private byte[] _JMSCorrelationIDAsBytes;
+ private String _JMSCorrelationID;
+ private Destination _JMSReplyTo;
+ private Destination _JMSDestination;
+ private int _JMSDeliveryMode;
+ private boolean _JMSRedelivered;
+ private String _JMSType;
+ private long _JMSExpiration;
+ private int _JMSPriority;
+ private Hashtable _properties;
+
+ public NonQpidMessage()
+ {
+ _properties = new Hashtable();
+ _JMSPriority = javax.jms.Message.DEFAULT_PRIORITY;
+ _JMSDeliveryMode = javax.jms.Message.DEFAULT_DELIVERY_MODE;
+ }
+
+ public String getJMSMessageID() throws JMSException
+ {
+ return _JMSMessageID;
+ }
+
+ public void setJMSMessageID(String string) throws JMSException
+ {
+ _JMSMessageID = string;
+ }
+
+ public long getJMSTimestamp() throws JMSException
+ {
+ return _JMSTimestamp;
+ }
+
+ public void setJMSTimestamp(long l) throws JMSException
+ {
+ _JMSTimestamp = l;
+ }
+
+ public byte[] getJMSCorrelationIDAsBytes() throws JMSException
+ {
+ return _JMSCorrelationIDAsBytes;
+ }
+
+ public void setJMSCorrelationIDAsBytes(byte[] bytes) throws JMSException
+ {
+ _JMSCorrelationIDAsBytes = bytes;
+ }
+
+ public void setJMSCorrelationID(String string) throws JMSException
+ {
+ _JMSCorrelationID = string;
+ }
+
+ public String getJMSCorrelationID() throws JMSException
+ {
+ return _JMSCorrelationID;
+ }
+
+ public Destination getJMSReplyTo() throws JMSException
+ {
+ return _JMSReplyTo;
+ }
+
+ public void setJMSReplyTo(Destination destination) throws JMSException
+ {
+ _JMSReplyTo = destination;
+ }
+
+ public Destination getJMSDestination() throws JMSException
+ {
+ return _JMSDestination;
+ }
+
+ public void setJMSDestination(Destination destination) throws JMSException
+ {
+ _JMSDestination = destination;
+ }
+
+ public int getJMSDeliveryMode() throws JMSException
+ {
+ return _JMSDeliveryMode;
+ }
+
+ public void setJMSDeliveryMode(int i) throws JMSException
+ {
+ _JMSDeliveryMode = i;
+ }
+
+ public boolean getJMSRedelivered() throws JMSException
+ {
+ return _JMSRedelivered;
+ }
+
+ public void setJMSRedelivered(boolean b) throws JMSException
+ {
+ _JMSRedelivered = b;
+ }
+
+ public String getJMSType() throws JMSException
+ {
+ return _JMSType;
+ }
+
+ public void setJMSType(String string) throws JMSException
+ {
+ _JMSType = string;
+ }
+
+ public long getJMSExpiration() throws JMSException
+ {
+ return _JMSExpiration;
+ }
+
+ public void setJMSExpiration(long l) throws JMSException
+ {
+ _JMSExpiration = l;
+ }
+
+ public int getJMSPriority() throws JMSException
+ {
+ return _JMSPriority;
+ }
+
+ public void setJMSPriority(int i) throws JMSException
+ {
+ _JMSPriority = i;
+ }
+
+ public void clearProperties() throws JMSException
+ {
+ _properties.clear();
+ }
+
+ public boolean propertyExists(String string) throws JMSException
+ {
+ return _properties.containsKey(string);
+ }
+
+ public boolean getBooleanProperty(String string) throws JMSException
+ {
+ if (propertyExists(string))
+ {
+ Object o = _properties.get(string);
+ if (o instanceof Boolean)
+ {
+ return (Boolean) o;
+ }
+ else
+ {
+ return Boolean.valueOf(null);
+ }
+ }
+ else
+ {
+ throw new JMSException("property does not exist: " + string);
+ }
+ }
+
+ public byte getByteProperty(String string) throws JMSException
+ {
+ if (propertyExists(string))
+ {
+ Object o = _properties.get(string);
+ if (o instanceof Byte)
+ {
+ return (Byte) o;
+ }
+ else
+ {
+ return Byte.valueOf(null);
+ }
+ }
+ else
+ {
+ throw new JMSException("property does not exist: " + string);
+ }
+ }
+
+ public short getShortProperty(String string) throws JMSException
+ {
+ if (propertyExists(string))
+ {
+ Object o = _properties.get(string);
+ if (o instanceof Short)
+ {
+ return (Short) o;
+ }
+ else
+ {
+ return Short.valueOf(null);
+ }
+ }
+ else
+ {
+ throw new JMSException("property does not exist: " + string);
+ }
+ }
+
+ public int getIntProperty(String string) throws JMSException
+ {
+ if (propertyExists(string))
+ {
+ Object o = _properties.get(string);
+ if (o instanceof Integer)
+ {
+ return (Integer) o;
+ }
+ else
+ {
+ return Integer.valueOf(null);
+ }
+ }
+ else
+ {
+ throw new JMSException("property does not exist: " + string);
+ }
+ }
+
+ public long getLongProperty(String string) throws JMSException
+ {
+ if (propertyExists(string))
+ {
+ Object o = _properties.get(string);
+ if (o instanceof Long)
+ {
+ return (Long) o;
+ }
+ else
+ {
+ return Long.valueOf(null);
+ }
+ }
+ else
+ {
+ throw new JMSException("property does not exist: " + string);
+ }
+ }
+
+ public float getFloatProperty(String string) throws JMSException
+ {
+ if (propertyExists(string))
+ {
+ Object o = _properties.get(string);
+ if (o instanceof Float)
+ {
+ return (Float) o;
+ }
+ else
+ {
+ return Float.valueOf(null);
+ }
+ }
+ else
+ {
+ throw new JMSException("property does not exist: " + string);
+ }
+ }
+
+ public double getDoubleProperty(String string) throws JMSException
+ {
+ if (propertyExists(string))
+ {
+ Object o = _properties.get(string);
+ if (o instanceof Double)
+ {
+ return (Double) o;
+ }
+ else
+ {
+ return Double.valueOf(null);
+ }
+ }
+ else
+ {
+ throw new JMSException("property does not exist: " + string);
+ }
+ }
+
+ public String getStringProperty(String string) throws JMSException
+ {
+ if (propertyExists(string))
+ {
+ Object o = _properties.get(string);
+ if (o instanceof String)
+ {
+ return (String) o;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ throw new JMSException("property does not exist: " + string);
+ }
+ }
+
+ public Object getObjectProperty(String string) throws JMSException
+ {
+ if (propertyExists(string))
+ {
+ Object o = _properties.get(string);
+ if (o instanceof Boolean)
+ {
+ return (Boolean) o;
+ }
+ else
+ {
+ return Boolean.valueOf(null);
+ }
+ }
+ else
+ {
+ throw new JMSException("property does not exist: " + string);
+ }
+ }
+
+ public Enumeration getPropertyNames() throws JMSException
+ {
+ return _properties.keys();
+ }
+
+ public void setBooleanProperty(String string, boolean b) throws JMSException
+ {
+ _properties.put(string, b);
+ }
+
+ public void setByteProperty(String string, byte b) throws JMSException
+ {
+ _properties.put(string, b);
+ }
+
+ public void setShortProperty(String string, short i) throws JMSException
+ {
+ _properties.put(string, i);
+ }
+
+ public void setIntProperty(String string, int i) throws JMSException
+ {
+ _properties.put(string, i);
+ }
+
+ public void setLongProperty(String string, long l) throws JMSException
+ {
+ _properties.put(string, l);
+ }
+
+ public void setFloatProperty(String string, float v) throws JMSException
+ {
+ _properties.put(string, v);
+ }
+
+ public void setDoubleProperty(String string, double v) throws JMSException
+ {
+ _properties.put(string, v);
+ }
+
+ public void setStringProperty(String string, String string1) throws JMSException
+ {
+ _properties.put(string, string1);
+ }
+
+ public void setObjectProperty(String string, Object object) throws JMSException
+ {
+ _properties.put(string, object);
+ }
+
+ public void acknowledge() throws JMSException
+ {
+
+ }
+
+ public void clearBody() throws JMSException
+ {
+
+ }
+}
diff --git a/qpid/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java b/qpid/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java
index 3eeddd7b4e..5746a32c26 100644
--- a/qpid/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java
+++ b/qpid/java/cluster/src/main/java/org/apache/qpid/server/cluster/Main.java
@@ -83,7 +83,7 @@ public class Main extends org.apache.qpid.server.Main
// implementation provided by MINA
if (connectorConfig.enableExecutorPool)
{
- sconfig.setThreadModel(new ReadWriteThreadModel());
+ sconfig.setThreadModel(ReadWriteThreadModel.getInstance());
}
String host = InetAddress.getLocalHost().getHostName();
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
index b29c23c2a2..81903b6936 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
@@ -10,7 +10,7 @@ public class AMQTypedValue
public AMQTypedValue(AMQType type, Object value)
{
- if(type == null)
+ if (type == null)
{
throw new NullPointerException("Cannot create a typed value with null type");
}
@@ -21,7 +21,7 @@ public class AMQTypedValue
private AMQTypedValue(AMQType type, ByteBuffer buffer)
{
_type = type;
- _value = type.readValueFromBuffer( buffer );
+ _value = type.readValueFromBuffer(buffer);
}
@@ -38,7 +38,7 @@ public class AMQTypedValue
public void writeToBuffer(ByteBuffer buffer)
{
- _type.writeToBuffer(_value,buffer);
+ _type.writeToBuffer(_value, buffer);
}
public int getEncodingSize()
@@ -51,4 +51,9 @@ public class AMQTypedValue
AMQType type = AMQTypeMap.getType(buffer.get());
return new AMQTypedValue(type, buffer);
}
+
+ public String toString()
+ {
+ return "[" + getType() + ": " + getValue() + "]";
+ }
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java
index f2d1a70cdc..18d2fdacfc 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java
@@ -27,7 +27,7 @@ import org.apache.qpid.AMQException;
public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQDataBlock
{
- public char[] header = new char[]{'A','M','Q','P'};
+ public char[] header = new char[]{'A', 'M', 'Q', 'P'};
// TODO: generate these constants automatically from the xml protocol spec file
private static byte CURRENT_PROTOCOL_CLASS = 1;
@@ -103,11 +103,10 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData
public static class Decoder //implements MessageDecoder
{
/**
- *
* @param session
* @param in
* @return true if we have enough data to decode the PI frame fully, false if more
- * data is required
+ * data is required
*/
public boolean decodable(IoSession session, ByteBuffer in)
{
@@ -115,12 +114,12 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData
}
public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out)
- throws Exception
+ throws Exception
{
byte[] theHeader = new byte[4];
in.get(theHeader);
- ProtocolInitiation pi = new ProtocolInitiation((byte)0, (byte)0);
- pi.header = new char[]{(char) theHeader[0],(char) theHeader[CURRENT_PROTOCOL_INSTANCE],(char) theHeader[2], (char) theHeader[3]};
+ ProtocolInitiation pi = new ProtocolInitiation((byte) 0, (byte) 0);
+ pi.header = new char[]{(char) theHeader[0], (char) theHeader[CURRENT_PROTOCOL_INSTANCE], (char) theHeader[2], (char) theHeader[3]};
String stringHeader = new String(pi.header);
if (!"AMQP".equals(stringHeader))
{
@@ -139,17 +138,17 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData
if (protocolClass != CURRENT_PROTOCOL_CLASS)
{
throw new AMQProtocolClassException("Protocol class " + CURRENT_PROTOCOL_CLASS + " was expected; received " +
- protocolClass);
+ protocolClass);
}
if (protocolInstance != CURRENT_PROTOCOL_INSTANCE)
{
throw new AMQProtocolInstanceException("Protocol instance " + CURRENT_PROTOCOL_INSTANCE + " was expected; received " +
- protocolInstance);
+ protocolInstance);
}
-
+
/* Look through list of available protocol versions */
boolean found = false;
- for (int i=0; i<pvl.pv.length; i++)
+ for (int i = 0; i < pvl.pv.length; i++)
{
if (pvl.pv[i][pvl.PROTOCOL_MAJOR] == protocolMajor &&
pvl.pv[i][pvl.PROTOCOL_MINOR] == protocolMinor)
@@ -161,7 +160,17 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData
{
// TODO: add list of available versions in list to msg...
throw new AMQProtocolVersionException("Protocol version " +
- protocolMajor + "." + protocolMinor + " not found in protocol version list.");
+ protocolMajor + "." + protocolMinor + " not found in protocol version list.");
}
}
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer(new String(header));
+ buffer.append(Integer.toHexString(protocolClass));
+ buffer.append(Integer.toHexString(protocolInstance));
+ buffer.append(Integer.toHexString(protocolMajor));
+ buffer.append(Integer.toHexString(protocolMinor));
+ return buffer.toString();
+ }
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java
index b9673cd48f..76d1207035 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/Job.java
@@ -30,13 +30,13 @@ import java.util.concurrent.atomic.AtomicInteger;
* Holds events for a session that will be processed asynchronously by
* the thread pool in PoolingFilter.
*/
-class Job implements Runnable
+public class Job implements Runnable
{
private final int _maxEvents;
private final IoSession _session;
private final java.util.Queue<Event> _eventQueue = new ConcurrentLinkedQueue<Event>();
private final AtomicBoolean _active = new AtomicBoolean();
- private final AtomicInteger _refCount = new AtomicInteger();
+// private final AtomicInteger _refCount = new AtomicInteger();
private final JobCompletionHandler _completionHandler;
Job(IoSession session, JobCompletionHandler completionHandler, int maxEvents)
@@ -46,20 +46,20 @@ class Job implements Runnable
_maxEvents = maxEvents;
}
- void acquire()
- {
- _refCount.incrementAndGet();
- }
-
- void release()
- {
- _refCount.decrementAndGet();
- }
-
- boolean isReferenced()
- {
- return _refCount.get() > 0;
- }
+// void acquire()
+// {
+// _refCount.incrementAndGet();
+// }
+//
+// void release()
+// {
+// _refCount.decrementAndGet();
+// }
+//
+// boolean isReferenced()
+// {
+// return _refCount.get() > 0;
+// }
void add(Event evt)
{
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java
index c0026c1f36..07ef69d6ad 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java
@@ -48,7 +48,7 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
void fireAsynchEvent(IoSession session, Event event)
{
Job job = getJobForSession(session);
- job.acquire(); //prevents this job being removed from _jobs
+// job.acquire(); //prevents this job being removed from _jobs
job.add(event);
//Additional checks on pool to check that it hasn't shutdown.
@@ -60,10 +60,25 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
}
+ public void createNewJobForSession(IoSession session)
+ {
+ Job job = new Job(session, this, _maxEvents);
+ session.setAttribute(_name, job);
+ }
+
private Job getJobForSession(IoSession session)
{
- Job job = _jobs.get(session);
- return job == null ? createJobForSession(session) : job;
+ return (Job) session.getAttribute(_name);
+
+/* if(job == null)
+ {
+ System.err.println("Error in " + _name);
+ Thread.dumpStack();
+ }
+
+
+ job = _jobs.get(session);
+ return job == null ? createJobForSession(session) : job;*/
}
private Job createJobForSession(IoSession session)
@@ -81,16 +96,18 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
//Job.JobCompletionHandler
public void completed(IoSession session, Job job)
{
- if (job.isComplete())
- {
- job.release();
- if (!job.isReferenced())
- {
- _jobs.remove(session);
- }
- }
- else
+// if (job.isComplete())
+// {
+// job.release();
+// if (!job.isReferenced())
+// {
+// _jobs.remove(session);
+// }
+// }
+// else
+ if (!job.isComplete())
{
+
// ritchiem : 2006-12-13 Do we need to perform the additional checks here?
// Can the pool be shutdown at this point?
if (job.activate() && _poolReference.getPool() != null && !_poolReference.getPool().isShutdown())
@@ -121,13 +138,13 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
public void exceptionCaught(final NextFilter nextFilter, final IoSession session,
final Throwable cause) throws Exception
{
- nextFilter.exceptionCaught(session,cause);
+ nextFilter.exceptionCaught(session, cause);
}
public void messageReceived(final NextFilter nextFilter, final IoSession session,
final Object message) throws Exception
{
- nextFilter.messageReceived(session,message);
+ nextFilter.messageReceived(session, message);
}
public void messageSent(final NextFilter nextFilter, final IoSession session,
@@ -185,7 +202,7 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
}
public void messageReceived(final NextFilter nextFilter, final IoSession session,
- final Object message) throws Exception
+ final Object message) throws Exception
{
fireAsynchEvent(session, new Event.ReceivedEvent(nextFilter, message));
@@ -211,15 +228,15 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
}
- public static PoolingFilter createAynschReadPoolingFilter(ReferenceCountingExecutorService refCountingPool,String name)
+ public static PoolingFilter createAynschReadPoolingFilter(ReferenceCountingExecutorService refCountingPool, String name)
{
- return new AsynchReadPoolingFilter(refCountingPool,name);
+ return new AsynchReadPoolingFilter(refCountingPool, name);
}
- public static PoolingFilter createAynschWritePoolingFilter(ReferenceCountingExecutorService refCountingPool,String name)
+ public static PoolingFilter createAynschWritePoolingFilter(ReferenceCountingExecutorService refCountingPool, String name)
{
- return new AsynchWritePoolingFilter(refCountingPool,name);
+ return new AsynchWritePoolingFilter(refCountingPool, name);
}
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java
index 84b72bb0dc..d6f76f8583 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/ReadWriteThreadModel.java
@@ -26,12 +26,36 @@ import org.apache.mina.common.ThreadModel;
public class ReadWriteThreadModel implements ThreadModel
{
+ private static final ReadWriteThreadModel _instance = new ReadWriteThreadModel();
+
+ private final PoolingFilter _asynchronousReadFilter;
+ private final PoolingFilter _asynchronousWriteFilter;
+
+ private ReadWriteThreadModel()
+ {
+ final ReferenceCountingExecutorService executor = ReferenceCountingExecutorService.getInstance();
+ _asynchronousReadFilter = PoolingFilter.createAynschReadPoolingFilter(executor, "AsynchronousReadFilter");
+ _asynchronousWriteFilter = PoolingFilter.createAynschWritePoolingFilter(executor, "AsynchronousWriteFilter");
+ }
+
+ public PoolingFilter getAsynchronousReadFilter()
+ {
+ return _asynchronousReadFilter;
+ }
+
+ public PoolingFilter getAsynchronousWriteFilter()
+ {
+ return _asynchronousWriteFilter;
+ }
+
public void buildFilterChain(IoFilterChain chain) throws Exception
{
- ReferenceCountingExecutorService executor = ReferenceCountingExecutorService.getInstance();
- PoolingFilter asyncRead = PoolingFilter.createAynschReadPoolingFilter(executor, "AsynchronousReadFilter");
- PoolingFilter asyncWrite = PoolingFilter.createAynschWritePoolingFilter(executor, "AsynchronousWriteFilter");
- chain.addFirst("AsynchronousReadFilter", new ReferenceCountingIoFilter(asyncRead));
- chain.addLast("AsynchronousWriteFilter", new ReferenceCountingIoFilter(asyncWrite));
+ chain.addFirst("AsynchronousReadFilter", new ReferenceCountingIoFilter(_asynchronousReadFilter));
+ chain.addLast("AsynchronousWriteFilter", new ReferenceCountingIoFilter(_asynchronousWriteFilter));
+ }
+
+ public static ReadWriteThreadModel getInstance()
+ {
+ return _instance;
}
}
diff --git a/qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java b/qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java
index 9a5208662b..cd7e240ee4 100644
--- a/qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java
+++ b/qpid/java/common/src/test/java/org/apache/qpid/pool/PoolingFilterTest.java
@@ -39,22 +39,26 @@ public class PoolingFilterTest extends TestCase
//Create Pool
_executorService = ReferenceCountingExecutorService.getInstance();
_executorService.acquireExecutorService();
- _pool = PoolingFilter.createAynschWritePoolingFilter(_executorService,
- "AsynchronousWriteFilter");
-
+ _pool = PoolingFilter.createAynschWritePoolingFilter(_executorService,
+ "AsynchronousWriteFilter");
}
public void testRejectedExecution() throws Exception
{
- _pool.filterWrite(new NoOpFilter(), new TestSession(), new IoFilter.WriteRequest("Message"));
+ TestSession testSession = new TestSession();
+ _pool.createNewJobForSession(testSession);
+ _pool.filterWrite(new NoOpFilter(), testSession, new IoFilter.WriteRequest("Message"));
//Shutdown the pool
_executorService.getPool().shutdownNow();
try
{
+
+ testSession = new TestSession();
+ _pool.createNewJobForSession(testSession);
//prior to fix for QPID-172 this would throw RejectedExecutionException
- _pool.filterWrite(null, new TestSession(), null);
+ _pool.filterWrite(null, testSession, null);
}
catch (RejectedExecutionException rje)
{
diff --git a/qpid/java/common/src/test/java/org/apache/qpid/session/TestSession.java b/qpid/java/common/src/test/java/org/apache/qpid/session/TestSession.java
index f10d55e9d0..308bb9a331 100644
--- a/qpid/java/common/src/test/java/org/apache/qpid/session/TestSession.java
+++ b/qpid/java/common/src/test/java/org/apache/qpid/session/TestSession.java
@@ -24,9 +24,13 @@ import org.apache.mina.common.*;
import java.net.SocketAddress;
import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
public class TestSession implements IoSession
{
+ private final ConcurrentMap attributes = new ConcurrentHashMap();
+
public TestSession()
{
}
@@ -68,42 +72,42 @@ public class TestSession implements IoSession
public Object getAttachment()
{
- return null; //TODO
+ return getAttribute("");
}
public Object setAttachment(Object attachment)
{
- return null; //TODO
+ return setAttribute("",attachment);
}
public Object getAttribute(String key)
{
- return null; //TODO
+ return attributes.get(key);
}
public Object setAttribute(String key, Object value)
{
- return null; //TODO
+ return attributes.put(key,value);
}
public Object setAttribute(String key)
{
- return null; //TODO
+ return attributes.put(key, Boolean.TRUE);
}
public Object removeAttribute(String key)
{
- return null; //TODO
+ return attributes.remove(key);
}
public boolean containsAttribute(String key)
{
- return false; //TODO
+ return attributes.containsKey(key);
}
public Set getAttributeKeys()
{
- return null; //TODO
+ return attributes.keySet();
}
public TransportType getTransportType()
@@ -270,4 +274,4 @@ public class TestSession implements IoSession
{
return 0; //TODO
}
-}
+} \ No newline at end of file
diff --git a/qpid/java/mvn-repo/README.txt b/qpid/java/mvn-repo/README.txt
index e24cb7a41b..c78cda6938 100644
--- a/qpid/java/mvn-repo/README.txt
+++ b/qpid/java/mvn-repo/README.txt
@@ -1 +1,5 @@
Temporary local repository for jars that are not available in the central repository yet.
+This was created because junit-toolkit is undergoing some development to use it with perf tests. Its an Apache licensed performance testing utility.
+It takes 2-4 days to get something added to the central repo but want to keep up with changed to junit-toolkit. This repository holds a snapshot
+of it, so that the build can get it from somewhere without breaking. It is anticipated that it will reach a stable 0.5 version within two weeks from
+30/01/2007, at which time it will be placed in the central repo and this local repository will be deleted.
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml
index 83b3102e66..0a46c1d79a 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml
@@ -4,9 +4,9 @@
<version>0.5-SNAPSHOT</version>
<versioning>
<snapshot>
- <timestamp>20070130.122841</timestamp>
+ <timestamp>20070130.111904</timestamp>
<buildNumber>1</buildNumber>
</snapshot>
- <lastUpdated>20070130122841</lastUpdated>
+ <lastUpdated>20070130111904</lastUpdated>
</versioning>
</metadata> \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.md5 b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.md5
index 2ceab1006e..4e7eab390b 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.md5
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.md5
@@ -1 +1 @@
-084991a8786d91eff123b053768eb232 \ No newline at end of file
+c619b7ac915b2eba622d556b2d2e0c25 \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.sha1 b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.sha1
index b6b0209c6a..83a5267307 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.sha1
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/0.5-SNAPSHOT/maven-metadata.xml.sha1
@@ -1 +1 @@
-13e6beaf255d393f939a59399b833f87ae7f4379 \ No newline at end of file
+db7b5d51a53a5018611391ecc3346032a6c20dda \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml
index bf278d23b3..a3bff0dde2 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml
@@ -7,6 +7,6 @@
<versions>
<version>0.5-SNAPSHOT</version>
</versions>
- <lastUpdated>20070130122841</lastUpdated>
+ <lastUpdated>20070130111904</lastUpdated>
</versioning>
</metadata> \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.md5 b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.md5
index ad190766aa..395a968533 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.md5
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.md5
@@ -1 +1 @@
-7a321ffcf3cba7f6cd7b43690d37c518 \ No newline at end of file
+da47ce66de64d4ba056d0a9c901c5676 \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.sha1 b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.sha1
index a25dcfe6f3..b396785e6c 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.sha1
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit-maven-plugin/maven-metadata.xml.sha1
@@ -1 +1 @@
-66446d0944bcb9269796a65834df3806cb45fd40 \ No newline at end of file
+70adf93da1c1757152e954750ceb2477a8659a99 \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml
index b2560dad04..216800cda7 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml
@@ -4,9 +4,9 @@
<version>0.5-SNAPSHOT</version>
<versioning>
<snapshot>
- <timestamp>20070130.111852</timestamp>
+ <timestamp>20070131.112634</timestamp>
<buildNumber>1</buildNumber>
</snapshot>
- <lastUpdated>20070130111852</lastUpdated>
+ <lastUpdated>20070131112634</lastUpdated>
</versioning>
</metadata> \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.md5 b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.md5
index d179176f11..c355e8f9be 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.md5
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.md5
@@ -1 +1 @@
-ee20ec4f594fd6efa85274c88d5d87ee \ No newline at end of file
+59aa948e74a22a370cc414718864f65f \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.sha1 b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.sha1
index 02f9de8303..5d9fbad25f 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.sha1
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/0.5-SNAPSHOT/maven-metadata.xml.sha1
@@ -1 +1 @@
-d8eb4f60a311e78bb6be82426fee0e579176344d \ No newline at end of file
+f2350021d6d3c2091d35d074b6ecd312d6f91657 \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml
index 8fad4186db..4ee3d61cca 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml
@@ -6,6 +6,6 @@
<versions>
<version>0.5-SNAPSHOT</version>
</versions>
- <lastUpdated>20070130111852</lastUpdated>
+ <lastUpdated>20070131112634</lastUpdated>
</versioning>
</metadata> \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.md5 b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.md5
index 5a4b9b2418..39d7b84744 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.md5
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.md5
@@ -1 +1 @@
-4278265ef1e27202cffc5d54d429b510 \ No newline at end of file
+260c92993eec99c2c2c0217cf6241842 \ No newline at end of file
diff --git a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.sha1 b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.sha1
index cef38679a5..bc3857fa21 100644
--- a/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.sha1
+++ b/qpid/java/mvn-repo/uk/co/thebadgerset/junit-toolkit/maven-metadata.xml.sha1
@@ -1 +1 @@
-31c796d63b1c0625d26f5df2ecb44220222546bd \ No newline at end of file
+c8803f171049b2bb3e258f78b8c9490dec3074c4 \ No newline at end of file
diff --git a/qpid/java/perftests/pom.xml b/qpid/java/perftests/pom.xml
index a69acfc451..02f55b43ee 100644
--- a/qpid/java/perftests/pom.xml
+++ b/qpid/java/perftests/pom.xml
@@ -19,6 +19,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-perftests</artifactId>
@@ -35,7 +36,7 @@
<properties>
<topDirectoryLocation>..</topDirectoryLocation>
- <log4j.perftests>perftests.log4j</log4j.perftests>
+ <log4j.perftests>perftests.log4j</log4j.perftests>
</properties>
<!-- Temporary local maven repo, whilst JUnit Toolkit is still reaching stable version to add to central maven repository. -->
@@ -43,7 +44,7 @@
<repository>
<id>junit-toolkit.snapshots</id>
<name>JUnit Toolkit SNAPSHOT Repository</name>
- <url>file://${basedir}/../mvn-repo</url>
+ <url>file://${basedir}/../mvn-repo</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
@@ -55,7 +56,7 @@
<pluginRepository>
<id>junit-toolkit-plugin.snapshots</id>
<name>JUnit Toolkit SNAPSHOT Repository</name>
- <url>file://${basedir}/../mvn-repo</url>
+ <url>file://${basedir}/../mvn-repo</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
@@ -74,15 +75,15 @@
<artifactId>log4j</artifactId>
</dependency>
- <!-- Test dependencies. -->
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
+ <groupId>uk.co.thebadgerset</groupId>
+ <artifactId>junit-toolkit</artifactId>
</dependency>
+ <!-- Test dependencies. -->
<dependency>
- <groupId>uk.co.thebadgerset</groupId>
- <artifactId>junit-toolkit</artifactId>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
</dependency>
</dependencies>
@@ -96,60 +97,57 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <!--<skip>true</skip>-->
- </configuration>
</plugin>
- <!-- The JUnit Toolkit maven2 plugin is in the process of being added to the maven repository. It will take a day or two from 16/1/2007.
+ <!-- The JUnit Toolkit maven2 plugin is in the process of being added to the maven repository.
- Configures the toolkit test runner for performance testing. These can be run from within maven, or by using the generated
+ Configures the toolkit test runner for performance testing. These can be run from within maven, or by using the generated
scripts.
- To run from maven:
-
- mvn uk.co.thebadgerset:junit-toolkit-maven-plugin:tktest
+ To run from within maven:
- To run from the command line (after doing assembly:assembly goal):
+ mvn uk.co.thebadgerset:junit-toolkit-maven-plugin:tktest
- java -cp target/test_jar-jar-with-dependencies.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -s 1 -r 100000 -o target org.apache.qpid.requestreply.PingPongTestPerf
+ To run from the command line (after doing assembly:assembly goal):
- To generate the scripts do:
+ java -cp target/test_jar-jar-with-dependencies.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -s 1 -r 100000
+ -o target org.apache.qpid.requestreply.PingPongTestPerf
- mvn uk.co.thebadgerset:junit-toolkit-maven-plugin:tkscriptgen
+ To generate the scripts do:
- Then to run the scripts do (after doing assembly:assembly goal):
+ mvn uk.co.thebadgerset:junit-toolkit-maven-plugin:tkscriptgen
- ./bin/script_name or ./bin/script_name.bat
+ Then to run the scripts, in the target directory do (after doing assembly:assembly goal):
- These scripts can find everything in the 'all test dependencies' jar created by the assembly:assembly goal.
- -->
+ ./script_name.sh
+ These scripts can find everything in the 'all test dependencies' jar created by the assembly:assembly goal.
+ -->
<plugin>
<groupId>uk.co.thebadgerset</groupId>
- <artifactId>junit-toolkit-maven-plugin</artifactId>
+ <artifactId>junit-toolkit-maven-plugin</artifactId>
<configuration>
- <scriptOutDirectory>target</scriptOutDirectory>
- <testJar>${project.build.finalName}-all-test-deps.jar</testJar>
+ <scriptOutDirectory>target</scriptOutDirectory>
+ <testJar>${project.build.finalName}-all-test-deps.jar</testJar>
<systemproperties>
- <property>
- <name>log4j.configuration</name>
- <value>${log4j.perftests}</value>
- </property>
- <property>
- <name>amqj.logging.level</name>
- <value>warn</value>
- </property>
- <property>
- <name>badger.level</name>
- <value>warn</value>
- </property>
- <property>
- <name>amqj.test.logging.level</name>
- <value>info</value>
- </property>
+ <property>
+ <name>log4j.configuration</name>
+ <value>${log4j.perftests}</value>
+ </property>
+ <property>
+ <name>amqj.logging.level</name>
+ <value>warn</value>
+ </property>
+ <property><!-- Turn off most logging messages from the junit-toolkit test tool itself. -->
+ <name>badger.level</name>
+ <value>warn</value>
+ </property>
+ <property>
+ <name>amqj.test.logging.level</name>
+ <value>info</value>
+ </property>
<property>
<name>logdir</name>
<value>$QPID_WORK/results</value>
@@ -164,25 +162,45 @@
</property>
</systemproperties>
- <commands>
- <!-- Run the ping pong test once. This is just to check toolkit test runner is working. Real tests follow. -->
- <PingOnce>-n PingOnce -s [1] -r 1 -t testPingOk -o . org.apache.qpid.ping.PingTestPerf</PingOnce>
-
- <!-- Tests the accuracy of the throttle implementation at different speeds. Throttle is used to restrict message rate in some tsts. -->
- <ThrottleTest>-n ThrottleTest -r 5 -s [10,10000],samples=100,exp -t testThrottle -o . org.apache.qpid.ping.ThrottleTestPerf</ThrottleTest>
-
- <!--
- Skim Tests.
- These are not part of the performance suite. They run quick tests to check that the different combinations of
- options that the performance suite uses are going to work.
- -->
- <Skim-Tx>-n Skim-Tx -s [1000] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf transacted=true</Skim-Tx>
- <Skim-Size>-n Skim-Size -s [1000] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messagesize=51200</Skim-Size>
- <Skim-Many>-n Skim-Many -s [1] -c [4] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf</Skim-Many>
- <Skim-Queues>-n Skim-Queues -s [1000] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf destinationcount=10</Skim-Queues>
- <Skim-Duration>-n Skim-Duration -s [1000] -d10S -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf</Skim-Duration>
- <Skim-Rate>-n Skim-Rate -s [1000] -d10S -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf rate=100</Skim-Rate>
-
+ <commands>
+ <!-- Single pings. These can be scaled up by overriding the parameters when calling the test script. -->
+ <Ping-Once>-n Ping-Once -s [1] -r 1 -t testPingOk -o . org.apache.qpid.ping.PingTestPerf</Ping-Once>
+ <Ping-Once-Async>-n Ping-Once-Async -s [1] -r 1 -t testAsyncPingOk -o . org.apache.qpid.ping.PingAsyncTestPerf</Ping-Once-Async>
+ <Ping-Latency>-n Ping-Latency -s [1000] -d 10S -t testPingLatency -o . org.apache.qpid.ping.PingLatencyTestPerf</Ping-Latency>
+
+ <!-- More example Tests. These are examples to exercise all the features of the test harness. Can scale up with option overrides. -->
+ <Ping-Tx>-n Ping-Tx -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf transacted=true</Ping-Tx>
+ <Ping-Size>-n Ping-Size -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messagesize=512</Ping-Size>
+ <Ping-Concurrent>-n Ping-Concurrent -s [100] -c [4] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf</Ping-Concurrent>
+ <Ping-Many-Queues>
+ -n Ping-Many-Queues -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf destinationcount=4
+ </Ping-Many-Queues>
+ <Ping-Duration>-n Ping-Duration -s [100] -d10S -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf</Ping-Duration>
+ <Ping-Rate>-n Ping-Rate -s [100] -d10S -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf rate=500</Ping-Rate>
+ <Ping-PubSub>-n Ping-PubSub -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true</Ping-PubSub>
+ <Ping-Many-Topics>
+ -n Ping-Many-Topics -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true destinationcount=4
+ </Ping-Many-Topics>
+ <Ping-Persistent>
+ -n Ping-Persistent -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true
+ </Ping-Persistent>
+ <Ping-Batch-Logging>
+ -n Ping-Batch-Logging -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf BatchSize=10
+ </Ping-Batch-Logging>
+ <Ping-Failover-Before-Send>
+ -n Ping-Failover-Before-Send -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf CommitBatchSize=10 FailBeforeSend=true
+ </Ping-Failover-Before-Send>
+ <Ping-Failover-After-Send>
+ -n Ping-Failover-After-Send -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf CommitBatchSize=10 FailAfterSend=true
+ </Ping-Failover-After-Send>
+ <Ping-Failover-Before-Commit>
+ -n Ping-Failover-Before-Commit -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf CommitBatchSize=10 FailBeforeCommit=true
+ </Ping-Failover-Before-Commit>
+ <Ping-Failover-After-Commit>
+ -n Ping-Failover-After-Commit -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf CommitBatchSize=10 FailAfterCommit=true
+ </Ping-Failover-After-Commit>
+
+
<!-- P2P Volume Tests. -->
<VT-Qpid-1>-n VT-Qpid-1 -s [15000000] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true BatchSize=10000 transacted=true</VT-Qpid-1>
<VT-Qpid-2>-n VT-Qpid-2 -s [15000000] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true BatchSize=10000</VT-Qpid-2>
@@ -323,7 +341,6 @@
</execution>
</executions>
</plugin>
-
<!-- Bundles all the dependencies, fully expanded into a single jar, required to run the tests.
Usefull when bundling system, integration or performance tests into a convenient
@@ -353,7 +370,7 @@
</plugins>
<resources>
- <!-- Include source files in built jar -->
+ <!-- Include source files in built jar -->
<resource>
<targetPath>src/</targetPath>
<filtering>false</filtering>
@@ -362,7 +379,7 @@
<include>**/*.java</include>
</includes>
</resource>
- <!-- Include a log4j configuration in the jar at the root level (don't name this log4j.properties though as won't be able to override it). -->
+ <!-- Include a log4j configuration in the jar at the root level (don't name this log4j.properties though as won't be able to override it). -->
<resource>
<targetPath>/</targetPath>
<filtering>false</filtering>
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingClient.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingClient.java
deleted file mode 100644
index 68dd98ff6b..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingClient.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- *
- * 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.qpid.ping;
-
-import java.io.IOException;
-import java.text.SimpleDateFormat;
-
-import javax.jms.JMSException;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.jms.Session;
-
-/**
- * Provides common functionality that ping clients (the recipients of ping messages) can use. This base class keeps
- * track of the connection used to send pings, provides a convenience method to commit a transaction only when a session
- * to commit on is transactional, keeps track of whether the ping client is pinging to a queue or a topic, provides
- * prompts to the console to terminate brokers before and after commits, in order to test failover functionality, and
- * provides a convience formatter for outputing readable timestamps for pings.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Commit the current transcation on a session.
- * <tr><td> Generate failover promts.
- * <tr><td> Keep track the connection.
- * <tr><td> Keep track of p2p or topic ping type.
- * </table>
- *
- * @todo This base class does not seem particularly usefull and all functionality is duplicated in {@link AbstractPingProducer}.
- * Merge it into that class.
- */
-public abstract class AbstractPingClient
-{
- private static final Logger _logger = Logger.getLogger(TestPingClient.class);
-
- /** A convenient formatter to use when time stamping output. */
- protected static final SimpleDateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS");
-
- /** Holds the connection to the broker. */
- private AMQConnection _connection;
-
- /** Flag used to indicate if this is a point to point or pub/sub ping client. */
- private boolean _isPubSub = false;
-
- /**
- * This flag is used to indicate that the user should be prompted to kill a broker, in order to test
- * failover, immediately before committing a transaction.
- */
- protected boolean _failBeforeCommit = false;
-
- /**
- * This flag is used to indicate that the user should be prompted to a kill a broker, in order to test
- * failover, immediate after committing a transaction.
- */
- protected boolean _failAfterCommit = false;
-
- /**
- * Convenience method to commit the transaction on the specified session. If the session to commit on is not
- * a transactional session, this method does nothing.
- *
- * <p/>If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the
- * commit is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker
- * after the commit is applied.
- *
- * @throws javax.jms.JMSException If the commit fails and then the rollback fails.
- */
- protected void commitTx(Session session) throws JMSException
- {
- if (session.getTransacted())
- {
- try
- {
- if (_failBeforeCommit)
- {
- _logger.trace("Failing Before Commit");
- doFailover();
- }
-
- session.commit();
-
- if (_failAfterCommit)
- {
- _logger.trace("Failing After Commit");
- doFailover();
- }
-
- _logger.trace("Session Commited.");
- }
- catch (JMSException e)
- {
- _logger.trace("JMSException on commit:" + e.getMessage(), e);
-
- try
- {
- session.rollback();
- _logger.debug("Message rolled back.");
- }
- catch (JMSException jmse)
- {
- _logger.trace("JMSE on rollback:" + jmse.getMessage(), jmse);
-
- // Both commit and rollback failed. Throw the rollback exception.
- throw jmse;
- }
- }
- }
- }
-
- /**
- * Prompts the user to terminate the named broker, in order to test failover functionality. This method will block
- * until the user supplied some input on the terminal.
- *
- * @param broker The name of the broker to terminate.
- */
- protected void doFailover(String broker)
- {
- System.out.println("Kill Broker " + broker + " now.");
- try
- {
- System.in.read();
- }
- catch (IOException e)
- { }
-
- System.out.println("Continuing.");
- }
-
- /**
- * Prompts the user to terminate the broker, in order to test failover functionality. This method will block
- * until the user supplied some input on the terminal.
- */
- protected void doFailover()
- {
- System.out.println("Kill Broker now.");
- try
- {
- System.in.read();
- }
- catch (IOException e)
- { }
-
- System.out.println("Continuing.");
-
- }
-
- /**
- * Gets the underlying connection that this ping client is running on.
- *
- * @return The underlying connection that this ping client is running on.
- */
- public AMQConnection getConnection()
- {
- return _connection;
- }
-
- /**
- * Sets the connection that this ping client is using.
- *
- * @param connection The ping connection.
- */
- public void setConnection(AMQConnection connection)
- {
- this._connection = connection;
- }
-
- /**
- * Sets or clears the pub/sub flag to indiciate whether this client is pinging a queue or a topic.
- *
- * @param pubsub <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
- */
- public void setPubSub(boolean pubsub)
- {
- _isPubSub = pubsub;
- }
-
- /**
- * Checks whether this client is a p2p or pub/sub ping client.
- *
- * @return <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
- */
- public boolean isPubSub()
- {
- return _isPubSub;
- }
-}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingProducer.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingProducer.java
deleted file mode 100644
index f9d1deecba..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/AbstractPingProducer.java
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- *
- * 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.qpid.ping;
-
-import java.io.IOException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.jms.*;
-import javax.jms.Connection;
-import javax.jms.Message;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQNoConsumersException;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.message.TestMessageFactory;
-import org.apache.qpid.jms.Session;
-
-/**
- * Provides common functionality that ping producers (the senders of ping messages) can use. This base class keeps
- * track of the connection used to send pings; provides a convenience method to commit a transaction only when a session
- * to commit on is transactional; keeps track of whether the ping client is pinging to a queue or a topic; provides
- * prompts to the console to terminate brokers before and after commits, in order to test failover functionality;
- * requires sub-classes to implement a ping loop, that this provides a run loop to repeatedly call; provides a
- * default shutdown hook to cleanly terminate the run loop; keeps track of the destinations to send pings to;
- * provides a convenience method to generate short pauses; and provides a convience formatter for outputing readable
- * timestamps for pings.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Commit the current transcation on a session.
- * <tr><td> Generate failover promts.
- * <tr><td> Keep track the connection.
- * <tr><td> Keep track of p2p or topic ping type.
- * <tr><td> Call ping loop to repeatedly send pings.
- * <tr><td> Provide a shutdown hook.
- * <tr><td> Generate short pauses.
- * </table>
- *
- * @todo Destination count versus list of desintations is redundant. Use _destinions.size() to get the count and
- * use a list of 1 destination when only 1 is needed. It is only important to distinguish when 1 destination
- * is shared between multiple ping producers on the same JVM or if each ping producer has its own single
- * destination.
- *
- * @todo Timestamp messages in nanos, not millis. Millis seems to have bad resolution, at least on windows.
- */
-public abstract class AbstractPingProducer implements Runnable, ExceptionListener
-{
- private static final Logger _logger = Logger.getLogger(AbstractPingProducer.class);
-
- /** Flag used to indicate if this is a point to point or pub/sub ping client. */
- private boolean _isPubSub = false;
-
- /** A convenient formatter to use when time stamping output. */
- protected static final DateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS");
-
- /**
- * This id generator is used to generate ids to append to the queue name to ensure that queues can be unique when
- * creating multiple ping producers in the same JVM.
- */
- private static AtomicInteger _queueSequenceID = new AtomicInteger();
-
- /** Used to tell the ping loop when to terminate, it only runs while this is true. */
- protected boolean _publish = true;
-
- /** Holds the connection to the broker. */
- private Connection _connection;
-
- /** Holds the producer session, needed to create ping messages. */
- private Session _producerSession;
-
- /** Holds the number of destinations that this ping producer will send pings to, defaulting to a single destination. */
- protected int _destinationCount = 1;
-
- /** Holds the set of destiniations that this ping producer pings. */
- private List<Destination> _destinations = new ArrayList<Destination>();
-
- /** Holds the message producer to send the pings through. */
- protected org.apache.qpid.jms.MessageProducer _producer;
-
- /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a commit. */
- protected boolean _failBeforeCommit = false;
-
- /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a commit. */
- protected boolean _failAfterCommit = false;
-
- /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a send. */
- protected boolean _failBeforeSend = false;
-
- /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a send. */
- protected boolean _failAfterSend = false;
-
- /** Flag used to indicate that failover prompting should only be done on the first commit, not on every commit. */
- protected boolean _failOnce = true;
-
- /** Holds the number of sends that should be performed in every transaction when using transactions. */
- protected int _txBatchSize = 1;
-
- /**
- * Sets or clears the pub/sub flag to indiciate whether this client is pinging a queue or a topic.
- *
- * @param pubsub <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
- */
- public void setPubSub(boolean pubsub)
- {
- _isPubSub = pubsub;
- }
-
- /**
- * Checks whether this client is a p2p or pub/sub ping client.
- *
- * @return <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
- */
- public boolean isPubSub()
- {
- return _isPubSub;
- }
-
- /**
- * Convenience method for a short pause.
- *
- * @param sleepTime The time in milliseconds to pause for.
- */
- public static void pause(long sleepTime)
- {
- if (sleepTime > 0)
- {
- try
- {
- Thread.sleep(sleepTime);
- }
- catch (InterruptedException ie)
- { }
- }
- }
-
- /**
- * Implementations should provide this method to perform a single ping cycle (which may send many messages). The
- * run loop will repeatedly call this method until the publish flag is set to false.
- */
- public abstract void pingLoop();
-
- /**
- * Generates a test message of the specified size, with the specified reply-to destination and persistence flag.
- *
- * @param replyQueue The reply-to destination for the message.
- * @param messageSize The desired size of the message in bytes.
- * @param persistent <tt>true</tt> if the message should use persistent delivery, <tt>false</tt> otherwise.
- *
- * @return A freshly generated test message.
- *
- * @throws JMSException All underlying JMSException are allowed to fall through.
- */
- public ObjectMessage getTestMessage(Destination replyQueue, int messageSize, boolean persistent) throws JMSException
- {
- ObjectMessage msg = TestMessageFactory.newObjectMessage(_producerSession, replyQueue, messageSize, persistent);
- // Timestamp the message.
- msg.setLongProperty("timestamp", System.currentTimeMillis());
-
- return msg;
- }
-
- /**
- * Stops the ping loop by clearing the publish flag. The current loop will complete before it notices that this
- * flag has been cleared.
- */
- public void stop()
- {
- _publish = false;
- }
-
- /**
- * Implements a ping loop that repeatedly pings until the publish flag becomes false.
- */
- public void run()
- {
- // Keep running until the publish flag is cleared.
- while (_publish)
- {
- pingLoop();
- }
- }
-
- /**
- * Callback method, implementing ExceptionListener. This should be registered to listen for exceptions on the
- * connection, this clears the publish flag which in turn will halt the ping loop.
- *
- * @param e The exception that triggered this callback method.
- */
- public void onException(JMSException e)
- {
- _publish = false;
- _logger.debug("There was a JMSException: " + e.getMessage(), e);
- }
-
- /**
- * Gets a shutdown hook that will cleanly shut this down when it is running the ping loop. This can be registered
- * with the runtime system as a shutdown hook.
- *
- * @return A shutdown hook for the ping loop.
- */
- public Thread getShutdownHook()
- {
- return new Thread(new Runnable()
- {
- public void run()
- {
- stop();
- }
- });
- }
-
- /**
- * Gets the underlying connection that this ping client is running on.
- *
- * @return The underlying connection that this ping client is running on.
- */
- public Connection getConnection()
- {
- return _connection;
- }
-
- /**
- * Sets the connection that this ping client is using.
- *
- * @param connection The ping connection.
- */
- public void setConnection(Connection connection)
- {
- this._connection = connection;
- }
-
- /**
- * Gets the producer session that the ping client is using to send pings on.
- *
- * @return The producer session that the ping client is using to send pings on.
- */
- public Session getProducerSession()
- {
- return _producerSession;
- }
-
- /**
- * Keeps track of the producer session that the ping client is using to send pings on.
- *
- * @param session The producer session that the ping client is using to send pings on.
- */
- public void setProducerSession(Session session)
- {
- this._producerSession = session;
- }
-
- /**
- * Gets the number of destinations that this ping client is sending to.
- *
- * @return The number of destinations that this ping client is sending to.
- */
- public int getDestinationsCount()
- {
- return _destinationCount;
- }
-
- /**
- * Sets the number of destination that this ping client should send to.
- *
- * @param count The number of destination that this ping client should send to.
- *
- * @deprectaed Use _destinations.size() instead.
- */
- public void setDestinationsCount(int count)
- {
- this._destinationCount = count;
- }
-
- /**
- * Commits the transaction on the producer session.
- *
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- *
- * @deprecated Use the commitTx(Session session) method instead, to explicitly specify which session is being
- * committed. This makes it more obvious what is going on.
- */
- protected void commitTx() throws JMSException
- {
- commitTx(getProducerSession());
- }
-
- /**
- * Creates the specified number of destinations to send pings to. Topics or Queues will be created depending on
- * the value of the {@link #_isPubSub} flag.
- *
- * @param count The number of ping destinations to create.
- */
- protected void createDestinations(int count)
- {
- // Create the desired number of ping destinations.
- for (int i = 0; i < count; i++)
- {
- AMQDestination destination = null;
-
- // Check if this is a pub/sub pinger, in which case create topics.
- if (isPubSub())
- {
- String name =
- new String("AMQTopic_" + _queueSequenceID.incrementAndGet() + "_" + System.currentTimeMillis());
- destination = new AMQTopic(name);
- }
- // Otherwise this is a p2p pinger, in which case create queues.
- else
- {
- String name =
- new String("AMQQueue_" + _queueSequenceID.incrementAndGet() + "_" + System.currentTimeMillis());
- destination = new AMQQueue(name, name, false, false);
- }
-
- _destinations.add(destination);
- }
- }
-
- /**
- * Returns the destination from the destinations list with the given index.
- *
- * @param index The index of the destination to get.
- *
- * @return Destination with the given index.
- */
- protected Destination getDestination(int index)
- {
- return _destinations.get(index);
- }
-
- /**
- * Convenience method to commit the transaction on the specified session. If the session to commit on is not
- * a transactional session, this method does nothing (unless the failover after send flag is set).
- *
- * <p/>If the {@link #_failAfterSend} flag is set, this will prompt the user to kill the broker before the commit
- * is applied. This flag applies whether the pinger is transactional or not.
- *
- * <p/>If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the
- * commit is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker
- * after the commit is applied. These flags will only apply if using a transactional pinger.
- *
- * @throws javax.jms.JMSException If the commit fails and then the rollback fails.
- *
- * @todo Consider moving the fail after send logic into the send method. It is confusing to have it in this commit
- * method, because commits only apply to transactional pingers, but fail after send applied to transactional
- * and non-transactional alike.
- */
- protected void commitTx(Session session) throws JMSException
- {
- _logger.trace("Batch time reached");
- if (_failAfterSend)
- {
- _logger.trace("Batch size reached");
- if (_failOnce)
- {
- _failAfterSend = false;
- }
-
- _logger.trace("Failing After Send");
- doFailover();
- }
-
- if (session.getTransacted())
- {
- try
- {
- if (_failBeforeCommit)
- {
- if (_failOnce)
- {
- _failBeforeCommit = false;
- }
-
- _logger.trace("Failing Before Commit");
- doFailover();
- }
-
- session.commit();
-
- if (_failAfterCommit)
- {
- if (_failOnce)
- {
- _failAfterCommit = false;
- }
-
- _logger.trace("Failing After Commit");
- doFailover();
- }
-
- _logger.trace("Session Commited.");
- }
- catch (JMSException e)
- {
- _logger.trace("JMSException on commit:" + e.getMessage(), e);
-
- // Warn that the bounce back client is not available.
- if (e.getLinkedException() instanceof AMQNoConsumersException)
- {
- _logger.debug("No consumers on queue.");
- }
-
- try
- {
- session.rollback();
- _logger.trace("Message rolled back.");
- }
- catch (JMSException jmse)
- {
- _logger.trace("JMSE on rollback:" + jmse.getMessage(), jmse);
-
- // Both commit and rollback failed. Throw the rollback exception.
- throw jmse;
- }
- }
- }
- }
-
- /**
- * Sends the specified message to the default destination of the ping producer.
- *
- * @param message The message to send.
- *
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- */
- protected void sendMessage(Message message) throws JMSException
- {
- sendMessage(null, message);
- }
-
- /**
- * Sends the message to the specified destination. If the destination is null, it gets sent to the default destination
- * of the ping producer. If an explicit destination is set, this overrides the default.
- *
- * @param destination The destination to send to.
- * @param message The message to send.
- *
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- */
- protected void sendMessage(Destination destination, Message message) throws JMSException
- {
- if (_failBeforeSend)
- {
- if (_failOnce)
- {
- _failBeforeSend = false;
- }
-
- _logger.trace("Failing Before Send");
- doFailover();
- }
-
- if (destination == null)
- {
- _producer.send(message);
- }
- else
- {
- _producer.send(destination, message);
- }
- }
-
- /**
- * Prompts the user to terminate the named broker, in order to test failover functionality. This method will block
- * until the user supplied some input on the terminal.
- *
- * @param broker The name of the broker to terminate.
- */
- protected void doFailover(String broker)
- {
- System.out.println("Kill Broker " + broker + " now then press return");
- try
- {
- System.in.read();
- }
- catch (IOException e)
- { }
-
- System.out.println("Continuing.");
- }
-
- /**
- * Prompts the user to terminate the broker, in order to test failover functionality. This method will block
- * until the user supplied some input on the terminal.
- */
- protected void doFailover()
- {
- System.out.println("Kill Broker now then press return");
- try
- {
- System.in.read();
- }
- catch (IOException e)
- { }
-
- System.out.println("Continuing.");
- }
-}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java
new file mode 100644
index 0000000000..75ecce861d
--- /dev/null
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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.qpid.ping;
+
+import java.util.List;
+
+import javax.jms.Destination;
+
+import org.apache.qpid.requestreply.PingPongProducer;
+
+/**
+ * PingClient is a {@link PingPongProducer} that does not need a {@link org.apache.qpid.requestreply.PingPongBouncer}
+ * to send replies to its pings. It simply listens to its own ping destinations, rather than seperate reply queues.
+ * It is an all in one ping client, that produces and consumes its own pings.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create a ping pong producer that listens to its own pings <td> {@link PingPongProducer}
+ * </table>
+ */
+public class PingClient extends PingPongProducer
+{
+ /**
+ * Creates a ping producer with the specified parameters, of which there are many. See their individual comments
+ * for details. This constructor creates ping pong producer but de-registers its reply-to destination message
+ * listener, and replaces it by listening to all of its ping destinations.
+ *
+ * @param brokerDetails The URL of the broker to send pings to.
+ * @param username The username to log onto the broker with.
+ * @param password The password to log onto the broker with.
+ * @param virtualpath The virtual host name to use on the broker.
+ * @param destinationName The name (or root where multiple destinations are used) of the desitination to send
+ * pings to.
+ * @param selector The selector to filter replies with.
+ * @param transacted Indicates whether or not pings are sent and received in transactions.
+ * @param persistent Indicates whether pings are sent using peristent delivery.
+ * @param messageSize Specifies the size of ping messages to send.
+ * @param verbose Indicates that information should be printed to the console on every ping.
+ * @param afterCommit Indicates that the user should be promted to terminate a broker after commits to test failover.
+ * @param beforeCommit Indicates that the user should be promted to terminate a broker before commits to test failover.
+ * @param afterSend Indicates that the user should be promted to terminate a broker after sends to test failover.
+ * @param beforeSend Indicates that the user should be promted to terminate a broker before sends to test failover.
+ * @param failOnce Indicates that the failover testing behaviour should only happen on the first commit, not all.
+ * @param txBatchSize Specifies the number of pings to send in each transaction.
+ * @param noOfDestinations The number of destinations to ping. Must be 1 or more.
+ * @param rate Specified the number of pings per second to send. Setting this to 0 means send as fast as
+ * possible, with no rate restriction.
+ * @param pubsub
+ *
+ * @throws Exception Any exceptions are allowed to fall through.
+ */
+ public PingClient(String brokerDetails, String username, String password, String virtualpath, String destinationName,
+ String selector, boolean transacted, boolean persistent, int messageSize, boolean verbose,
+ boolean afterCommit, boolean beforeCommit, boolean afterSend, boolean beforeSend, boolean failOnce,
+ int txBatchSize, int noOfDestinations, int rate, boolean pubsub) throws Exception
+ {
+ super(brokerDetails, username, password, virtualpath, destinationName, selector, transacted, persistent, messageSize,
+ verbose, afterCommit, beforeCommit, afterSend, beforeSend, failOnce, txBatchSize, noOfDestinations, rate,
+ pubsub);
+ }
+
+ /**
+ * Returns the ping destinations themselves as the reply destinations for this pinger to listen to. This has the
+ * effect of making this pinger listen to its own pings.
+ *
+ * @return The ping destinations.
+ */
+ public List<Destination> getReplyDestinations()
+ {
+ return _pingDestinations;
+ }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingClient.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingClient.java
deleted file mode 100644
index 949ace20e1..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingClient.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- *
- * 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.qpid.ping;
-
-import java.net.InetAddress;
-
-import javax.jms.*;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.jms.Session;
-
-/**
- * PingClient is a message listener that received time stamped ping messages. It can work out how long a ping took,
- * provided that its clokc is synchronized to that of the ping producer, or by running it on the same machine (or jvm)
- * as the ping producer.
- * <p/>
- * <p/>There is a verbose mode flag which causes information about each ping to be output to the console
- * (info level logging, so usually console). This can be helpfull to check the bounce backs are happening but should
- * be disabled for real timing tests as writing to the console will slow things down.
- * <p/>
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide command line invocation to start the ping consumer on a configurable broker url.
- * </table>
- *
- * @todo Add a better command line interpreter to the main method. The command line is not very nice...
- */
-class TestPingClient extends AbstractPingClient implements MessageListener
-{
- private static final Logger _logger = Logger.getLogger(TestPingClient.class);
-
- /**
- * Used to indicate that the reply generator should log timing info to the console (logger info level).
- */
- private boolean _verbose = false;
-
- /**
- * The producer session.
- */
- private Session _consumerSession;
-
- /**
- * Creates a TestPingClient on the specified session.
- *
- * @param brokerDetails
- * @param username
- * @param password
- * @param queueName
- * @param virtualpath
- * @param transacted
- * @param selector
- * @param verbose
- * @param afterCommit
- *@param beforeCommit @throws Exception All underlying exceptions allowed to fall through. This is only test code...
- */
- public TestPingClient(String brokerDetails, String username, String password, String queueName, String virtualpath,
- boolean transacted, String selector, boolean verbose, boolean afterCommit, boolean beforeCommit) throws Exception
- {
- // Create a connection to the broker.
- InetAddress address = InetAddress.getLocalHost();
- String clientID = address.getHostName() + System.currentTimeMillis();
-
- setConnection(new AMQConnection(brokerDetails, username, password, clientID, virtualpath));
-
- // Create a transactional or non-transactional session depending on the command line parameter.
- _consumerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE);
-
- // Connect a consumer to the ping queue and register this to be called back by it.
- Queue q = new AMQQueue(queueName);
- MessageConsumer consumer = _consumerSession.createConsumer(q, 1, false, false, selector);
-
- consumer.setMessageListener(this);
-
- // Hang on to the verbose flag setting.
- _verbose = verbose;
-
- // Set failover interrupts
- _failAfterCommit = afterCommit;
- _failBeforeCommit = beforeCommit;
- }
-
- /**
- * Starts a stand alone ping-pong client running in verbose mode.
- *
- * @param args
- */
- public static void main(String[] args) throws Exception
- {
- _logger.info("Starting...");
-
- // Display help on the command line.
- if (args.length < 4)
- {
- System.out.println(
- "Usage: brokerdetails username password virtual-path [queueName] [verbose] [transacted] [selector] [failover:<before|after>:commit]");
- System.exit(1);
- }
-
- // Extract all command line parameters.
- String brokerDetails = args[0];
- String username = args[1];
- String password = args[2];
- String virtualpath = args[3];
- String queueName = (args.length >= 5) ? args[4] : "ping";
- boolean verbose = (args.length >= 6) ? Boolean.parseBoolean(args[5]) : true;
- boolean transacted = (args.length >= 7) ? Boolean.parseBoolean(args[6]) : false;
- String selector = (args.length == 8) ? args[7] : null;
-
- boolean afterCommit = false;
- boolean beforeCommit = false;
-
- for (String arg : args)
- {
- if (arg.startsWith("failover:"))
- {
- //failover:<before|after>:<send:commit>
- String[] parts = arg.split(":");
- if (parts.length == 3)
- {
- if (parts[2].equals("commit"))
- {
- afterCommit = parts[1].equals("after");
- beforeCommit = parts[1].equals("before");
- }
- }
- else
- {
- System.out.println("Unrecognized failover request:" + arg);
- }
- }
- }
-
- // Create the test ping client and set it running.
- TestPingClient pingClient =
- new TestPingClient(brokerDetails, username, password, queueName, virtualpath, transacted, selector, verbose, afterCommit, beforeCommit);
-
- pingClient.getConnection().start();
-
- System.out.println("Waiting...");
- }
- /**
- * This is a callback method that is notified of all messages for which this has been registered as a message
- * listener on a message consumer.
- *
- * @param message The message that triggered this callback.
- */
- public void onMessage(javax.jms.Message message)
- {
- try
- {
- // Spew out some timing information if verbose mode is on.
- if (_verbose)
- {
- Long timestamp = message.getLongProperty("timestamp");
-
- if (timestamp != null)
- {
- long diff = System.currentTimeMillis() - timestamp;
- System.out.println("Ping time: " + diff);
- }
- }
-
- // Commit the transaction if running in transactional mode.
- commitTx(_consumerSession);
- }
- catch (JMSException e)
- {
- _logger.error("There was a JMSException: " + e.getMessage(), e);
- }
- }
-}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingItself.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingItself.java
deleted file mode 100644
index acb0135b86..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingItself.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- *
- * Copyright (c) 2006 The Apache Software Foundation
- *
- * Licensed 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.qpid.ping;
-
-import javax.jms.JMSException;
-import javax.jms.MessageConsumer;
-import javax.jms.ObjectMessage;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.requestreply.PingPongProducer;
-import org.apache.qpid.topic.Config;
-
-/**
- * This class is used to test sending and receiving messages to (pingQueue) and from a queue (replyQueue).
- * The producer and consumer created by this test send and receive messages to and from the same Queue. ie.
- * pingQueue and replyQueue are same.
- * This class extends @see org.apache.qpid.requestreply.PingPongProducer which different ping and reply Queues
- */
-public class TestPingItself extends PingPongProducer
-{
- private static final Logger _logger = Logger.getLogger(TestPingItself.class);
-
- /**
- * If noOfDestinations is <= 1 : There will be one Queue and one consumer instance for the test
- * If noOfDestinations is > 1 : This creats a client for tests with multiple queues. Creates as many consumer instances
- * as there are queues, each listening to a Queue. A producer is created which picks up a queue from
- * the list of queues to send message
- *
- * @param brokerDetails
- * @param username
- * @param password
- * @param virtualpath
- * @param queueName
- * @param selector
- * @param transacted
- * @param persistent
- * @param messageSize
- * @param verbose
- * @param afterCommit
- * @param beforeCommit
- * @param afterSend
- * @param beforeSend
- * @param failOnce
- * @param batchSize
- * @param noOfDestinations
- * @throws Exception
- */
- public TestPingItself(String brokerDetails, String username, String password, String virtualpath, String queueName,
- String selector, boolean transacted, boolean persistent, int messageSize, boolean verbose,
- boolean afterCommit, boolean beforeCommit, boolean afterSend, boolean beforeSend, boolean failOnce,
- int batchSize, int noOfDestinations, int rate, boolean pubsub) throws Exception
- {
- super(brokerDetails, username, password, virtualpath, queueName, selector, transacted, persistent,
- messageSize, verbose, afterCommit, beforeCommit, afterSend, beforeSend, failOnce, batchSize,
- noOfDestinations, rate, pubsub);
-
- if (noOfDestinations > DEFAULT_DESTINATION_COUNT)
- {
- createDestinations(noOfDestinations);
- _persistent = persistent;
- _messageSize = messageSize;
- _verbose = verbose;
-
- createConsumers(selector);
- createProducer();
- }
- }
-
- /**
- * Sets the replyQueue to be the same as ping queue.
- */
- @Override
- public void createConsumer(String selector) throws JMSException
- {
- // Create a message consumer to get the replies with and register this to be called back by it.
- setReplyDestination(getPingDestination());
- MessageConsumer consumer =
- getConsumerSession().createConsumer(getReplyDestination(), PREFETCH, false, EXCLUSIVE, selector);
- consumer.setMessageListener(this);
- }
-
- /**
- * Starts a ping-pong loop running from the command line.
- *
- * @param args The command line arguments as defined above.
- */
- public static void main(String[] args) throws Exception
- {
- // Extract the command line.
- Config config = new Config();
- config.setOptions(args);
- if (args.length == 0)
- {
- _logger.info("Running test with default values...");
- }
-
- String brokerDetails = config.getHost() + ":" + config.getPort();
- String virtualpath = "/test";
- boolean verbose = true;
- boolean transacted = config.isTransacted();
- boolean persistent = config.usePersistentMessages();
- int messageSize = (config.getPayload() != 0) ? config.getPayload() : DEFAULT_MESSAGE_SIZE;
- int messageCount = config.getMessages();
- int destCount = (config.getDestinationsCount() != 0) ? config.getDestinationsCount() : DEFAULT_DESTINATION_COUNT;
- int batchSize = (config.getBatchSize() != 0) ? config.getBatchSize() : DEFAULT_BATCH_SIZE;
- int rate = (config.getRate() != 0) ? config.getRate() : DEFAULT_RATE;
- boolean pubsub = config.isPubSub();
-
- String destName = config.getDestination();
- if (destName == null)
- {
- destName = PING_DESTINATION_NAME;
- }
-
- boolean afterCommit = false;
- boolean beforeCommit = false;
- boolean afterSend = false;
- boolean beforeSend = false;
- boolean failOnce = false;
-
- for (String arg : args)
- {
- if (arg.startsWith("failover:"))
- {
- //failover:<before|after>:<send:commit>
- String[] parts = arg.split(":");
- if (parts.length == 3)
- {
- if (parts[2].equals("commit"))
- {
- afterCommit = parts[1].equals("after");
- beforeCommit = parts[1].equals("before");
- }
-
- if (parts[2].equals("send"))
- {
- afterSend = parts[1].equals("after");
- beforeSend = parts[1].equals("before");
- }
-
- if (parts[1].equals("once"))
- {
- failOnce = true;
- }
-
- }
- else
- {
- System.out.println("Unrecognized failover request:" + arg);
- }
- }
- }
-
- // Create a ping producer to handle the request/wait/reply cycle.
- TestPingItself pingItself = new TestPingItself(brokerDetails, "guest", "guest", virtualpath, destName, null,
- transacted, persistent, messageSize, verbose, afterCommit,
- beforeCommit, afterSend, beforeSend, failOnce, batchSize,
- destCount, rate, pubsub);
-
- pingItself.getConnection().start();
-
- // Create a shutdown hook to terminate the ping-pong producer.
- Runtime.getRuntime().addShutdownHook(pingItself.getShutdownHook());
-
- // Ensure that the ping pong producer is registered to listen for exceptions on the connection too.
- pingItself.getConnection().setExceptionListener(pingItself);
-
- if ((destCount > DEFAULT_DESTINATION_COUNT) || (messageCount > 0))
- {
- _logger.info("Destinations Count:" + destCount + ", Transacted:" + transacted + ", persistent:" +
- persistent + ",Message Size:" + messageSize + " bytes, pubsub:" + pubsub);
- pingItself.pingLoop();
- }
- else
- {
- _logger.info("Destination:" + destName + ", Transacted:" + transacted + ", persistent:" +
- persistent + ",Message Size:" + messageSize + " bytes, pubsub:" + pubsub);
- // set the message count to 0 to run this loop
- // Run a few priming pings to remove warm up time from test results.
- pingItself.prime(PRIMING_LOOPS);
-
- _logger.info("Running the infinite loop and pinging the broker...");
- // Create the ping loop thread and run it until it is terminated by the shutdown hook or exception.
- Thread pingThread = new Thread(pingItself);
- pingThread.run();
- pingThread.join();
- }
-
- pingItself.getConnection().close();
- }
-
- private static void usage()
- {
- System.err.println("Usage: TestPingPublisher \n" + "-host : broker host" + "-port : broker port" +
- "-destinationname : queue/topic name\n" +
- "-transacted : (true/false). Default is false\n" +
- "-persistent : (true/false). Default is false\n" +
- "-pubsub : (true/false). Default is false\n" +
- "-selector : selector string\n" +
- "-payload : paylaod size. Default is 0\n" +
- "-messages : no of messages to be sent (if 0, the ping loop will run indefinitely)\n" +
- "-destinationscount : no of destinations for multi-destinations test\n" +
- "-batchsize : batch size\n" +
- "-rate : thruput rate\n");
- System.exit(0);
- }
-}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingProducer.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingProducer.java
deleted file mode 100644
index d9e81d39de..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingProducer.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- *
- * 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.qpid.ping;
-
-import java.net.InetAddress;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import javax.jms.*;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.jms.MessageProducer;
-import org.apache.qpid.jms.Session;
-
-/**
- * PingProducer is a client that sends timestamped pings to a queue. It is designed to be run from the command line
- * as a stand alone test tool, but it may also be fairly easily instantiated by other code by supplying a session and
- * configured message producer.
- * <p/>
- * <p/>This implements the Runnable interface with a run method that implements an infinite ping loop. The ping loop
- * does all its work through helper methods, so that code wishing to run a ping cycle is not forced to do so
- * by starting a new thread. The command line invocation does take advantage of this ping loop. A shutdown hook is
- * also registered to terminate the ping loop cleanly.
- * <p/>
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide a ping cycle.
- * <tr><td> Provide command line invocation to loop the ping cycle on a configurable broker url.
- * </table>
- */
-class TestPingProducer extends AbstractPingProducer
-{
- private static final Logger _logger = Logger.getLogger(TestPingProducer.class);
-
- /**
- * Used to set up a default message size.
- */
- private static final int DEFAULT_MESSAGE_SIZE = 0;
-
- /**
- * Used to define how long to wait between pings.
- */
- private static final long SLEEP_TIME = 250;
-
- /**
- * Holds the name of the queue to send pings on.
- */
- private static final String PING_QUEUE_NAME = "ping";
-
- private static TestPingProducer _pingProducer;
-
- /**
- * Determines whether this producer sends persistent messages from the run method.
- */
- private boolean _persistent = false;
-
- /**
- * Holds the message size to send, from the run method.
- */
- private int _messageSize = DEFAULT_MESSAGE_SIZE;
-
- /**
- * Used to indicate that the ping loop should print out whenever it pings.
- */
- private boolean _verbose = false;
-
- public TestPingProducer(String brokerDetails, String username, String password, String virtualpath, String queueName,
- boolean transacted, boolean persistent, int messageSize, boolean verbose, boolean afterCommit,
- boolean beforeCommit, boolean afterSend, boolean beforeSend, boolean failOnce, int batchSize)
- throws Exception
- {
- // Create a connection to the broker.
- InetAddress address = InetAddress.getLocalHost();
- String clientID = address.getHostName() + System.currentTimeMillis();
-
- setConnection(new AMQConnection(brokerDetails, username, password, clientID, virtualpath));
-
- // Create a transactional or non-transactional session, based on the command line arguments.
- setProducerSession((Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE));
-
- // Create a queue to send the pings on.
- Queue pingQueue = new AMQQueue(queueName);
- _producer = (MessageProducer) getProducerSession().createProducer(pingQueue);
-
- _persistent = persistent;
- _messageSize = messageSize;
-
- _verbose = verbose;
-
- // Set failover interrupts
- _failAfterCommit = afterCommit;
- _failBeforeCommit = beforeCommit;
- _failAfterSend = afterSend;
- _failBeforeSend = beforeSend;
- _txBatchSize = batchSize;
- _failOnce = failOnce;
- }
-
- /**
- * Starts a ping-pong loop running from the command line. The bounce back client {@link TestPingClient} also needs
- * to be started to bounce the pings back again.
- *
- * @param args The command line arguments as defined above.
- */
- public static void main(String[] args) throws Exception
- {
- // Extract the command line.
- if (args.length < 2)
- {
- System.err.println(
- "Usage: TestPingPublisher <brokerDetails> <virtual path> "
- + "[<verbose(true|false)> <transacted(true|false))> <persistent(true|false)> <message size in bytes> <batchsize>");
- System.exit(0);
- }
-
- String brokerDetails = args[0];
- String virtualpath = args[1];
- boolean verbose = (args.length >= 3) ? Boolean.parseBoolean(args[2]) : true;
- boolean transacted = (args.length >= 4) ? Boolean.parseBoolean(args[3]) : false;
- boolean persistent = (args.length >= 5) ? Boolean.parseBoolean(args[4]) : false;
- int messageSize = (args.length >= 6) ? Integer.parseInt(args[5]) : DEFAULT_MESSAGE_SIZE;
- int batchSize = (args.length >= 7) ? Integer.parseInt(args[6]) : 1;
-
- boolean afterCommit = false;
- boolean beforeCommit = false;
- boolean afterSend = false;
- boolean beforeSend = false;
- boolean failOnce = false;
-
- for (String arg : args)
- {
- if (arg.startsWith("failover:"))
- {
- //failover:<before|after>:<send:commit>
- String[] parts = arg.split(":");
- if (parts.length == 3)
- {
- if (parts[2].equals("commit"))
- {
- afterCommit = parts[1].equals("after");
- beforeCommit = parts[1].equals("before");
- }
-
- if (parts[2].equals("send"))
- {
- afterSend = parts[1].equals("after");
- beforeSend = parts[1].equals("before");
- }
-
- if (parts[1].equals("once"))
- {
- failOnce = true;
- }
- }
- else
- {
- System.out.println("Unrecognized failover request:" + arg);
- }
- }
- }
-
- // Create a ping producer to generate the pings.
- _pingProducer = new TestPingProducer(brokerDetails, "guest", "guest", virtualpath, PING_QUEUE_NAME, transacted,
- persistent, messageSize, verbose, afterCommit, beforeCommit, afterSend,
- beforeSend, failOnce, batchSize);
-
- // Start the connection running.
- _pingProducer.getConnection().start();
-
- // Create a shutdown hook to terminate the ping-pong producer.
- Runtime.getRuntime().addShutdownHook(_pingProducer.getShutdownHook());
-
- // Ensure the ping loop execption listener is registered on the connection to terminate it on error.
- _pingProducer.getConnection().setExceptionListener(_pingProducer);
-
- // Start the ping loop running until it is interrupted.
- Thread pingThread = new Thread(_pingProducer);
- pingThread.run();
- pingThread.join();
- }
-
- /**
- * Sends the specified ping message.
- *
- * @param message The message to send.
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- */
- public void ping(Message message) throws JMSException
- {
- sendMessage(message);
-
- // Keep the messageId to correlate with the reply.
- String messageId = message.getJMSMessageID();
-
- // Commit the transaction if running in transactional mode. This must happen now, rather than at the end of
- // this method, as the message will not be sent until the transaction is committed.
- commitTx();
- }
-
- /**
- * The ping loop implementation. This send out pings of the configured size, persistence and transactionality, and
- * waits for short pauses in between each.
- */
- public void pingLoop()
- {
- try
- {
- // Generate a sample message and time stamp it.
- ObjectMessage msg = getTestMessage(null, _messageSize, _persistent);
- msg.setLongProperty("timestamp", System.currentTimeMillis());
-
- // Send the message.
- ping(msg);
-
- if (_verbose)
- {
- System.out.println("Pinged at: " + timestampFormatter.format(new Date())); //" + " with id: " + msg.getJMSMessageID());
- }
- // Introduce a short pause if desired.
- pause(SLEEP_TIME);
- }
- catch (JMSException e)
- {
- _publish = false;
- _logger.error("There was a JMSException: " + e.getMessage(), e);
- }
- }
-}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingPublisher.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingPublisher.java
deleted file mode 100644
index 3b2dcc4d36..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingPublisher.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- *
- * 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.qpid.pingpong;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.url.URLSyntaxException;
-import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.BasicMessageProducer;
-import org.apache.qpid.client.message.TestMessageFactory;
-import org.apache.qpid.jms.MessageProducer;
-import org.apache.qpid.jms.Session;
-
-import javax.jms.*;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * A client that behaves as follows:
- * <ul><li>Connects to a queue, whose name is specified as a cmd-line argument</li>
- * <li>Creates a temporary queue</li>
- * <li>Creates messages containing a property that is the name of the temporary queue</li>
- * <li>Fires off a message on the original queue and waits for a response on the temporary queue</li>
- * </ul>
- */
-public class TestPingPublisher implements ExceptionListener
-{
- private static final Logger _log = Logger.getLogger(TestPingPublisher.class);
-
- private AMQConnection _connection;
-
- private boolean _publish;
- private static int _messageSize = 0;
- private long SLEEP_TIME = 0L;
-
-// private class CallbackHandler implements MessageListener
-// {
-//
-// private int _actualMessageCount;
-//
-//
-// public void onMessage(Message m)
-// {
-// if (_log.isDebugEnabled())
-// {
-// _log.debug("Message received: " + m);
-// }
-// _actualMessageCount++;
-// if (_actualMessageCount % 1000 == 0)
-// {
-// _log.info("Received message count: " + _actualMessageCount);
-// }
-// }
-// }
-
- public TestPingPublisher(String brokerDetails, String clientID, String virtualpath) throws AMQException, URLSyntaxException
- {
- try
- {
- createConnection(brokerDetails, clientID, virtualpath);
-
- Session session = (Session) _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- //AMQQueue destination = new AMQQueue("ping");
- AMQTopic destination = new AMQTopic("ping");
- MessageProducer producer = (MessageProducer) session.createProducer(destination);
-
- _connection.setExceptionListener(this);
-
- _connection.start();
-
- int msgCount = 0;
- while (_publish)
- {
-/*
- TextMessage msg = session.createTextMessage(
- "Presented to in conjunction with Mahnah Mahnah and the Snowths: " + ++messageNumber);
-*/
- ObjectMessage msg = null;
- if (_messageSize != 0)
- {
- msg = TestMessageFactory.newObjectMessage(session, _messageSize);
- }
- else
- {
- msg = session.createObjectMessage();
- }
-
- Long time = System.nanoTime();
- msg.setStringProperty("timestampString", Long.toString(time));
- msg.setLongProperty("timestamp", time);
-
- ((BasicMessageProducer) producer).send(msg, DeliveryMode.PERSISTENT, true);
-
- _log.info("Message Sent:" + msgCount++);
- _log.debug(msg);
-
- if (msgCount == Integer.MAX_VALUE)
- {
- _publish = false;
- }
-
- if (SLEEP_TIME > 0)
- {
- try
- {
- Thread.sleep(SLEEP_TIME);
- }
- catch (InterruptedException ie)
- {
- //do nothing
- }
- }
- }
-
- }
- catch (JMSException e)
- {
- e.printStackTrace();
- }
- }
-
- private void createConnection(String brokerDetails, String clientID, String virtualpath) throws AMQException, URLSyntaxException
- {
- _publish = true;
- _connection = new AMQConnection(brokerDetails, "guest", "guest", clientID, virtualpath);
- _log.info("Connected with URL:" + _connection.toURL());
- }
-
- /**
- * @param args argument 1 if present specifies the name of the temporary queue to create. Leaving it blank
- * means the server will allocate a name.
- */
- public static void main(String[] args)
- {
- if (args.length < 2)
- {
- System.err.println("Usage: TestPingPublisher <brokerDetails> <virtual path> [message size in bytes]");
- System.exit(0);
- }
- try
- {
- InetAddress address = InetAddress.getLocalHost();
- String clientID = address.getHostName() + System.currentTimeMillis();
- if (args.length > 2 )
- {
- _messageSize = Integer.parseInt(args[2]);
- }
- new TestPingPublisher(args[0], clientID, args[1]);
- }
- catch (UnknownHostException e)
- {
- e.printStackTrace();
- }
- catch (AMQException e)
- {
- System.err.println("Error in client: " + e);
- e.printStackTrace();
- }
- catch (URLSyntaxException e)
- {
- System.err.println("Error in connection arguments : " + e);
- }
-
- //System.exit(0);
- }
-
- /**
- * @see javax.jms.ExceptionListener#onException(javax.jms.JMSException)
- */
- public void onException(JMSException e)
- {
- System.err.println(e.getMessage());
-
- _publish = false;
- e.printStackTrace(System.err);
- }
-}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingSubscriber.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingSubscriber.java
deleted file mode 100644
index b43319744a..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/TestPingSubscriber.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- *
- * 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.qpid.pingpong;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.Level;
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.jms.Session;
-
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.Topic;
-import javax.jms.JMSException;
-import java.net.InetAddress;
-
-public class TestPingSubscriber
-{
- private static final Logger _logger = Logger.getLogger(TestPingSubscriber.class);
-
- private static class TestPingMessageListener implements MessageListener
- {
- public TestPingMessageListener()
- {
- }
-
- long _lastTimestamp = 0L;
- long _lastTimestampString = 0L;
-
- public void onMessage(javax.jms.Message message)
- {
- Long time = System.nanoTime();
-
- if (_logger.isInfoEnabled())
- {
- long timestampString = 0L;
-
- try
- {
- long timestamp = message.getLongProperty("timestamp");
- timestampString = Long.parseLong(message.getStringProperty("timestampString"));
-
- if (timestampString != timestamp)
- {
- _logger.info("Timetamps differ!:\n" +
- "timestamp:" + timestamp + "\n" +
- "timestampString:" + timestampString);
- }
-
- }
- catch (JMSException jmse)
- {
- _logger.error("JMSException caught:" + jmse.getMessage(), jmse);
- }
-
-
- long stringDiff = time - timestampString;
-
- _logger.info("Ping: TS:" + stringDiff / 1000 + "us");
-
- // _logger.info(_name + " got message '" + message + "\n");
- }
- }
- }
-
- public static void main(String[] args)
- {
- _logger.info("Starting...");
-
- if (args.length < 4)
- {
- System.out.println("Usage: brokerdetails username password virtual-path [selector] ");
- System.exit(1);
- }
- try
- {
- InetAddress address = InetAddress.getLocalHost();
- AMQConnection con1 = new AMQConnection(args[0], args[1], args[2],
- address.getHostName(), args[3]);
-
- _logger.info("Connected with URL:" + con1.toURL());
-
- final org.apache.qpid.jms.Session session1 = (org.apache.qpid.jms.Session)
- con1.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
-
- String selector = null;
-
- if (args.length == 5)
- {
- selector = args[4];
- _logger.info("Message selector is <" + selector + ">...");
- }
- else
- {
- _logger.info("Not using message selector ");
- }
-
- Topic t = new AMQTopic("ping");
-
- MessageConsumer consumer1 = session1.createConsumer(t,
- 1, false, false, selector);
-
- consumer1.setMessageListener(new TestPingMessageListener());
- con1.start();
- }
- catch (Throwable t)
- {
- System.err.println("Fatal error: " + t);
- t.printStackTrace();
- }
-
- System.out.println("Waiting...");
- }
-}
-
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/Throttle.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/Throttle.java
deleted file mode 100644
index a33ba4557a..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/Throttle.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.apache.qpid.ping;
-
-/**
- * Throttle is a helper class used in situations where a controlled rate of processing is desired. It allows a certain
- * number of operations-per-second to be defined and supplies a {@link #throttle} method that can only be called at
- * most at that rate. The first call to the throttle method will return immediately, subsequent calls will introduce
- * a short pause to fill out the remainder of the current cycle to attain the desired rate. If there is no remainder
- * left then it will return immediately.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- *
- * @author Rupert Smith
- */
-public class Throttle
-{
- /** Holds the length of the cycle in nano seconds. */
- long cycleLengthNanos = 0L;
-
- /** Records the nano time of the last call to the throttle method. */
- long lastTimeNanos = 0L;
-
- /**
- * Sets up the desired rate of operation per second that the throttle method should restrict to.
- *
- * @param opsPerSecond The maximum number of calls per second that the throttle method will take.
- */
- public void setRate(int opsPerSecond)
- {
- // Calculate the length of a cycle.
- cycleLengthNanos = 1000000000 / opsPerSecond;
- }
-
- /**
- * Introduces a short pause to fill out any time left in the cycle since this method was last called, of length
- * defined by a call to the {@link #setRate} method.
- */
- public void throttle()
- {
- // Record the time now.
- long currentTimeNanos = System.nanoTime();
-
- // Check if there is any time remaining in the current cycle and introduce a short wait to fill out the
- // remainder of the cycle if needed.
- long remainingTimeNanos = cycleLengthNanos - (currentTimeNanos - lastTimeNanos);
-
- if (remainingTimeNanos > 0)
- {
- long milliWait = remainingTimeNanos / 1000000;
- int nanoWait = (int) (remainingTimeNanos % 1000000);
-
- try
- {
- Thread.currentThread().sleep(milliWait, nanoWait);
- }
- catch (InterruptedException e)
- {
- // Just ignore this?
- }
- }
-
- // Keep the time of the last call to this method to calculate the next cycle.
- //lastTimeNanos = currentTimeNanos;
- lastTimeNanos = System.nanoTime();
- }
-}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java
index 0fde5c6c3c..347b81cd50 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java
@@ -20,7 +20,9 @@
*/
package org.apache.qpid.requestreply;
+import java.io.IOException;
import java.net.InetAddress;
+import java.text.SimpleDateFormat;
import java.util.Date;
import javax.jms.*;
@@ -32,7 +34,6 @@ import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQTopic;
import org.apache.qpid.jms.ConnectionListener;
import org.apache.qpid.jms.Session;
-import org.apache.qpid.ping.AbstractPingClient;
import org.apache.qpid.topic.Config;
/**
@@ -58,7 +59,7 @@ import org.apache.qpid.topic.Config;
*
* @todo Make verbose accept a number of messages, only prints to console every X messages.
*/
-public class PingPongBouncer extends AbstractPingClient implements MessageListener
+public class PingPongBouncer implements MessageListener
{
private static final Logger _logger = Logger.getLogger(PingPongBouncer.class);
@@ -73,6 +74,9 @@ public class PingPongBouncer extends AbstractPingClient implements MessageListen
/** The default exclusive flag for the message consumer. */
private static final boolean EXCLUSIVE = false;
+ /** A convenient formatter to use when time stamping output. */
+ protected static final SimpleDateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS");
+
/** Used to indicate that the reply generator should log timing info to the console (logger info level). */
private boolean _verbose = false;
@@ -93,6 +97,24 @@ public class PingPongBouncer extends AbstractPingClient implements MessageListen
/** The producer session. */
private Session _producerSession;
+ /** Holds the connection to the broker. */
+ private AMQConnection _connection;
+
+ /** Flag used to indicate if this is a point to point or pub/sub ping client. */
+ private boolean _isPubSub = false;
+
+ /**
+ * This flag is used to indicate that the user should be prompted to kill a broker, in order to test
+ * failover, immediately before committing a transaction.
+ */
+ protected boolean _failBeforeCommit = false;
+
+ /**
+ * This flag is used to indicate that the user should be prompted to a kill a broker, in order to test
+ * failover, immediate after committing a transaction.
+ */
+ protected boolean _failAfterCommit = false;
+
/**
* Creates a PingPongBouncer on the specified producer and consumer sessions.
*
@@ -110,8 +132,8 @@ public class PingPongBouncer extends AbstractPingClient implements MessageListen
* @throws Exception All underlying exceptions allowed to fall through. This is only test code...
*/
public PingPongBouncer(String brokerDetails, String username, String password, String virtualpath,
- String destinationName, boolean persistent, boolean transacted, String selector,
- boolean verbose, boolean pubsub) throws Exception
+ String destinationName, boolean persistent, boolean transacted, String selector, boolean verbose,
+ boolean pubsub) throws Exception
{
// Create a client id to uniquely identify this client.
InetAddress address = InetAddress.getLocalHost();
@@ -133,7 +155,8 @@ public class PingPongBouncer extends AbstractPingClient implements MessageListen
// Create the queue to listen for message on.
createConsumerDestination(destinationName);
- MessageConsumer consumer = _consumerSession.createConsumer(_consumerDestination, PREFETCH, NO_LOCAL, EXCLUSIVE, selector);
+ MessageConsumer consumer =
+ _consumerSession.createConsumer(_consumerDestination, PREFETCH, NO_LOCAL, EXCLUSIVE, selector);
// Create a producer for the replies, without a default destination.
_replyProducer = _producerSession.createProducer(null);
@@ -144,18 +167,6 @@ public class PingPongBouncer extends AbstractPingClient implements MessageListen
consumer.setMessageListener(this);
}
- private void createConsumerDestination(String name)
- {
- if (isPubSub())
- {
- _consumerDestination = new AMQTopic(name);
- }
- else
- {
- _consumerDestination = new AMQQueue(name);
- }
- }
-
/**
* Starts a stand alone ping-pong client running in verbose mode.
*
@@ -177,12 +188,13 @@ public class PingPongBouncer extends AbstractPingClient implements MessageListen
Config config = new Config();
config.setOptions(args);
String brokerDetails = config.getHost() + ":" + config.getPort();
- String virtualpath = "/test";
+ String virtualpath = "test";
String destinationName = config.getDestination();
if (destinationName == null)
{
destinationName = DEFAULT_DESTINATION_NAME;
}
+
String selector = config.getSelector();
boolean transacted = config.isTransacted();
boolean persistent = config.usePersistentMessages();
@@ -192,13 +204,22 @@ public class PingPongBouncer extends AbstractPingClient implements MessageListen
//String selector = null;
// Instantiate the ping pong client with the command line options and start it running.
- PingPongBouncer pingBouncer = new PingPongBouncer(brokerDetails, "guest", "guest", virtualpath,
- destinationName, persistent, transacted, selector, verbose, pubsub);
+ PingPongBouncer pingBouncer =
+ new PingPongBouncer(brokerDetails, "guest", "guest", virtualpath, destinationName, persistent, transacted,
+ selector, verbose, pubsub);
pingBouncer.getConnection().start();
System.out.println("Waiting...");
}
+ private static void usage()
+ {
+ System.err.println("Usage: PingPongBouncer \n" + "-host : broker host\n" + "-port : broker port\n"
+ + "-destinationname : queue/topic name\n" + "-transacted : (true/false). Default is false\n"
+ + "-persistent : (true/false). Default is false\n"
+ + "-pubsub : (true/false). Default is false\n" + "-selector : selector string\n");
+ }
+
/**
* This is a callback method that is notified of all messages for which this has been registered as a message
* listener on a message consumer. It sends a reply (pong) to all messages it receieves on the reply to
@@ -260,14 +281,145 @@ public class PingPongBouncer extends AbstractPingClient implements MessageListen
}
}
- private static void usage()
+ /**
+ * Gets the underlying connection that this ping client is running on.
+ *
+ * @return The underlying connection that this ping client is running on.
+ */
+ public AMQConnection getConnection()
+ {
+ return _connection;
+ }
+
+ /**
+ * Sets the connection that this ping client is using.
+ *
+ * @param connection The ping connection.
+ */
+ public void setConnection(AMQConnection connection)
+ {
+ this._connection = connection;
+ }
+
+ /**
+ * Sets or clears the pub/sub flag to indiciate whether this client is pinging a queue or a topic.
+ *
+ * @param pubsub <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
+ */
+ public void setPubSub(boolean pubsub)
+ {
+ _isPubSub = pubsub;
+ }
+
+ /**
+ * Checks whether this client is a p2p or pub/sub ping client.
+ *
+ * @return <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
+ */
+ public boolean isPubSub()
+ {
+ return _isPubSub;
+ }
+
+ /**
+ * Convenience method to commit the transaction on the specified session. If the session to commit on is not
+ * a transactional session, this method does nothing.
+ *
+ * <p/>If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the
+ * commit is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker
+ * after the commit is applied.
+ *
+ * @throws javax.jms.JMSException If the commit fails and then the rollback fails.
+ */
+ protected void commitTx(Session session) throws JMSException
+ {
+ if (session.getTransacted())
+ {
+ try
+ {
+ if (_failBeforeCommit)
+ {
+ _logger.trace("Failing Before Commit");
+ doFailover();
+ }
+
+ session.commit();
+
+ if (_failAfterCommit)
+ {
+ _logger.trace("Failing After Commit");
+ doFailover();
+ }
+
+ _logger.trace("Session Commited.");
+ }
+ catch (JMSException e)
+ {
+ _logger.trace("JMSException on commit:" + e.getMessage(), e);
+
+ try
+ {
+ session.rollback();
+ _logger.debug("Message rolled back.");
+ }
+ catch (JMSException jmse)
+ {
+ _logger.trace("JMSE on rollback:" + jmse.getMessage(), jmse);
+
+ // Both commit and rollback failed. Throw the rollback exception.
+ throw jmse;
+ }
+ }
+ }
+ }
+
+ /**
+ * Prompts the user to terminate the named broker, in order to test failover functionality. This method will block
+ * until the user supplied some input on the terminal.
+ *
+ * @param broker The name of the broker to terminate.
+ */
+ protected void doFailover(String broker)
+ {
+ System.out.println("Kill Broker " + broker + " now.");
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ { }
+
+ System.out.println("Continuing.");
+ }
+
+ /**
+ * Prompts the user to terminate the broker, in order to test failover functionality. This method will block
+ * until the user supplied some input on the terminal.
+ */
+ protected void doFailover()
{
- System.err.println("Usage: PingPongBouncer \n" + "-host : broker host\n" + "-port : broker port\n" +
- "-destinationname : queue/topic name\n" +
- "-transacted : (true/false). Default is false\n" +
- "-persistent : (true/false). Default is false\n" +
- "-pubsub : (true/false). Default is false\n" +
- "-selector : selector string\n");
+ System.out.println("Kill Broker now.");
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ { }
+
+ System.out.println("Continuing.");
+
+ }
+
+ private void createConsumerDestination(String name)
+ {
+ if (isPubSub())
+ {
+ _consumerDestination = new AMQTopic(name);
+ }
+ else
+ {
+ _consumerDestination = new AMQQueue(name);
+ }
}
/**
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
index fb0ae19767..6141272d70 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
@@ -20,344 +20,382 @@
*/
package org.apache.qpid.requestreply;
+import java.io.IOException;
import java.net.InetAddress;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import javax.jms.*;
import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.message.TestMessageFactory;
import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.jms.ConnectionListener;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQNoConsumersException;
import org.apache.qpid.jms.MessageProducer;
import org.apache.qpid.jms.Session;
-import org.apache.qpid.ping.AbstractPingProducer;
-import org.apache.qpid.ping.Throttle;
import org.apache.qpid.topic.Config;
+import uk.co.thebadgerset.junit.extensions.BatchedThrottle;
+import uk.co.thebadgerset.junit.extensions.Throttle;
+
/**
* PingPongProducer is a client that sends pings to a queue and waits for pongs to be bounced back by a bounce back
- * client (see {@link PingPongBouncer} for the bounce back client). It is designed to be run from the command line
- * as a stand alone test tool, but it may also be fairly easily instantiated by other code by supplying a session,
- * message producer and message consumer to run the ping-pong cycle on.
- * <p/>
+ * client (see {@link PingPongBouncer} for the bounce back client).
+ *
* <p/>The pings are sent with a reply-to field set to a single temporary queue, which is the same for all pings.
* This means that this class has to do some work to correlate pings with pongs; it expectes the original message
- * id in the ping to be bounced back in the correlation id. If a new temporary queue per ping were used, then
- * this correlation would not need to be done.
- * <p/>
+ * correlation id in the ping to be bounced back in the reply correlation id.
+ *
+ * <p/>This ping tool accepts a vast number of configuration options, all of which are passed in to the constructor.
+ * It can ping topics or queues; ping multiple destinations; do persistent pings; send messages of any size; do pings
+ * within transactions; control the number of pings to send in each transaction; limit its sending rate; and perform
+ * failover testing.
+ *
* <p/>This implements the Runnable interface with a run method that implements an infinite ping loop. The ping loop
* does all its work through helper methods, so that code wishing to run a ping-pong cycle is not forced to do so
* by starting a new thread. The command line invocation does take advantage of this ping loop. A shutdown hook is
* also registered to terminate the ping-pong loop cleanly.
- * <p/>
+ *
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide a ping and wait for response cycle.
+ * <tr><td> Provide a ping and wait for all responses cycle.
* <tr><td> Provide command line invocation to loop the ping cycle on a configurable broker url.
* </table>
*
- * @todo Make temp queue per ping a command line option.
- * @todo Make the queue name a command line option.
+ * @todo The use of a ping rate {@link #DEFAULT_RATE} and waits between pings {@link #DEFAULT_SLEEP_TIME} are overlapping.
+ * Use the rate and throttling only. Ideally, optionally pass the rate throttle into the ping method, throttle to
+ * be created and configured by the test runner from the -f command line option and made available through
+ * the timing controller on timing aware tests or by throttling rate of calling tests methods on non-timing aware
+ * tests.
+ *
+ * @todo Make shared or unique destinations a configurable option, hard coded to false.
+ *
+ * @todo Make acknowledege mode a test option.
+ *
+ * @todo Make the message listener a static for all replies to be sent to. It won't be any more of a bottle neck than
+ * having one per PingPongProducer, as will synchronize on message correlation id, allowing threads to process
+ * messages concurrently for different ids. Needs to be static so that when using a chained message listener and
+ * shared destinations between multiple PPPs, it gets notified about all replies, not just those that happen to
+ * be picked up by the PPP that it is atteched to.
+ *
+ * @todo Use read/write lock in the onmessage, not for reading writing but to make use of a shared and exlcusive lock
+ * pair. Obtian read lock on all messages, before decrementing the message count. At the end of the on message
+ * method add a block that obtains the write lock for the very last message, releases any waiting producer. Means
+ * that the last message waits until all other messages have been handled before releasing producers but allows
+ * messages to be processed concurrently, unlike the current synchronized block.
+ *
+ * @todo Set the timeout to be per message correlation id. Restart it every time a message is received (with matching id).
+ * Means that timeout is measuring situations whether a particular ping stream has pasued for too long, rather than
+ * the time to send an entire block of messages. This will be better because the timeout won't need to be adjusted
+ * depending on the total number of messages being sent. Logic to be added to sendAndWait to recheck the timeout
+ * whenever its wait expires.
+ *
+ * @todo Need to multiply up the number of expected messages for pubsub tests as each can be received by many consumers?
*/
-public class PingPongProducer extends AbstractPingProducer implements Runnable, MessageListener, ExceptionListener
+public class PingPongProducer implements Runnable, MessageListener, ExceptionListener
{
private static final Logger _logger = Logger.getLogger(PingPongProducer.class);
- /**
- * Used to set up a default message size.
- */
- protected static final int DEFAULT_MESSAGE_SIZE = 0;
+ /** Holds the name of the property to get the test message size from. */
+ public static final String MESSAGE_SIZE_PROPNAME = "messagesize";
- /**
- * This is set and used when the test is for multiple-destinations
- */
- protected static final int DEFAULT_DESTINATION_COUNT = 0;
+ /** Holds the name of the property to get the ping queue name from. */
+ public static final String PING_QUEUE_NAME_PROPNAME = "destinationname";
- protected static final int DEFAULT_RATE = 0;
+ /** Holds the name of the property to get the test delivery mode from. */
+ public static final String PERSISTENT_MODE_PROPNAME = "persistent";
- /**
- * Used to define how long to wait between pings.
- */
- protected static final long SLEEP_TIME = 250;
+ /** Holds the name of the property to get the test transactional mode from. */
+ public static final String TRANSACTED_PROPNAME = "transacted";
- /**
- * Used to define how long to wait before assuming that a ping has timed out.
- */
- protected static final long TIMEOUT = 9000;
+ /** Holds the name of the property to get the test broker url from. */
+ public static final String BROKER_PROPNAME = "broker";
- /**
- * Holds the name of the destination to send pings on.
- */
- protected static final String PING_DESTINATION_NAME = "ping";
+ /** Holds the name of the property to get the test broker virtual path. */
+ public static final String VIRTUAL_PATH_PROPNAME = "virtualPath";
- /**
- * The batch size.
- */
- protected static final int DEFAULT_BATCH_SIZE = 100;
+ /** Holds the name of the property to get the message rate from. */
+ public static final String RATE_PROPNAME = "rate";
- protected static final int PREFETCH = 100;
- protected static final boolean NO_LOCAL = true;
- protected static final boolean EXCLUSIVE = false;
+ public static final String VERBOSE_OUTPUT_PROPNAME = "verbose";
- /**
- * The number of priming loops to run.
- */
- protected static final int PRIMING_LOOPS = 3;
+ /** Holds the true or false depending on wether it is P2P test or PubSub */
+ public static final String IS_PUBSUB_PROPNAME = "pubsub";
- /**
- * A source for providing sequential unique correlation ids.
- */
+ public static final String FAIL_AFTER_COMMIT_PROPNAME = "FailAfterCommit";
+
+ public static final String FAIL_BEFORE_COMMIT_PROPNAME = "FailBeforeCommit";
+
+ public static final String FAIL_AFTER_SEND_PROPNAME = "FailAfterSend";
+
+ public static final String FAIL_BEFORE_SEND_PROPNAME = "FailBeforeSend";
+
+ public static final String FAIL_ONCE_PROPNAME = "FailOnce";
+
+ public static final String USERNAME_PROPNAME = "username";
+
+ public static final String PASSWORD_PROPNAME = "password";
+
+ public static final String SELECTOR_PROPNAME = "selector";
+
+ public static final String PING_DESTINATION_COUNT_PROPNAME = "destinationscount";
+
+ /** Holds the name of the property to get the waiting timeout for response messages. */
+ public static final String TIMEOUT_PROPNAME = "timeout";
+
+ public static final String COMMIT_BATCH_SIZE_PROPNAME = "CommitBatchSize";
+
+ /** Used to set up a default message size. */
+ public static final int DEFAULT_MESSAGE_SIZE = 0;
+
+ /** Holds the name of the default destination to send pings on. */
+ public static final String DEFAULT_PING_DESTINATION_NAME = "ping";
+
+ /** Defines the default number of destinations to ping. */
+ public static final int DEFAULT_DESTINATION_COUNT = 1;
+
+ /** Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. */
+ public static final int DEFAULT_RATE = 0;
+
+ /** Defines the default wait between pings. */
+ public static final long DEFAULT_SLEEP_TIME = 250;
+
+ /** Default time to wait before assuming that a ping has timed out. */
+ public static final long DEFAULT_TIMEOUT = 9000;
+
+ /** Defines the default number of pings to send in each transaction when running transactionally. */
+ public static final int DEFAULT_TX_BATCH_SIZE = 100;
+
+ /** Defines the default prefetch size to use when consuming messages. */
+ public static final int DEFAULT_PREFETCH = 100;
+
+ /** Defines the default value of the no local flag to use when consuming messages. */
+ public static final boolean DEFAULT_NO_LOCAL = false;
+
+ /** Defines the default value of the exclusive flag to use when consuming messages. */
+ public static final boolean DEFAULT_EXCLUSIVE = false;
+
+ /** Holds the message delivery mode to use for the test. */
+ public static final boolean DEFAULT_PERSISTENT_MODE = false;
+
+ /** Holds the transactional mode to use for the test. */
+ public static final boolean DEFAULT_TRANSACTED = false;
+
+ /** Holds the default broker url for the test. */
+ public static final String DEFAULT_BROKER = "tcp://localhost:5672";
+
+ /** Holds the default virtual path for the test. */
+ public static final String DEFAULT_VIRTUAL_PATH = "test";
+
+ /** Holds the pub/sub mode default, true means ping a topic, false means ping a queue. */
+ public static final boolean DEFAULT_PUBSUB = false;
+
+ /** Holds the default broker log on username. */
+ public static final String DEFAULT_USERNAME = "guest";
+
+ /** Holds the default broker log on password. */
+ public static final String DEFAULT_PASSWORD = "guest";
+
+ /** Holds the default message selector. */
+ public static final String DEFAULT_SELECTOR = null;
+
+ /** Holds the default failover after commit test flag. */
+ public static final String DEFAULT_FAIL_AFTER_COMMIT = "false";
+
+ /** Holds the default failover before commit test flag. */
+ public static final String DEFAULT_FAIL_BEFORE_COMMIT = "false";
+
+ /** Holds the default failover after send test flag. */
+ public static final String DEFAULT_FAIL_AFTER_SEND = "false";
+
+ /** Holds the default failover before send test flag. */
+ public static final String DEFAULT_FAIL_BEFORE_SEND = "false";
+
+ /** Holds the default failover only once flag, true means only do one failover, false means failover on every commit cycle. */
+ public static final String DEFAULT_FAIL_ONCE = "true";
+
+ /** Holds the default verbose mode. */
+ public static final boolean DEFAULT_VERBOSE = false;
+
+ /** Holds the name of the property to store nanosecond timestamps in ping messages with. */
+ public static final String MESSAGE_TIMESTAMP_PROPNAME = "timestamp";
+
+ /** A source for providing sequential unique correlation ids. These will be unique within the same JVM. */
private static AtomicLong idGenerator = new AtomicLong(0L);
/**
- * Holds a map from message ids to latches on which threads wait for replies.
+ * Holds a map from message ids to latches on which threads wait for replies. This map is shared accross
+ * multiple ping producers on the same JVM.
*/
- private static Map<String, CountDownLatch> trafficLights = new HashMap<String, CountDownLatch>();
+ private static Map<String, CountDownLatch> trafficLights =
+ Collections.synchronizedMap(new HashMap<String, CountDownLatch>());
- /**
- * Destination where the responses messages will arrive
- */
- private Destination _replyDestination;
+ /** A convenient formatter to use when time stamping output. */
+ protected static final DateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS");
/**
- * Destination where the producer will be sending message to
+ * This id generator is used to generate ids to append to the queue name to ensure that queues can be unique when
+ * creating multiple ping producers in the same JVM.
*/
- private Destination _pingDestination;
+ protected static AtomicInteger _queueJVMSequenceID = new AtomicInteger();
- /**
- * Determines whether this producer sends persistent messages from the run method.
- */
+ /** Destination where the response messages will arrive. */
+ private Destination _replyDestination;
+
+ /** Determines whether this producer sends persistent messages. */
protected boolean _persistent;
- /**
- * Holds the message size to send, from the run method.
- */
+ /** Determines what size of messages this producer sends. */
protected int _messageSize;
- /**
- * Used to indicate that the ping loop should print out whenever it pings.
- */
+ /** Used to indicate that the ping loop should print out whenever it pings. */
protected boolean _verbose = false;
+ /** Holds the session on which ping replies are received. */
protected Session _consumerSession;
- /**
- * Used to restrict the sending rate to a specified limit.
- */
- private Throttle rateLimiter = null;
+ /** Used to restrict the sending rate to a specified limit. */
+ private Throttle _rateLimiter = null;
+
+ /** Holds a message listener that this message listener chains all its messages to. */
+ private ChainedMessageListener _chainedMessageListener = null;
+
+ /** Flag used to indicate if this is a point to point or pub/sub ping client. */
+ protected boolean _isPubSub = false;
/**
- * The throttler can only reliably restrict to a few hundred cycles per second, so a throttling batch size is used
- * to group sends together into batches large enough that the throttler runs slower than that.
+ * This id generator is used to generates ids that are only unique within this pinger. Creating multiple pingers
+ * on the same JVM using this id generator will allow them to ping on the same queues.
*/
- int _throttleBatchSize;
+ protected AtomicInteger _queueSharedId = new AtomicInteger();
- private MessageListener _messageListener = null;
+ /** Used to tell the ping loop when to terminate, it only runs while this is true. */
+ protected boolean _publish = true;
- private PingPongProducer(String brokerDetails, String username, String password, String virtualpath, boolean transacted,
- boolean persistent, int messageSize, boolean verbose, boolean afterCommit, boolean beforeCommit,
- boolean afterSend, boolean beforeSend, boolean failOnce, int batchSize, int rate)
- throws Exception
- {
- // Create a connection to the broker.
- InetAddress address = InetAddress.getLocalHost();
- String clientID = address.getHostName() + System.currentTimeMillis();
+ /** Holds the connection to the broker. */
+ private Connection _connection;
- setConnection(new AMQConnection(brokerDetails, username, password, clientID, virtualpath));
+ /** Holds the producer session, needed to create ping messages. */
+ private Session _producerSession;
- // Create transactional or non-transactional sessions, based on the command line arguments.
- setProducerSession((Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE));
- _consumerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE);
+ /** Holds the set of destiniations that this ping producer pings. */
+ protected List<Destination> _pingDestinations = new ArrayList<Destination>();
- _persistent = persistent;
- _messageSize = messageSize;
- _verbose = verbose;
+ /** Holds the message producer to send the pings through. */
+ protected MessageProducer _producer;
- // Set failover interrupts
- _failAfterCommit = afterCommit;
- _failBeforeCommit = beforeCommit;
- _failAfterSend = afterSend;
- _failBeforeSend = beforeSend;
- _failOnce = failOnce;
- _txBatchSize = batchSize;
-
- // Calculate a throttling batch size and rate such that the throttle runs slower than 100 cycles per second
- // and batched sends within each cycle multiply up to give the desired rate.
- //
- // total rate = throttle rate * batch size.
- // 1 < throttle rate < 100
- // 1 < total rate < 20000
- if (rate > DEFAULT_RATE)
- {
- // Log base 10 over 2 is used here to get a feel for what power of 100 the total rate is.
- // As the total rate goes up the powers of 100 the batch size goes up by powers of 100 to keep the
- // throttle rate back into the range 1 to 100.
- int x = (int) (Math.log10(rate) / 2);
- _throttleBatchSize = (int) Math.pow(100, x);
- int throttleRate = rate / _throttleBatchSize;
-
- _logger.debug("rate = " + rate);
- _logger.debug("x = " + x);
- _logger.debug("_throttleBatchSize = " + _throttleBatchSize);
- _logger.debug("throttleRate = " + throttleRate);
-
- rateLimiter = new Throttle();
- rateLimiter.setRate(throttleRate);
- }
- }
+ /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a commit. */
+ protected boolean _failBeforeCommit = false;
- /**
- * Creates a ping pong producer with the specified connection details and type.
- *
- * @param brokerDetails
- * @param username
- * @param password
- * @param virtualpath
- * @param transacted
- * @throws Exception All allowed to fall through. This is only test code...
- */
- public PingPongProducer(String brokerDetails, String username, String password, String virtualpath,
- String destinationName, String selector, boolean transacted, boolean persistent,
- int messageSize, boolean verbose, boolean afterCommit, boolean beforeCommit,
- boolean afterSend, boolean beforeSend, boolean failOnce, int batchSize,
- int noOfDestinations, int rate, boolean pubsub) throws Exception
- {
- this(brokerDetails, username, password, virtualpath, transacted, persistent, messageSize, verbose, afterCommit,
- beforeCommit, afterSend, beforeSend, failOnce, batchSize, rate);
+ /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a commit. */
+ protected boolean _failAfterCommit = false;
- _destinationCount = noOfDestinations;
- setPubSub(pubsub);
+ /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a send. */
+ protected boolean _failBeforeSend = false;
- if (noOfDestinations == DEFAULT_DESTINATION_COUNT)
- {
- if (destinationName != null)
- {
- createPingDestination(destinationName);
- // Create producer and the consumer
- createProducer();
- createConsumer(selector);
- }
- else
- {
- _logger.error("Destination is not specified");
- throw new IllegalArgumentException("Destination is not specified");
- }
- }
- }
+ /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a send. */
+ protected boolean _failAfterSend = false;
- private void createPingDestination(String name)
- {
- if (isPubSub())
- {
- _pingDestination = new AMQTopic(name);
- }
- else
- {
- _pingDestination = new AMQQueue(name);
- }
- }
+ /** Flag used to indicate that failover prompting should only be done on the first commit, not on every commit. */
+ protected boolean _failOnce = true;
+
+ /** Holds the number of sends that should be performed in every transaction when using transactions. */
+ protected int _txBatchSize = 1;
/**
- * Creates the producer to send the pings on. If the tests are with nultiple-destinations, then producer
- * is created with null destination, so that any destination can be specified while sending
+ * Creates a ping producer with the specified parameters, of which there are many. See their individual comments
+ * for details. This constructor creates a connection to the broker and creates producer and consumer sessions on it,
+ * to send and recieve its pings and replies on. The other options are kept, and control how this pinger behaves.
+ *
+ * @param brokerDetails The URL of the broker to send pings to.
+ * @param username The username to log onto the broker with.
+ * @param password The password to log onto the broker with.
+ * @param virtualpath The virtual host name to use on the broker.
+ * @param destinationName The name (or root where multiple destinations are used) of the desitination to send
+ * pings to.
+ * @param selector The selector to filter replies with.
+ * @param transacted Indicates whether or not pings are sent and received in transactions.
+ * @param persistent Indicates whether pings are sent using peristent delivery.
+ * @param messageSize Specifies the size of ping messages to send.
+ * @param verbose Indicates that information should be printed to the console on every ping.
+ * @param afterCommit Indicates that the user should be promted to terminate a broker after commits to test failover.
+ * @param beforeCommit Indicates that the user should be promted to terminate a broker before commits to test failover.
+ * @param afterSend Indicates that the user should be promted to terminate a broker after sends to test failover.
+ * @param beforeSend Indicates that the user should be promted to terminate a broker before sends to test failover.
+ * @param failOnce Indicates that the failover testing behaviour should only happen on the first commit, not all.
+ * @param txBatchSize Specifies the number of pings to send in each transaction.
+ * @param noOfDestinations The number of destinations to ping. Must be 1 or more.
+ * @param rate Specified the number of pings per second to send. Setting this to 0 means send as fast as
+ * possible, with no rate restriction.
+ * @param pubsub
*
- * @throws JMSException
+ * @throws Exception Any exceptions are allowed to fall through.
*/
- public void createProducer() throws JMSException
+ public PingPongProducer(String brokerDetails, String username, String password, String virtualpath,
+ String destinationName, String selector, boolean transacted, boolean persistent, int messageSize,
+ boolean verbose, boolean afterCommit, boolean beforeCommit, boolean afterSend,
+ boolean beforeSend, boolean failOnce, int txBatchSize, int noOfDestinations, int rate,
+ boolean pubsub) throws Exception
{
- if (getDestinationsCount() > DEFAULT_DESTINATION_COUNT)
+ // Check that one or more destinations were specified.
+ if (noOfDestinations < 1)
{
- // create producer with initial destination as null for test with multiple-destinations
- // In this case, a different destination will be used while sending the message
- _producer = (MessageProducer) getProducerSession().createProducer(null);
+ throw new IllegalArgumentException("There must be at least one destination.");
}
- else
- {
- // Create a producer with known destination to send the pings on.
- _producer = (MessageProducer) getProducerSession().createProducer(_pingDestination);
- }
-
- _producer.setDisableMessageTimestamp(true);
- _producer.setDeliveryMode(_persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
- }
+ // Create a connection to the broker.
+ InetAddress address = InetAddress.getLocalHost();
+ String clientID = address.getHostName() + System.currentTimeMillis();
- /**
- * Creates the temporary destination to listen to the responses
- *
- * @param selector
- * @throws JMSException
- */
- public void createConsumer(String selector) throws JMSException
- {
- // Create a temporary destination to get the pongs on.
- if (isPubSub())
- {
- _replyDestination = _consumerSession.createTemporaryTopic();
- }
- else
- {
- _replyDestination = _consumerSession.createTemporaryQueue();
- }
+ _connection = new AMQConnection(brokerDetails, username, password, clientID, virtualpath);
- // Create a message consumer to get the replies with and register this to be called back by it.
- MessageConsumer consumer = _consumerSession.createConsumer(_replyDestination, PREFETCH, NO_LOCAL, EXCLUSIVE, selector);
- consumer.setMessageListener(this);
- }
+ // Create transactional or non-transactional sessions, based on the command line arguments.
+ _producerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE);
+ _consumerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE);
- /**
- * Creates consumer instances for each destination. This is used when test is being done with multiple destinations.
- *
- * @param selector
- * @throws JMSException
- */
- public void createConsumers(String selector) throws JMSException
- {
- for (int i = 0; i < getDestinationsCount(); i++)
+ // Set up a throttle to control the send rate, if a rate > 0 is specified.
+ if (rate > 0)
{
- MessageConsumer consumer =
- getConsumerSession().createConsumer(getDestination(i), PREFETCH, false, EXCLUSIVE, selector);
- consumer.setMessageListener(this);
+ _rateLimiter = new BatchedThrottle();
+ _rateLimiter.setRate(rate);
}
- }
+ // Create the temporary queue for replies.
+ _replyDestination = _consumerSession.createTemporaryQueue();
- public Session getConsumerSession()
- {
- return _consumerSession;
- }
-
- public Destination getPingDestination()
- {
- return _pingDestination;
- }
+ // Create the producer and the consumers for all reply destinations.
+ createProducer();
+ createPingDestinations(noOfDestinations, selector, destinationName, true);
+ createReplyConsumers(getReplyDestinations(), selector);
- protected void setPingDestination(Destination destination)
- {
- _pingDestination = destination;
+ // Keep all the remaining options.
+ _persistent = persistent;
+ _messageSize = messageSize;
+ _verbose = verbose;
+ _failAfterCommit = afterCommit;
+ _failBeforeCommit = beforeCommit;
+ _failAfterSend = afterSend;
+ _failBeforeSend = beforeSend;
+ _failOnce = failOnce;
+ _txBatchSize = txBatchSize;
+ _isPubSub = pubsub;
}
/**
- * Starts a ping-pong loop running from the command line. The bounce back client {@link org.apache.qpid.requestreply.PingPongBouncer} also needs
+ * Starts a ping-pong loop running from the command line. The bounce back client {@link PingPongBouncer} also needs
* to be started to bounce the pings back again.
- * <p/>
- * <p/>The command line takes from 2 to 4 arguments:
- * <p/><table>
- * <tr><td>brokerDetails <td> The broker connection string.
- * <tr><td>virtualPath <td> The virtual path.
- * <tr><td>transacted <td> A boolean flag, telling this client whether or not to use transactions.
- * <tr><td>size <td> The size of ping messages to use, in bytes.
- * </table>
- *
- * @param args The command line arguments as defined above.
+ *
+ * @param args The command line arguments.
*/
public static void main(String[] args) throws Exception
{
@@ -372,22 +410,22 @@ public class PingPongProducer extends AbstractPingProducer implements Runnable,
}
String brokerDetails = config.getHost() + ":" + config.getPort();
- String virtualpath = "/test";
- String selector = config.getSelector();
+ String virtualpath = "test";
+ String selector = (config.getSelector() == null) ? DEFAULT_SELECTOR : config.getSelector();
boolean verbose = true;
boolean transacted = config.isTransacted();
boolean persistent = config.usePersistentMessages();
int messageSize = (config.getPayload() != 0) ? config.getPayload() : DEFAULT_MESSAGE_SIZE;
//int messageCount = config.getMessages();
int destCount = (config.getDestinationsCount() != 0) ? config.getDestinationsCount() : DEFAULT_DESTINATION_COUNT;
- int batchSize = (config.getBatchSize() != 0) ? config.getBatchSize() : DEFAULT_BATCH_SIZE;
+ int batchSize = (config.getBatchSize() != 0) ? config.getBatchSize() : DEFAULT_TX_BATCH_SIZE;
int rate = (config.getRate() != 0) ? config.getRate() : DEFAULT_RATE;
boolean pubsub = config.isPubSub();
String destName = config.getDestination();
if (destName == null)
{
- destName = PING_DESTINATION_NAME;
+ destName = DEFAULT_PING_DESTINATION_NAME;
}
boolean afterCommit = false;
@@ -429,15 +467,13 @@ public class PingPongProducer extends AbstractPingProducer implements Runnable,
}
// Create a ping producer to handle the request/wait/reply cycle.
- PingPongProducer pingProducer = new PingPongProducer(brokerDetails, "guest", "guest", virtualpath,
- destName, selector, transacted, persistent, messageSize, verbose,
- afterCommit, beforeCommit, afterSend, beforeSend, failOnce, batchSize,
- destCount, rate, pubsub);
+ PingPongProducer pingProducer =
+ new PingPongProducer(brokerDetails, DEFAULT_USERNAME, DEFAULT_PASSWORD, virtualpath, destName, selector,
+ transacted, persistent, messageSize, verbose, afterCommit, beforeCommit, afterSend,
+ beforeSend, failOnce, batchSize, destCount, rate, pubsub);
pingProducer.getConnection().start();
- // Run a few priming pings to remove warm up time from test results.
- //pingProducer.prime(PRIMING_LOOPS);
// Create a shutdown hook to terminate the ping-pong producer.
Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook());
@@ -450,50 +486,105 @@ public class PingPongProducer extends AbstractPingProducer implements Runnable,
pingThread.join();
}
- private static void usage()
+ /**
+ * Convenience method for a short pause.
+ *
+ * @param sleepTime The time in milliseconds to pause for.
+ */
+ public static void pause(long sleepTime)
{
- System.err.println("Usage: TestPingPublisher \n" + "-host : broker host" + "-port : broker port" +
- "-destinationname : queue/topic name\n" +
- "-transacted : (true/false). Default is false\n" +
- "-persistent : (true/false). Default is false\n" +
- "-pubsub : (true/false). Default is false\n" +
- "-selector : selector string\n" +
- "-payload : paylaod size. Default is 0\n" +
- //"-messages : no of messages to be sent (if 0, the ping loop will run indefinitely)\n" +
- "-destinationscount : no of destinations for multi-destinations test\n" +
- "-batchsize : batch size\n" +
- "-rate : thruput rate\n");
+ if (sleepTime > 0)
+ {
+ try
+ {
+ Thread.sleep(sleepTime);
+ }
+ catch (InterruptedException ie)
+ { }
+ }
}
/**
- * Primes the test loop by sending a few messages, then introduces a short wait. This allows the bounce back client
- * on the other end a chance to configure its reply producer on the reply to destination. It is also worth calling
- * this a few times, in order to prime the JVMs JIT compilation.
+ * Gets all the reply destinations (to listen for replies on). In this case this will just be the single reply
+ * to destination of this pinger.
*
- * @param x The number of priming loops to run.
- * @throws JMSException All underlying exceptions are allowed to fall through.
+ * @return The single reply to destination of this pinger, wrapped in a list.
*/
- public void prime(int x) throws JMSException
+ public List<Destination> getReplyDestinations()
{
- for (int i = 0; i < x; i++)
+ _logger.debug("public List<Destination> getReplyDestinations(): called");
+
+ List<Destination> replyDestinations = new ArrayList<Destination>();
+ replyDestinations.add(_replyDestination);
+
+ return replyDestinations;
+ }
+
+ /**
+ * Creates the producer to send the pings on. This is created without a default destination. Its persistent delivery
+ * flag is set accoring the ping producer creation options.
+ *
+ * @throws JMSException Any JMSExceptions are allowed to fall through.
+ */
+ public void createProducer() throws JMSException
+ {
+ _logger.debug("public void createProducer(): called");
+
+ _producer = (MessageProducer) _producerSession.createProducer(null);
+ //_producer.setDisableMessageTimestamp(true);
+ _producer.setDeliveryMode(_persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+ }
+
+ /**
+ * Creates consumers for the specified number of destinations. The destinations themselves are also created by
+ * this method.
+ *
+ * @param noOfDestinations The number of destinations to create consumers for.
+ * @param selector The message selector to filter the consumers with.
+ * @param rootName The root of the name, or actual name if only one is being created.
+ * @param unique <tt>true</tt> to make the destinations unique to this pinger, <tt>false</tt> to share
+ * the numbering with all pingers on the same JVM.
+ *
+ * @throws JMSException Any JMSExceptions are allowed to fall through.
+ */
+ public void createPingDestinations(int noOfDestinations, String selector, String rootName, boolean unique)
+ throws JMSException
+ {
+ _logger.debug("public void createPingDestinations(int noOfDestinations = " + noOfDestinations
+ + ", String selector = " + selector + ", String rootName = " + rootName + ", boolean unique = "
+ + unique + "): called");
+
+ // Create the desired number of ping destinations and consumers for them.
+ for (int i = 0; i < noOfDestinations; i++)
{
- // Create and send a small message.
- Message first = getTestMessage(_replyDestination, 0, false);
- sendMessage(first);
+ AMQDestination destination = null;
- commitTx();
+ int id;
- try
+ // Generate an id, unique within this pinger or to the whole JVM depending on the unique flag.
+ if (unique)
{
- Thread.sleep(100);
+ id = _queueJVMSequenceID.incrementAndGet();
}
- catch (InterruptedException ignore)
+ else
{
-
+ id = _queueSharedId.incrementAndGet();
}
- }
+ // Check if this is a pub/sub pinger, in which case create topics.
+ if (_isPubSub)
+ {
+ destination = new AMQTopic(rootName + id);
+ }
+ // Otherwise this is a p2p pinger, in which case create queues.
+ else
+ {
+ destination = new AMQQueue(rootName + id);
+ }
+ // Keep the destination.
+ _pingDestinations.add(destination);
+ }
}
/**
@@ -505,60 +596,72 @@ public class PingPongProducer extends AbstractPingProducer implements Runnable,
*/
public void onMessage(Message message)
{
+ _logger.debug("public void onMessage(Message message): called");
try
{
-
- // Store the reply, if it has a correlation id that is expected.
+ // Extract the messages correlation id.
String correlationID = message.getJMSCorrelationID();
+ _logger.debug("correlationID = " + correlationID);
- if (_verbose)
- {
- _logger.info(timestampFormatter.format(new Date()) + ": Got reply with correlation id, " + correlationID);
- //_logger.debug("Received from : " + message.getJMSDestination());
- }
-
- // Turn the traffic light to green.
+ // Countdown on the traffic light if there is one for the matching correlation id.
CountDownLatch trafficLight = trafficLights.get(correlationID);
if (trafficLight != null)
{
- if (_messageListener != null)
- {
- synchronized (trafficLight)
- {
- _messageListener.onMessage(message);
- trafficLight.countDown();
- }
- }
- else
+ _logger.debug("Reply was expected, decrementing the latch for the id, " + correlationID);
+
+ // Decrement the countdown latch. Before this point, it is possible that two threads might enter this
+ // method simultanesouly with the same correlation id. Decrementing the latch in a synchronized block
+ // ensures that each thread will get a unique value for the remaining messages.
+ long trueCount = -1;
+ long remainingCount = -1;
+
+ synchronized (trafficLight)
{
trafficLight.countDown();
- }
- _logger.trace("Reply was expected, decrementing the latch for the id.");
+ trueCount = trafficLight.getCount();
+ remainingCount = trueCount - 1;
- long remainingCount = trafficLight.getCount();
+ _logger.debug("remainingCount = " + remainingCount);
+ _logger.debug("trueCount = " + trueCount);
- if ((remainingCount % _txBatchSize) == 0)
- {
- commitTx(getConsumerSession());
- }
+ // Commit on transaction batch size boundaries. At this point in time the waiting producer remains
+ // blocked, even on the last message.
+ if ((remainingCount % _txBatchSize) == 0)
+ {
+ commitTx(_consumerSession);
+ }
+ // Forward the message and remaining count to any interested chained message listener.
+ if (_chainedMessageListener != null)
+ {
+ _chainedMessageListener.onMessage(message, (int) remainingCount);
+ }
+
+ // Check if this is the last message, in which case release any waiting producers. This is done
+ // after the transaction has been committed and any listeners notified.
+ if (trueCount == 1)
+ {
+ trafficLight.countDown();
+ }
+ }
}
else
{
- _logger.trace("There was no thread waiting for reply: " + correlationID);
+ _logger.debug("There was no thread waiting for reply: " + correlationID);
}
+ // Print out ping times for every message in verbose mode only.
if (_verbose)
{
- Long timestamp = message.getLongProperty("timestamp");
+ Long timestamp = message.getLongProperty(MESSAGE_TIMESTAMP_PROPNAME);
if (timestamp != null)
{
- long diff = System.currentTimeMillis() - timestamp;
- _logger.trace("Time for round trip: " + diff);
+ long diff = System.nanoTime() - timestamp;
+ _logger.trace("Time for round trip (nanos): " + diff);
}
}
}
@@ -566,32 +669,70 @@ public class PingPongProducer extends AbstractPingProducer implements Runnable,
{
_logger.warn("There was a JMSException: " + e.getMessage(), e);
}
+
+ _logger.debug("public void onMessage(Message message): ending");
}
/**
* Sends the specified number of ping message and then waits for all correlating replies. If the wait times out
- * before a reply arrives, then a null reply is returned from this method.
+ * before a reply arrives, then a null reply is returned from this method. This method generates a new unqiue
+ * correlation id for the messages.
*
* @param message The message to send.
* @param numPings The number of ping messages to send.
* @param timeout The timeout in milliseconds.
+ *
* @return The number of replies received. This may be less than the number sent if the timeout terminated the
* wait for all prematurely.
+ *
* @throws JMSException All underlying JMSExceptions are allowed to fall through.
*/
public int pingAndWaitForReply(Message message, int numPings, long timeout) throws JMSException, InterruptedException
{
- String messageCorrelationId = null;
+ _logger.debug("public int pingAndWaitForReply(Message message, int numPings = " + numPings + ", long timeout = "
+ + timeout + "): called");
+
+ // Create a unique correlation id to put on the messages before sending them.
+ String messageCorrelationId = Long.toString(idGenerator.incrementAndGet());
+
+ return pingAndWaitForReply(message, numPings, timeout, messageCorrelationId);
+ }
+
+ /**
+ * Sends the specified number of ping message and then waits for all correlating replies. If the wait times out
+ * before a reply arrives, then a null reply is returned from this method. This method allows the caller to specify
+ * the correlation id.
+ *
+ * @param message The message to send.
+ * @param numPings The number of ping messages to send.
+ * @param timeout The timeout in milliseconds.
+ * @param messageCorrelationId The message correlation id.
+ *
+ * @return The number of replies received. This may be less than the number sent if the timeout terminated the
+ * wait for all prematurely.
+ *
+ * @throws JMSException All underlying JMSExceptions are allowed to fall through.
+ */
+ public int pingAndWaitForReply(Message message, int numPings, long timeout, String messageCorrelationId)
+ throws JMSException, InterruptedException
+ {
+ _logger.debug("public int pingAndWaitForReply(Message message, int numPings = " + numPings + ", long timeout = "
+ + timeout + ", String messageCorrelationId = " + messageCorrelationId + "): called");
try
{
- // Put a unique correlation id on the message before sending it.
- messageCorrelationId = Long.toString(getNewID());
-
+ // Create a count down latch to count the number of replies with. This is created before the messages are
+ // sent so that the replies cannot be received before the count down is created.
+ // One is added to this, so that the last reply becomes a special case. The special case is that the
+ // chained message listener must be called before this sender can be unblocked, but that decrementing the
+ // countdown needs to be done before the chained listener can be called.
+ CountDownLatch trafficLight = new CountDownLatch(numPings + 1);
+ trafficLights.put(messageCorrelationId, trafficLight);
+
+ // Send the specifed number of messages.
pingNoWaitForReply(message, numPings, messageCorrelationId);
- CountDownLatch trafficLight = trafficLights.get(messageCorrelationId);
- // Block the current thread until a reply to the message is received, or it times out.
+ // Block the current thread until replies to all the message are received, or it times out.
trafficLight.await(timeout, TimeUnit.MILLISECONDS);
// Work out how many replies were receieved.
@@ -606,45 +747,37 @@ public class PingPongProducer extends AbstractPingProducer implements Runnable,
_logger.info("Got all replies on id, " + messageCorrelationId);
}
- commitTx(getConsumerSession());
+ commitTx(_consumerSession);
+
+ _logger.debug("public int pingAndWaitForReply(Message message, int numPings, long timeout): ending");
return numReplies;
}
+ // Ensure that the message countdown latch is always removed from the reply map. The reply map is long lived,
+ // so will be a memory leak if this is not done.
finally
{
- removeLock(messageCorrelationId);
+ trafficLights.remove(messageCorrelationId);
}
}
- public long getNewID()
- {
- return idGenerator.incrementAndGet();
- }
-
- public CountDownLatch removeLock(String correlationID)
- {
- return trafficLights.remove(correlationID);
- }
-
-
- /*
- * Sends the specified ping message but does not wait for a correlating reply.
- *
- * @param message The message to send.
- * @param numPings The number of pings to send.
- * @return The reply, or null if no reply arrives before the timeout.
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- */
- public void pingNoWaitForReply(Message message, int numPings, String messageCorrelationId) throws JMSException, InterruptedException
+ /**
+ * Sends the specified number of ping messages and does not wait for correlating replies.
+ *
+ * @param message The message to send.
+ * @param numPings The number of pings to send.
+ * @param messageCorrelationId A correlation id to place on all messages sent.
+ *
+ * @throws JMSException All underlying JMSExceptions are allowed to fall through.
+ */
+ public void pingNoWaitForReply(Message message, int numPings, String messageCorrelationId) throws JMSException
{
- // Create a count down latch to count the number of replies with. This is created before the message is sent
- // so that the message is not received before the count down is created.
- CountDownLatch trafficLight = new CountDownLatch(numPings);
- trafficLights.put(messageCorrelationId, trafficLight);
+ _logger.debug("public void pingNoWaitForReply(Message message, int numPings = " + numPings
+ + ", String messageCorrelationId = " + messageCorrelationId + "): called");
message.setJMSCorrelationID(messageCorrelationId);
- // Set up a committed flag to detect uncommitted message at the end of the send loop. This may occurr if the
+ // Set up a committed flag to detect uncommitted messages at the end of the send loop. This may occurr if the
// transaction batch size is not a factor of the number of pings. In which case an extra commit at the end is
// needed.
boolean committed = false;
@@ -652,55 +785,46 @@ public class PingPongProducer extends AbstractPingProducer implements Runnable,
// Send all of the ping messages.
for (int i = 0; i < numPings; i++)
{
- // Reset the committed flag to indicate that there are uncommitted message.
+ // Reset the committed flag to indicate that there are uncommitted messages.
committed = false;
// Re-timestamp the message.
- message.setLongProperty("timestamp", System.currentTimeMillis());
+ message.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
- // Check if the test is with multiple-destinations, in which case round robin the destinations
- // as the messages are sent.
- if (getDestinationsCount() > DEFAULT_DESTINATION_COUNT)
- {
- sendMessage(getDestination(i % getDestinationsCount()), message);
- }
- else
- {
- sendMessage(message);
- }
+ // Round robin the destinations as the messages are sent.
+ //return _destinationCount;
+ sendMessage(_pingDestinations.get(i % _pingDestinations.size()), message);
- // Apply message rate throttling if a rate limit has been set up and the throttling batch limit has been
- // reached. See the comment on the throttle batch size for information about the use of batches here.
- if ((rateLimiter != null) && ((i % _throttleBatchSize) == 0))
+ // Apply message rate throttling if a rate limit has been set up.
+ if (_rateLimiter != null)
{
- rateLimiter.throttle();
+ _rateLimiter.throttle();
}
// Call commit every time the commit batch size is reached.
if ((i % _txBatchSize) == 0)
{
- commitTx();
+ commitTx(_producerSession);
committed = true;
}
+
+ // Spew out per message timings on every message sonly in verbose mode.
+ if (_verbose)
+ {
+ _logger.info(timestampFormatter.format(new Date()) + ": Pinged at with correlation id, "
+ + messageCorrelationId);
+ }
}
// Call commit if the send loop finished before reaching a batch size boundary so there may still be uncommitted messages.
if (!committed)
{
- commitTx();
- }
-
- // Spew out per message timings only in verbose mode.
- if (_verbose)
- {
- _logger.info(timestampFormatter.format(new Date()) + ": Pinged at with correlation id, " + messageCorrelationId);
+ commitTx(_producerSession);
}
-
}
/**
- * The ping loop implementation. This send out pings of the configured size, persistence and transactionality, and
- * waits for replies and inserts short pauses in between each.
+ * The ping loop implementation. This sends out pings waits for replies and inserts short pauses in between each.
*/
public void pingLoop()
{
@@ -708,13 +832,13 @@ public class PingPongProducer extends AbstractPingProducer implements Runnable,
{
// Generate a sample message and time stamp it.
ObjectMessage msg = getTestMessage(_replyDestination, _messageSize, _persistent);
- msg.setLongProperty("timestamp", System.currentTimeMillis());
+ msg.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
// Send the message and wait for a reply.
- pingAndWaitForReply(msg, DEFAULT_BATCH_SIZE, TIMEOUT);
+ pingAndWaitForReply(msg, DEFAULT_TX_BATCH_SIZE, DEFAULT_TIMEOUT);
// Introduce a short pause if desired.
- pause(SLEEP_TIME);
+ pause(DEFAULT_SLEEP_TIME);
}
catch (JMSException e)
{
@@ -728,79 +852,300 @@ public class PingPongProducer extends AbstractPingProducer implements Runnable,
}
}
- public Destination getReplyDestination()
+ /*public Destination getReplyDestination()
{
return _replyDestination;
+ }*/
+
+ /**
+ * Sets a chained message listener. The message listener on this pinger, chains all its messages to the one set
+ * here.
+ *
+ * @param messageListener The chained message listener.
+ */
+ public void setChainedMessageListener(ChainedMessageListener messageListener)
+ {
+ _chainedMessageListener = messageListener;
}
- protected void setReplyDestination(Destination destination)
+ /**
+ * Removes any chained message listeners from this pinger.
+ */
+ public void removeChainedMessageListener()
{
- _replyDestination = destination;
+ _chainedMessageListener = null;
}
- public void setMessageListener(MessageListener messageListener)
+ /**
+ * Generates a test message of the specified size, with the specified reply-to destination and persistence flag.
+ *
+ * @param replyQueue The reply-to destination for the message.
+ * @param messageSize The desired size of the message in bytes.
+ * @param persistent <tt>true</tt> if the message should use persistent delivery, <tt>false</tt> otherwise.
+ *
+ * @return A freshly generated test message.
+ *
+ * @throws javax.jms.JMSException All underlying JMSException are allowed to fall through.
+ */
+ public ObjectMessage getTestMessage(Destination replyQueue, int messageSize, boolean persistent) throws JMSException
{
- _messageListener = messageListener;
+ ObjectMessage msg = TestMessageFactory.newObjectMessage(_producerSession, replyQueue, messageSize, persistent);
+
+ // Timestamp the message in nanoseconds.
+ msg.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
+
+ return msg;
}
- public CountDownLatch getEndLock(String correlationID)
+ /**
+ * Stops the ping loop by clearing the publish flag. The current loop will complete before it notices that this
+ * flag has been cleared.
+ */
+ public void stop()
{
- return trafficLights.get(correlationID);
+ _publish = false;
}
- /*
- * When the test is being performed with multiple queues, then this method will be used, which has a loop to
- * pick up the next queue from the queues list and sends message to it.
- *
- * @param message
- * @param numPings
- * @throws JMSException
- */
- /*private void pingMultipleQueues(Message message, int numPings) throws JMSException
+ /**
+ * Implements a ping loop that repeatedly pings until the publish flag becomes false.
+ */
+ public void run()
{
- int queueIndex = 0;
- for (int i = 0; i < numPings; i++)
+ // Keep running until the publish flag is cleared.
+ while (_publish)
{
- // Re-timestamp the message.
- message.setLongProperty("timestamp", System.currentTimeMillis());
+ pingLoop();
+ }
+ }
- sendMessage(getDestination(queueIndex++), message);
+ /**
+ * Callback method, implementing ExceptionListener. This should be registered to listen for exceptions on the
+ * connection, this clears the publish flag which in turn will halt the ping loop.
+ *
+ * @param e The exception that triggered this callback method.
+ */
+ public void onException(JMSException e)
+ {
+ _publish = false;
+ _logger.debug("There was a JMSException: " + e.getMessage(), e);
+ }
- // reset the counter to get the first queue
- if (queueIndex == (getDestinationsCount() - 1))
+ /**
+ * Gets a shutdown hook that will cleanly shut this down when it is running the ping loop. This can be registered
+ * with the runtime system as a shutdown hook.
+ *
+ * @return A shutdown hook for the ping loop.
+ */
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
{
- queueIndex = 0;
- }
+ public void run()
+ {
+ stop();
+ }
+ });
+ }
+
+ /**
+ * Gets the underlying connection that this ping client is running on.
+ *
+ * @return The underlying connection that this ping client is running on.
+ */
+ public Connection getConnection()
+ {
+ return _connection;
+ }
+
+ /**
+ * Creates consumers for the specified destinations and registers this pinger to listen to their messages.
+ *
+ * @param destinations The destinations to listen to.
+ * @param selector A selector to filter the messages with.
+ *
+ * @throws javax.jms.JMSException Any JMSExceptions are allowed to fall through.
+ */
+ public void createReplyConsumers(Collection<Destination> destinations, String selector) throws JMSException
+ {
+ _logger.debug("public void createReplyConsumers(Collection<Destination> destinations = " + destinations
+ + ", String selector = " + selector + "): called");
+
+ for (Destination destination : destinations)
+ {
+ // Create a consumer for the destination and set this pinger to listen to its messages.
+ MessageConsumer consumer =
+ _consumerSession.createConsumer(destination, DEFAULT_PREFETCH, DEFAULT_NO_LOCAL, DEFAULT_EXCLUSIVE,
+ selector);
+ consumer.setMessageListener(this);
}
- }*/
+ }
+
+ /**
+ * Closes the pingers connection.
+ *
+ * @throws JMSException All JMSException are allowed to fall through.
+ */
+ public void close() throws JMSException
+ {
+ _logger.debug("public void close(): called");
+
+ if (_connection != null)
+ {
+ _connection.close();
+ }
+ }
/**
- * A connection listener that logs out any failover complete events. Could do more interesting things with this
- * at some point...
+ * Convenience method to commit the transaction on the specified session. If the session to commit on is not
+ * a transactional session, this method does nothing (unless the failover after send flag is set).
+ *
+ * <p/>If the {@link #_failAfterSend} flag is set, this will prompt the user to kill the broker before the commit
+ * is applied. This flag applies whether the pinger is transactional or not.
+ *
+ * <p/>If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the
+ * commit is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker
+ * after the commit is applied. These flags will only apply if using a transactional pinger.
+ *
+ * @throws javax.jms.JMSException If the commit fails and then the rollback fails.
+ *
+ * @todo Consider moving the fail after send logic into the send method. It is confusing to have it in this commit
+ * method, because commits only apply to transactional pingers, but fail after send applied to transactional
+ * and non-transactional alike.
*/
- public static class FailoverNotifier implements ConnectionListener
+ protected void commitTx(Session session) throws JMSException
{
- public void bytesSent(long count)
+ _logger.debug("protected void commitTx(Session session): called");
+
+ _logger.trace("Batch time reached");
+ if (_failAfterSend)
{
+ _logger.trace("Batch size reached");
+ if (_failOnce)
+ {
+ _failAfterSend = false;
+ }
+
+ _logger.trace("Failing After Send");
+ doFailover();
}
- public void bytesReceived(long count)
+ if (session.getTransacted())
{
+ try
+ {
+ if (_failBeforeCommit)
+ {
+ if (_failOnce)
+ {
+ _failBeforeCommit = false;
+ }
+
+ _logger.trace("Failing Before Commit");
+ doFailover();
+ }
+
+ session.commit();
+
+ if (_failAfterCommit)
+ {
+ if (_failOnce)
+ {
+ _failAfterCommit = false;
+ }
+
+ _logger.trace("Failing After Commit");
+ doFailover();
+ }
+
+ _logger.trace("Session Commited.");
+ }
+ catch (JMSException e)
+ {
+ _logger.trace("JMSException on commit:" + e.getMessage(), e);
+
+ // Warn that the bounce back client is not available.
+ if (e.getLinkedException() instanceof AMQNoConsumersException)
+ {
+ _logger.debug("No consumers on queue.");
+ }
+
+ try
+ {
+ session.rollback();
+ _logger.trace("Message rolled back.");
+ }
+ catch (JMSException jmse)
+ {
+ _logger.trace("JMSE on rollback:" + jmse.getMessage(), jmse);
+
+ // Both commit and rollback failed. Throw the rollback exception.
+ throw jmse;
+ }
+ }
}
+ }
- public boolean preFailover(boolean redirect)
+ /**
+ * Sends the message to the specified destination. If the destination is null, it gets sent to the default destination
+ * of the ping producer. If an explicit destination is set, this overrides the default.
+ *
+ * @param destination The destination to send to.
+ * @param message The message to send.
+ *
+ * @throws javax.jms.JMSException All underlying JMSExceptions are allowed to fall through.
+ */
+ protected void sendMessage(Destination destination, Message message) throws JMSException
+ {
+ if (_failBeforeSend)
{
- return true; //Allow failover
+ if (_failOnce)
+ {
+ _failBeforeSend = false;
+ }
+
+ _logger.trace("Failing Before Send");
+ doFailover();
}
- public boolean preResubscribe()
+ if (destination == null)
+ {
+ _producer.send(message);
+ }
+ else
{
- return true; // Allow resubscription
+ _producer.send(destination, message);
}
+ }
- public void failoverComplete()
+ /**
+ * Prompts the user to terminate the broker, in order to test failover functionality. This method will block
+ * until the user supplied some input on the terminal.
+ */
+ protected void doFailover()
+ {
+ System.out.println("Kill Broker now then press return");
+ try
{
- _logger.info("App got failover complete callback.");
+ System.in.read();
}
+ catch (IOException e)
+ { }
+
+ System.out.println("Continuing.");
+ }
+
+ /**
+ * Defines a chained message listener interface that can be attached to this pinger. Whenever this pinger's
+ * {@link PingPongProducer#onMessage} method is called, the chained listener set through the
+ * {@link PingPongProducer#setChainedMessageListener} method is passed the message, and the remaining expected
+ * count of messages with that correlation id.
+ *
+ * Provided only one pinger is producing messages with that correlation id, the chained listener will always be
+ * given unique message counts. It will always be called while the producer waiting for all messages to arrive is
+ * still blocked.
+ */
+ public static interface ChainedMessageListener
+ {
+ public void onMessage(Message message, int remainingCount) throws JMSException;
}
}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceProvidingClient.java b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceProvidingClient.java
deleted file mode 100644
index bab732e2a6..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceProvidingClient.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *
- * 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.qpid.requestreply;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.jms.ConnectionListener;
-import org.apache.qpid.jms.Session;
-import org.apache.qpid.url.URLSyntaxException;
-
-import javax.jms.*;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-public class ServiceProvidingClient
-{
- private static final Logger _logger = Logger.getLogger(ServiceProvidingClient.class);
-
- private MessageProducer _destinationProducer;
-
- private Destination _responseDest;
-
- private AMQConnection _connection;
-
- private Session _session;
- private Session _producerSession;
-
- private boolean _isTransactional;
-
- public ServiceProvidingClient(String brokerDetails, String username, String password,
- String clientName, String virtualPath, String serviceName,
- final int deliveryMode, boolean transactedMode, String selector)
- throws AMQException, JMSException, URLSyntaxException
- {
- _isTransactional = transactedMode;
-
- _logger.info("Delivery Mode: " + (deliveryMode == DeliveryMode.NON_PERSISTENT ? "Non Persistent" : "Persistent")
- + "\t isTransactional: " + _isTransactional);
-
- _connection = new AMQConnection(brokerDetails, username, password, clientName, virtualPath);
- _connection.setConnectionListener(new ConnectionListener()
- {
-
- public void bytesSent(long count)
- {
- }
-
- public void bytesReceived(long count)
- {
- }
-
- public boolean preFailover(boolean redirect)
- {
- return true;
- }
-
- public boolean preResubscribe()
- {
- return true;
- }
-
- public void failoverComplete()
- {
- _logger.info("App got failover complete callback");
- }
- });
- _session = (Session) _connection.createSession(_isTransactional, Session.AUTO_ACKNOWLEDGE);
- _producerSession = (Session) _connection.createSession(_isTransactional, Session.AUTO_ACKNOWLEDGE);
-
- _logger.info("Service (queue) name is '" + serviceName + "'...");
-
- AMQQueue destination = new AMQQueue(serviceName);
-
- MessageConsumer consumer = _session.createConsumer(destination,
- 100, true, false, selector);
-
- consumer.setMessageListener(new MessageListener()
- {
- private int _messageCount;
-
- public void onMessage(Message message)
- {
- //_logger.info("Got message '" + message + "'");
- TextMessage tm = (TextMessage) message;
- try
- {
- Destination responseDest = tm.getJMSReplyTo();
- if (responseDest == null)
- {
- _logger.info("Producer not created because the response destination is null.");
- return;
- }
-
- if (!responseDest.equals(_responseDest))
- {
- _responseDest = responseDest;
-
- _logger.info("About to create a producer");
- _destinationProducer = _producerSession.createProducer(responseDest);
- _destinationProducer.setDisableMessageTimestamp(true);
- _destinationProducer.setDeliveryMode(deliveryMode);
- _logger.info("After create a producer");
- }
- }
- catch (JMSException e)
- {
- _logger.error("Error creating destination");
- }
- _messageCount++;
- if (_messageCount % 1000 == 0)
- {
- _logger.info("Received message total: " + _messageCount);
- _logger.info("Sending response to '" + _responseDest + "'");
- }
-
- try
- {
- String payload = "This is a response: sing together: 'Mahnah mahnah...'" + tm.getText();
- TextMessage msg = _producerSession.createTextMessage(payload);
- if (tm.propertyExists("timeSent"))
- {
- _logger.info("timeSent property set on message");
- long timesent = tm.getLongProperty("timeSent");
- _logger.info("timeSent value is: " + timesent);
- msg.setLongProperty("timeSent", timesent);
- }
-
- _destinationProducer.send(msg);
-
- if (_isTransactional)
- {
- _producerSession.commit();
- }
- if (_isTransactional)
- {
- _session.commit();
- }
- if (_messageCount % 1000 == 0)
- {
- _logger.info("Sent response to '" + _responseDest + "'");
- }
- }
- catch (JMSException e)
- {
- _logger.error("Error sending message: " + e, e);
- }
- }
- });
- }
-
- public void run() throws JMSException
- {
- _connection.start();
- _logger.info("Waiting...");
- }
-
- public static void main(String[] args)
- {
- _logger.info("Starting...");
-
- if (args.length < 5)
- {
- System.out.println("Usage: serviceProvidingClient <brokerDetails> <username> <password> <virtual-path> <serviceQueue> [<P[ersistent]|N[onPersistent]> <T[ransacted]|N[onTransacted]>] [selector]");
- System.exit(1);
- }
- String clientId = null;
- try
- {
- InetAddress address = InetAddress.getLocalHost();
- clientId = address.getHostName() + System.currentTimeMillis();
- }
- catch (UnknownHostException e)
- {
- _logger.error("Error: " + e, e);
- }
-
- int deliveryMode = DeliveryMode.NON_PERSISTENT;
- boolean transactedMode = false;
-
- if (args.length > 7)
- {
- deliveryMode = args[args.length - 2].toUpperCase().charAt(0) == 'P' ? DeliveryMode.PERSISTENT
- : DeliveryMode.NON_PERSISTENT;
-
- transactedMode = args[args.length - 1].toUpperCase().charAt(0) == 'T' ? true : false;
- }
-
- String selector = null;
- if ((args.length == 8) || (args.length == 7))
- {
- selector = args[args.length - 1];
- }
-
- try
- {
- ServiceProvidingClient client = new ServiceProvidingClient(args[0], args[1], args[2],
- clientId, args[3], args[4],
- deliveryMode, transactedMode, selector);
- client.run();
- }
- catch (JMSException e)
- {
- _logger.error("Error: " + e, e);
- }
- catch (AMQException e)
- {
- _logger.error("Error: " + e, e);
- }
- catch (URLSyntaxException e)
- {
- _logger.error("Error: " + e, e);
- }
- }
-}
-
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceRequestingClient.java b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceRequestingClient.java
deleted file mode 100644
index 57512929c1..0000000000
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/ServiceRequestingClient.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- *
- * 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.qpid.requestreply;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.message.TestMessageFactory;
-import org.apache.qpid.client.message.JMSTextMessage;
-import org.apache.qpid.jms.MessageConsumer;
-import org.apache.qpid.jms.MessageProducer;
-import org.apache.qpid.jms.Session;
-import org.apache.qpid.url.URLSyntaxException;
-
-import javax.jms.*;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * A client that behaves as follows:
- * <ul><li>Connects to a queue, whose name is specified as a cmd-line argument</li>
- * <li>Creates a temporary queue</li>
- * <li>Creates messages containing a property(reply-to) that is the name of the temporary queue</li>
- * <li>Fires off a message on the original queue and registers the callbackHandler to listen to the response on the temporary queue</li>
- * <li>Start the loop to send all messages</li>
- * <li>CallbackHandler keeps listening to the responses and exits if all the messages have been received back or
- * if the waiting time for next message is elapsed</li>
- * </ul>
- */
-public class ServiceRequestingClient implements ExceptionListener
-{
- private static final Logger _log = Logger.getLogger(ServiceRequestingClient.class);
-
- private long _messageIdentifier = 0;
-
- // time for which callbackHandler should wait for a message before exiting. Default time= 60 secs
- private static long _callbackHandlerWaitingTime = 60000;
-
- private String MESSAGE_DATA;
-
- private AMQConnection _connection;
-
- private Session _session;
- private Session _producerSession;
-
- private long _averageLatency;
-
- private int _messageCount;
- private boolean _isTransactional;
-
- private volatile boolean _completed;
-
- private AMQDestination _tempDestination;
-
- private MessageProducer _producer;
-
- private Object _waiter;
-
- private class CallbackHandler implements MessageListener
- {
- private int _actualMessageCount;
-
- private long _startTime;
- // The time when the last message was received by the callbackHandler
- private long _messageReceivedTime = 0;
- private Object _timerCallbackHandler = new Object();
-
- public CallbackHandler(long startTime)
- {
- _startTime = startTime;
- // Start the timer thread, which will keep checking if test should exit because the waiting time has elapsed
- (new Thread(new TimerThread())).start();
- }
-
- public void onMessage(Message m)
- {
- _messageReceivedTime = System.currentTimeMillis();
- if (_log.isDebugEnabled())
- {
- _log.debug("Message received: " + m);
- }
- try
- {
- m.getPropertyNames();
- if (m.propertyExists("timeSent"))
- {
- long timeSent = m.getLongProperty("timeSent");
- if (_averageLatency == 0)
- {
- _averageLatency = _messageReceivedTime - timeSent;
- _log.info("Latency " + _averageLatency);
- }
- else
- {
- _log.info("Individual latency: " + (_messageReceivedTime - timeSent));
- _averageLatency = (_averageLatency + (_messageReceivedTime - timeSent)) / 2;
- _log.info("Average latency now: " + _averageLatency);
- }
- }
- if(_isTransactional)
- {
- _session.commit();
- }
- }
- catch (JMSException e)
- {
- _log.error("Error getting latency data: " + e, e);
- }
- _actualMessageCount++;
- if (_actualMessageCount % 1000 == 0)
- {
- _log.info("Received message count: " + _actualMessageCount);
- }
-
- checkForMessageID(m);
-
- if (_actualMessageCount == _messageCount)
- {
- finishTesting(_actualMessageCount);
- }
- }
-
- /**
- * sets completed flag to true, closes the callbackHandler connection and notifies the waiter thread,
- * so that the callbackHandler can finish listening for messages. This causes the test to finish.
- * @param receivedMessageCount
- */
- private void finishTesting(int receivedMessageCount)
- {
- _completed = true;
- notifyWaiter();
- notifyTimerThread();
-
- long timeTaken = System.currentTimeMillis() - _startTime;
- _log.info("***** Result *****");
- _log.info("Total messages received = " + receivedMessageCount);
- _log.info("Total time taken to receive " + receivedMessageCount + " messages was " +
- timeTaken + "ms, equivalent to " +
- (receivedMessageCount / (timeTaken / 1000.0)) + " messages per second");
-
- try
- {
- _connection.close();
- _log.info("Connection closed");
- }
- catch (JMSException e)
- {
- _log.error("Error closing connection");
- }
- }
-
- private void notifyTimerThread()
- {
- if (_timerCallbackHandler != null)
- {
- synchronized (_timerCallbackHandler)
- {
- _timerCallbackHandler.notify();
- }
- }
- }
-
- /**
- * Thread class implementing the timer for callbackHandler. The thread will exit the test if the waiting time
- * has elapsed before next message is received.
- */
- private class TimerThread implements Runnable
- {
- public void run()
- {
- do
- {
- try
- {
- synchronized(_timerCallbackHandler)
- {
- _timerCallbackHandler.wait(_callbackHandlerWaitingTime);
- }
- }
- catch (InterruptedException ignore)
- {
-
- }
-
- // exit if callbackHandler has received all messages
- if (_completed)
- {
- return;
- }
- }
- while ((System.currentTimeMillis() - _messageReceivedTime) < _callbackHandlerWaitingTime);
-
- // waiting time has elapsed, so exit the test
- _log.info("");
- _log.info("Exited after waiting for " + _callbackHandlerWaitingTime/1000 + " secs");
- finishTesting(_actualMessageCount);
- }
- }
- } // end of CallbackHandler class
-
- /**
- * Checks if the received AMQ Message ID(delivery tag) is in sequence, by comparing it with the AMQ MessageID
- * of previous message.
- * @param receivedMsg
- */
- private void checkForMessageID(Message receivedMsg)
- {
- try
- {
- JMSTextMessage msg = (JMSTextMessage)receivedMsg;
- if (! (msg.getDeliveryTag() == _messageIdentifier + 1))
- {
- _log.info("Out of sequence message received. Previous AMQ MessageID= " + _messageIdentifier +
- ", Received AMQ messageID= " + receivedMsg.getJMSMessageID());
- }
- _messageIdentifier = msg.getDeliveryTag();
- }
- catch (Exception ex)
- {
- _log.error("Error in checking messageID ", ex);
- }
-
- }
-
- private void notifyWaiter()
- {
- if (_waiter != null)
- {
- synchronized (_waiter)
- {
- _waiter.notify();
- }
- }
- }
-
- public ServiceRequestingClient(String brokerHosts, String clientID, String username, String password,
- String vpath, String commandQueueName,
- int deliveryMode, boolean transactedMode,
- final int messageCount, final int messageDataLength) throws AMQException, URLSyntaxException
- {
- _isTransactional = transactedMode;
-
- _log.info("Delivery Mode: " + (deliveryMode == DeliveryMode.NON_PERSISTENT ? "Non Persistent" : "Persistent"));
- _log.info("isTransactional: " + _isTransactional);
-
- _messageCount = messageCount;
- MESSAGE_DATA = TestMessageFactory.createMessagePayload(messageDataLength);
- try
- {
- createConnection(brokerHosts, clientID, username, password, vpath);
- _session = (Session) _connection.createSession(_isTransactional, Session.AUTO_ACKNOWLEDGE);
- _producerSession = (Session) _connection.createSession(_isTransactional, Session.AUTO_ACKNOWLEDGE);
-
- _connection.setExceptionListener(this);
-
- AMQQueue destination = new AMQQueue(commandQueueName);
- _producer = (MessageProducer) _producerSession.createProducer(destination);
- _producer.setDisableMessageTimestamp(true);
- _producer.setDeliveryMode(deliveryMode);
-
- _tempDestination = new AMQQueue("TempResponse" +
- Long.toString(System.currentTimeMillis()), true);
- MessageConsumer messageConsumer = (MessageConsumer) _session.createConsumer(_tempDestination, 100, true,
- true, null);
-
- //Send first message, then wait a bit to allow the provider to get initialised
- TextMessage first = _session.createTextMessage(MESSAGE_DATA);
- first.setJMSReplyTo(_tempDestination);
- _producer.send(first);
- if (_isTransactional)
- {
- _producerSession.commit();
- }
- try
- {
- Thread.sleep(1000);
- }
- catch (InterruptedException ignore)
- {
- }
-
- //now start the clock and the test...
- final long startTime = System.currentTimeMillis();
-
- messageConsumer.setMessageListener(new CallbackHandler(startTime));
- }
- catch (JMSException e)
- {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
- }
- }
-
- /**
- * Run the test and notify an object upon receipt of all responses.
- *
- * @param waiter the object that will be notified
- * @throws JMSException
- */
- public void run(Object waiter) throws JMSException
- {
- _waiter = waiter;
- _connection.start();
- for (int i = 1; i < _messageCount; i++)
- {
- TextMessage msg = _producerSession.createTextMessage(MESSAGE_DATA + i);
- msg.setJMSReplyTo(_tempDestination);
- if (i % 1000 == 0)
- {
- long timeNow = System.currentTimeMillis();
- msg.setLongProperty("timeSent", timeNow);
- }
- _producer.send(msg);
- if (_isTransactional)
- {
- _producerSession.commit();
- }
-
- }
- _log.info("Finished sending " + _messageCount + " messages");
- }
-
- public boolean isCompleted()
- {
- return _completed;
- }
-
- private void createConnection(String brokerHosts, String clientID, String username, String password,
- String vpath) throws AMQException, URLSyntaxException
- {
- _connection = new AMQConnection(brokerHosts, username, password, clientID, vpath);
- }
-
- /**
- * @param args argument 1 if present specifies the name of the temporary queue to create. Leaving it blank
- * means the server will allocate a name.
- */
- public static void main(String[] args)
- {
- if ((args.length < 6) || (args.length == 8))
- {
- System.err.println("Usage: ServiceRequestingClient <brokerDetails> <username> <password> <vpath> " +
- "<command queue name> <number of messages> [<message size>] " +
- "[<P[ersistent]|N[onPersistent] (Default N)> <T[ransacted]|N[onTransacted] (Default N)>] " +
- "[<waiting time for response in sec (default 60 sec)>]");
- System.exit(1);
- }
- try
- {
- int messageSize = 4096;
- boolean transactedMode = false;
- int deliveryMode = DeliveryMode.NON_PERSISTENT;
-
- if (args.length > 6)
- {
- messageSize = Integer.parseInt(args[6]);
- }
- if (args.length > 7)
- {
- deliveryMode = args[7].toUpperCase().charAt(0) == 'P' ? DeliveryMode.PERSISTENT
- : DeliveryMode.NON_PERSISTENT;
-
- transactedMode = args[8].toUpperCase().charAt(0) == 'T' ? true : false;
- }
-
- if (args.length > 9)
- {
- _callbackHandlerWaitingTime = Long.parseLong(args[9]) * 1000;
- }
-
- _log.info("Each message size = " + messageSize + " bytes");
-
- InetAddress address = InetAddress.getLocalHost();
- String clientID = address.getHostName() + System.currentTimeMillis();
- ServiceRequestingClient client = new ServiceRequestingClient(args[0], clientID, args[1], args[2], args[3],
- args[4], deliveryMode, transactedMode, Integer.parseInt(args[5]),
- messageSize);
- Object waiter = new Object();
- client.run(waiter);
-
- // Start a thread to
- synchronized (waiter)
- {
- while (!client.isCompleted())
- {
- waiter.wait();
- }
- }
- }
- catch (UnknownHostException e)
- {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
- }
- catch (Exception e)
- {
- System.err.println("Error in client: " + e);
- e.printStackTrace();
- }
- }
-
- /**
- * @see javax.jms.ExceptionListener#onException(javax.jms.JMSException)
- */
- public void onException(JMSException e)
- {
- System.err.println(e.getMessage());
- e.printStackTrace(System.err);
- }
-}
diff --git a/qpid/java/perftests/src/main/java/perftests.log4j b/qpid/java/perftests/src/main/java/perftests.log4j
index a6e1bd5452..3bd8c201f8 100644
--- a/qpid/java/perftests/src/main/java/perftests.log4j
+++ b/qpid/java/perftests/src/main/java/perftests.log4j
@@ -24,19 +24,19 @@ log4j.additivity.org.apache.qpid=false
log4j.logger.org.apache.qpid.requestreply=${amqj.test.logging.level}
log4j.logger.org.apache.qpid.pingpong=${amqj.test.logging.level}
+log4j.logger.org.apache.qpid.ping=${amqj.test.logging.level}
log4j.logger.org.apache.qpid.topic=${amqj.test.logging.level}
-log4j.logger.uk.co.thebadgerset.junit.extensions=info, console
+log4j.logger.uk.co.thebadgerset.junit.extensions=${badger.level}, console
log4j.additivity.uk.co.thebadgerset.junit.extensions=false
-log4j.logger.uk.co.thebadgerset.junit.extensions=info
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=all
log4j.appender.console.layout=org.apache.log4j.PatternLayout
-#log4j.appender.console.layout.ConversionPattern=%t %d %p [%c{4}] %m%n
-log4j.appender.console.layout.ConversionPattern=%p [%c] %m%n
+log4j.appender.console.layout.ConversionPattern=%t %d %p [%c{4}] %m%n
+#log4j.appender.console.layout.ConversionPattern=%t %p [%c] %m%n
log4j.appender.fileApp=org.apache.log4j.FileAppender
log4j.appender.fileApp.file=${log.dir}/perftests.volumetest.log
diff --git a/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java b/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java
index 63e966c63a..27de27faf3 100644
--- a/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java
+++ b/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java
@@ -1,54 +1,92 @@
/*
- * 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
+ * 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
*
- * 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.
+ * 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.qpid.ping;
-import uk.co.thebadgerset.junit.extensions.TimingControllerAware;
-import uk.co.thebadgerset.junit.extensions.TimingController;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
-import javax.jms.MessageListener;
-import javax.jms.ObjectMessage;
import javax.jms.JMSException;
import javax.jms.Message;
+import javax.jms.ObjectMessage;
-import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
-import org.apache.log4j.Logger;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.CountDownLatch;
+import org.apache.log4j.Logger;
+import org.apache.qpid.requestreply.PingPongProducer;
+import uk.co.thebadgerset.junit.extensions.TimingController;
+import uk.co.thebadgerset.junit.extensions.TimingControllerAware;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+/**
+ * PingAsyncTestPerf is a performance test that outputs multiple timings from its test method, using the timing controller
+ * interface supplied by the test runner from a seperate listener thread. It differs from the {@link PingTestPerf} test
+ * that it extends because it can output timings as replies are received, rather than waiting until all expected replies
+ * are received. This is less 'blocky' than the tests in {@link PingTestPerf}, and provides a truer simulation of sending
+ * and recieving clients working asynchronously.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><td> Responsibilities <th> Collaborations
+ * <tr><td> Send many ping messages and output timings asynchronously on batches received.
+ * </table>
+ */
public class PingAsyncTestPerf extends PingTestPerf implements TimingControllerAware
{
private static Logger _logger = Logger.getLogger(PingAsyncTestPerf.class);
+ /** Holds the name of the property to get the test results logging batch size. */
+ public static final String TEST_RESULTS_BATCH_SIZE_PROPNAME = "BatchSize";
+
+ /** Holds the default test results logging batch size. */
+ public static final int DEFAULT_TEST_RESULTS_BATCH_SIZE = 1000;
+
+ /** Used to hold the timing controller passed from the test runner. */
private TimingController _timingController;
- private AsyncMessageListener _listener;
+ /** Used to generate unique correlation ids for each test run. */
+ private AtomicLong corellationIdGenerator = new AtomicLong();
+ /** Holds test specifics by correlation id. This consists of the expected number of messages and the timing controler. */
+ private Map<String, PerCorrelationId> perCorrelationIds =
+ Collections.synchronizedMap(new HashMap<String, PerCorrelationId>());
+
+ /** Holds the batched results listener, that does logging on batch boundaries. */
+ private BatchedResultsListener batchedResultsListener = null;
+
+ /**
+ * Creates a new asynchronous ping performance test with the specified name.
+ *
+ * @param name The test name.
+ */
public PingAsyncTestPerf(String name)
{
super(name);
+
+ // Sets up the test parameters with defaults.
+ ParsedProperties.setSysPropertyIfNull(TEST_RESULTS_BATCH_SIZE_PROPNAME,
+ Integer.toString(DEFAULT_TEST_RESULTS_BATCH_SIZE));
}
/**
@@ -65,248 +103,200 @@ public class PingAsyncTestPerf extends PingTestPerf implements TimingControllerA
return suite;
}
- protected void setUp() throws Exception
+ /**
+ * Accepts a timing controller from the test runner.
+ *
+ * @param timingController The timing controller to register mutliple timings with.
+ */
+ public void setTimingController(TimingController timingController)
{
- // Create the test setups on a per thread basis, only if they have not already been created.
-
- if (threadSetup.get() == null)
- {
- PerThreadSetup perThreadSetup = new PerThreadSetup();
-
- // Extract the test set up paramaeters.
- String brokerDetails = testParameters.getProperty(BROKER_PROPNAME);
- String username = "guest";
- String password = "guest";
- String virtualpath = testParameters.getProperty(VIRTUAL_PATH_PROPNAME);
- int destinationscount = Integer.parseInt(testParameters.getProperty(PING_DESTINATION_COUNT_PROPNAME));
- String destinationname = testParameters.getProperty(PING_DESTINATION_NAME_PROPNAME);
- boolean persistent = Boolean.parseBoolean(testParameters.getProperty(PERSISTENT_MODE_PROPNAME));
- boolean transacted = Boolean.parseBoolean(testParameters.getProperty(TRANSACTED_PROPNAME));
- String selector = null;
- boolean verbose = Boolean.parseBoolean(testParameters.getProperty(VERBOSE_OUTPUT_PROPNAME));
- int messageSize = Integer.parseInt(testParameters.getProperty(MESSAGE_SIZE_PROPNAME));
- int rate = Integer.parseInt(testParameters.getProperty(RATE_PROPNAME));
- boolean pubsub = Boolean.parseBoolean(testParameters.getProperty(IS_PUBSUB_PROPNAME));
-
-
- boolean afterCommit = Boolean.parseBoolean(testParameters.getProperty(FAIL_AFTER_COMMIT));
- boolean beforeCommit = Boolean.parseBoolean(testParameters.getProperty(FAIL_BEFORE_COMMIT));
- boolean afterSend = Boolean.parseBoolean(testParameters.getProperty(FAIL_AFTER_SEND));
- boolean beforeSend = Boolean.parseBoolean(testParameters.getProperty(FAIL_BEFORE_SEND));
- boolean failOnce = Boolean.parseBoolean(testParameters.getProperty(FAIL_ONCE));
-
- int batchSize = Integer.parseInt(testParameters.getProperty(BATCH_SIZE));
- int commitbatchSize = Integer.parseInt(testParameters.getProperty(COMMIT_BATCH_SIZE));
-
- // This is synchronized because there is a race condition, which causes one connection to sleep if
- // all threads try to create connection concurrently
- synchronized (this)
- {
- // Establish a client to ping a Queue and listen the reply back from same Queue
- perThreadSetup._pingItselfClient = new TestPingItself(brokerDetails, username, password, virtualpath,
- destinationname, selector, transacted, persistent,
- messageSize, verbose,
- afterCommit, beforeCommit, afterSend, beforeSend, failOnce,
- commitbatchSize, destinationscount, rate, pubsub);
- }
-
- // Attach the per-thread set to the thread.
- threadSetup.set(perThreadSetup);
-
- _listener = new AsyncMessageListener(batchSize);
-
- perThreadSetup._pingItselfClient.setMessageListener(_listener);
- // Start the client connection
- perThreadSetup._pingItselfClient.getConnection().start();
-
- }
+ _timingController = timingController;
}
-
- public void testAsyncPingOk(int numPings)
+ /**
+ * Gets the timing controller passed in by the test runner.
+ *
+ * @return The timing controller passed in by the test runner.
+ */
+ public TimingController getTimingController()
{
- _timingController = this.getTimingController();
+ return _timingController;
+ }
- _listener.setTotalMessages(numPings);
+ /**
+ * Sends the specified number of pings, asynchronously outputs timings on every batch boundary, and waits until
+ * all replies have been received or a time out occurs before exiting this method.
+ *
+ * @param numPings The number of pings to send.
+ */
+ public void testAsyncPingOk(int numPings) throws Exception
+ {
+ _logger.debug("public void testAsyncPingOk(int numPings): called");
- PerThreadSetup perThreadSetup = threadSetup.get();
+ // Ensure that at least one ping was requeusted.
if (numPings == 0)
{
_logger.error("Number of pings requested was zero.");
- fail("Number of pings requested was zero.");
}
- // Generate a sample message. This message is already time stamped and has its reply-to destination set.
- ObjectMessage msg = null;
-
- try
- {
- msg = perThreadSetup._pingItselfClient.getTestMessage(null,
- Integer.parseInt(testParameters.getProperty(
- MESSAGE_SIZE_PROPNAME)),
- Boolean.parseBoolean(testParameters.getProperty(
- PERSISTENT_MODE_PROPNAME)));
- }
- catch (JMSException e)
+ // Get the per thread test setup to run the test through.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+ PingClient pingClient = perThreadSetup._pingClient;
+
+ // Advance the correlation id of messages to send, to make it unique for this run.
+ String messageCorrelationId = Long.toString(corellationIdGenerator.incrementAndGet());
+ _logger.debug("messageCorrelationId = " + messageCorrelationId);
+
+ // Initialize the count and timing controller for the new correlation id.
+ PerCorrelationId perCorrelationId = new PerCorrelationId();
+ TimingController tc = getTimingController().getControllerForCurrentThread();
+ perCorrelationId._tc = tc;
+ perCorrelationId._expectedCount = numPings;
+ perCorrelationIds.put(messageCorrelationId, perCorrelationId);
+
+ // Attach the chained message listener to the ping producer to listen asynchronously for the replies to these
+ // messages.
+ pingClient.setChainedMessageListener(batchedResultsListener);
+
+ // Generate a sample message of the specified size.
+ ObjectMessage msg =
+ pingClient.getTestMessage(perThreadSetup._pingClient.getReplyDestinations().get(0),
+ testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME),
+ testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME));
+
+ // Send the requested number of messages, and wait until they have all been received.
+ long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME));
+ int numReplies = pingClient.pingAndWaitForReply(msg, numPings, timeout);
+
+ // Check that all the replies were received and log a fail if they were not.
+ if (numReplies < numPings)
{
-
+ tc.completeTest(false, numPings - numReplies);
}
- // start the test
- long timeout = Long.parseLong(testParameters.getProperty(TIMEOUT_PROPNAME));
-
- String correlationID = Long.toString(perThreadSetup._pingItselfClient.getNewID());
-
- try
- {
- _logger.debug("Sending messages");
+ // Remove the chained message listener from the ping producer.
+ pingClient.removeChainedMessageListener();
- perThreadSetup._pingItselfClient.pingNoWaitForReply(msg, numPings, correlationID);
+ // Remove the expected count and timing controller for the message correlation id, to ensure they are cleaned up.
+ perCorrelationIds.remove(messageCorrelationId);
+ }
- _logger.debug("All sent");
- }
- catch (JMSException e)
- {
- e.printStackTrace();
- Assert.fail("JMS Exception Received" + e);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
+ /**
+ * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
+ */
+ public void threadSetUp()
+ {
+ _logger.debug("public void threadSetUp(): called");
try
{
- _logger.debug("Awating test finish");
-
- perThreadSetup._pingItselfClient.getEndLock(correlationID).await(timeout, TimeUnit.MILLISECONDS);
+ // Call the set up method in the super class. This creates a PingClient pinger.
+ super.threadSetUp();
- if (perThreadSetup._pingItselfClient.getEndLock(correlationID).getCount() != 0)
- {
- _logger.error("Timeout occured");
- }
- //Allow the time out to exit the loop.
- }
- catch (InterruptedException e)
- {
- //ignore
- _logger.error("Awaiting test end was interrupted.");
-
- }
-
- // Fail the test if the timeout was exceeded.
- int numReplies = numPings - (int) perThreadSetup._pingItselfClient.removeLock(correlationID).getCount();
-
- _logger.info("Test Finished");
-
- if (numReplies != numPings)
- {
- try
- {
- perThreadSetup._pingItselfClient.commitTx(perThreadSetup._pingItselfClient.getConsumerSession());
- }
- catch (JMSException e)
- {
- _logger.error("Error commiting received messages", e);
- }
- try
+ // Create the chained message listener, only if it has not already been created. This is set up with the
+ // batch size property, to tell it what batch size to output results on. A synchronized block is used to
+ // ensure that only one thread creates this.
+ synchronized (this)
{
- if (_timingController != null)
+ if (batchedResultsListener == null)
{
- _logger.trace("Logging missing message count");
- _timingController.completeTest(false, numPings - numReplies);
+ int batchSize = Integer.parseInt(testParameters.getProperty(TEST_RESULTS_BATCH_SIZE_PROPNAME));
+ batchedResultsListener = new BatchedResultsListener(batchSize);
}
}
- catch (InterruptedException e)
- {
- //ignore
- }
- Assert.fail("The ping timed out after " + timeout + " ms. Messages Sent = " + numPings + ", MessagesReceived = " + numReplies);
- }
- }
-
- public void setTimingController(TimingController timingController)
- {
- _timingController = timingController;
- }
-
- public TimingController getTimingController()
- {
- return _timingController;
- }
-
- private class AsyncMessageListener implements MessageListener
- {
- private volatile int _totalMessages;
- private int _batchSize;
- PerThreadSetup _perThreadSetup;
+ // Get the set up that the super class created.
+ PerThreadSetup perThreadSetup = threadSetup.get();
- public AsyncMessageListener(int batchSize)
+ // Register the chained message listener on the pinger to do its asynchronous test timings from.
+ perThreadSetup._pingClient.setChainedMessageListener(batchedResultsListener);
+ }
+ catch (Exception e)
{
- this(batchSize, -1);
+ _logger.warn("There was an exception during per thread setup.", e);
}
+ }
- public AsyncMessageListener(int batchSize, int totalMessages)
+ /**
+ * BatchedResultsListener is a {@link PingPongProducer.ChainedMessageListener} that can be attached to the
+ * pinger, in order to receive notifications about every message received and the number remaining to be
+ * received. Whenever the number remaining crosses a batch size boundary this results listener outputs
+ * a test timing for the actual number of messages received in the current batch.
+ */
+ private class BatchedResultsListener implements PingPongProducer.ChainedMessageListener
+ {
+ /** The test results logging batch size. */
+ int _batchSize;
+
+ /**
+ * Creates a results listener on the specified batch size.
+ *
+ * @param batchSize The batch size to use.
+ */
+ public BatchedResultsListener(int batchSize)
{
_batchSize = batchSize;
- _totalMessages = totalMessages;
- _perThreadSetup = threadSetup.get();
}
- public void setTotalMessages(int newTotal)
+ /**
+ * This callback method is called from all of the pingers that this test creates. It uses the correlation id
+ * from the message to identify the timing controller for the test thread that was responsible for sending those
+ * messages.
+ *
+ * @param message The message.
+ * @param remainingCount The count of messages remaining to be received with a particular correlation id.
+ *
+ * @throws JMSException Any underlying JMSException is allowed to fall through.
+ */
+ public void onMessage(Message message, int remainingCount) throws JMSException
{
- _totalMessages = newTotal;
- }
+ _logger.debug("public void onMessage(Message message, int remainingCount = " + remainingCount + "): called");
- public void onMessage(Message message)
- {
- try
+ // Check if a batch boundary has been crossed.
+ if ((remainingCount % _batchSize) == 0)
{
- _logger.trace("Message Received");
+ // Extract the correlation id from the message.
+ String correlationId = message.getJMSCorrelationID();
- CountDownLatch count = _perThreadSetup._pingItselfClient.getEndLock(message.getJMSCorrelationID());
-
- if (count != null)
+ // Get the details for the correlation id and check that they are not null. They can become null
+ // if a test times out.
+ PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationId);
+ if (perCorrelationId != null)
{
- int messagesLeft = (int) count.getCount() - 1;// minus one as we haven't yet counted the current message
-
- if ((messagesLeft % _batchSize) == 0)
+ // Get the timing controller and expected count for this correlation id.
+ TimingController tc = perCorrelationId._tc;
+ int expected = perCorrelationId._expectedCount;
+
+ // Calculate how many messages were actually received in the last batch. This will be the batch size
+ // except where the number expected is not a multiple of the batch size and this is the first remaining
+ // count to cross a batch size boundary, in which case it will be the number expected modulo the batch
+ // size.
+ int receivedInBatch = ((expected - remainingCount) < _batchSize) ? (expected % _batchSize) : _batchSize;
+
+ // Register a test result for the correlation id.
+ try
{
- doDone(_batchSize);
+
+ tc.completeTest(true, receivedInBatch);
}
- else if (messagesLeft == 0)
+ catch (InterruptedException e)
{
- doDone(_totalMessages % _batchSize);
+ // Ignore this. It means the test runner wants to stop as soon as possible.
+ _logger.warn("Got InterruptedException.", e);
}
}
-
- }
- catch (JMSException e)
- {
- _logger.warn("There was a JMSException", e);
- }
-
- }
-
- private void doDone(int messageCount)
- {
- _logger.trace("Messages received:" + messageCount);
- _logger.trace("Total Messages :" + _totalMessages);
-
- try
- {
- if (_timingController != null)
- {
- _timingController.completeTest(true, messageCount);
- }
- }
- catch (InterruptedException e)
- {
- //ignore
+ // Else ignore, test timed out. Should log a fail here?
}
}
-
}
+ /**
+ * Holds state specific to each correlation id, needed to output test results. This consists of the count of
+ * the total expected number of messages, and the timing controller for the thread sending those message ids.
+ */
+ private static class PerCorrelationId
+ {
+ public int _expectedCount;
+ public TimingController _tc;
+ }
}
diff --git a/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingLatencyTestPerf.java b/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingLatencyTestPerf.java
new file mode 100644
index 0000000000..068baa57a9
--- /dev/null
+++ b/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingLatencyTestPerf.java
@@ -0,0 +1,317 @@
+/*
+ *
+ * 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.qpid.ping;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.ObjectMessage;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.requestreply.PingPongProducer;
+
+import uk.co.thebadgerset.junit.extensions.TimingController;
+import uk.co.thebadgerset.junit.extensions.TimingControllerAware;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+/**
+ * PingLatencyTestPerf is a performance test that outputs multiple timings from its test method, using the timing
+ * controller interface supplied by the test runner from a seperate listener thread. It outputs round trip timings for
+ * individual ping messages rather than for how long a complete batch of messages took to process. It also differs from
+ * the {@link PingTestPerf} test that it extends because it can output timings as replies are received, rather than
+ * waiting until all expected replies are received.
+ *
+ * <p/>This test does not output timings for every single ping message, as when running at high volume, writing the test
+ * log for a vast number of messages would slow the testing down. Instead samples ping latency occasionally. The frequency
+ * of ping sampling is set using the {@link #TEST_RESULTS_BATCH_SIZE_PROPNAME} property, to override the default of every
+ * {@link #DEFAULT_TEST_RESULTS_BATCH_SIZE}.
+ *
+ * <p/>The size parameter logged for each individual ping is set to the size of the batch of messages that the individual
+ * timed ping was taken from, rather than 1 for a single message. This is so that the total throughput (messages / time)
+ * can be calculated in order to examine the relationship between throughput and latency.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><td> Responsibilities <th> Collaborations
+ * <tr><td> Send many ping messages and output timings for sampled individual pings.
+ * </table>
+ */
+public class PingLatencyTestPerf extends PingTestPerf implements TimingControllerAware
+{
+ private static Logger _logger = Logger.getLogger(PingLatencyTestPerf.class);
+
+ /** Holds the name of the property to get the test results logging batch size. */
+ public static final String TEST_RESULTS_BATCH_SIZE_PROPNAME = "BatchSize";
+
+ /** Holds the default test results logging batch size. */
+ public static final int DEFAULT_TEST_RESULTS_BATCH_SIZE = 1000;
+
+ /** Used to hold the timing controller passed from the test runner. */
+ private TimingController _timingController;
+
+ /** Used to generate unique correlation ids for each test run. */
+ private AtomicLong corellationIdGenerator = new AtomicLong();
+
+ /** Holds test specifics by correlation id. This consists of the expected number of messages and the timing controler. */
+ private Map<String, PerCorrelationId> perCorrelationIds =
+ Collections.synchronizedMap(new HashMap<String, PerCorrelationId>());
+
+ /** Holds the batched results listener, that does logging on batch boundaries. */
+ private BatchedResultsListener batchedResultsListener = null;
+
+ /**
+ * Creates a new asynchronous ping performance test with the specified name.
+ *
+ * @param name The test name.
+ */
+ public PingLatencyTestPerf(String name)
+ {
+ super(name);
+
+ // Sets up the test parameters with defaults.
+ ParsedProperties.setSysPropertyIfNull(TEST_RESULTS_BATCH_SIZE_PROPNAME,
+ Integer.toString(DEFAULT_TEST_RESULTS_BATCH_SIZE));
+ }
+
+ /**
+ * Compile all the tests into a test suite.
+ */
+ public static Test suite()
+ {
+ // Build a new test suite
+ TestSuite suite = new TestSuite("Ping Latency Tests");
+
+ // Run performance tests in read committed mode.
+ suite.addTest(new PingLatencyTestPerf("testPingLatency"));
+
+ return suite;
+ }
+
+ /**
+ * Accepts a timing controller from the test runner.
+ *
+ * @param timingController The timing controller to register mutliple timings with.
+ */
+ public void setTimingController(TimingController timingController)
+ {
+ _timingController = timingController;
+ }
+
+ /**
+ * Gets the timing controller passed in by the test runner.
+ *
+ * @return The timing controller passed in by the test runner.
+ */
+ public TimingController getTimingController()
+ {
+ return _timingController;
+ }
+
+ /**
+ * Sends the specified number of pings, asynchronously outputs timings on every batch boundary, and waits until
+ * all replies have been received or a time out occurs before exiting this method.
+ *
+ * @param numPings The number of pings to send.
+ */
+ public void testPingLatency(int numPings) throws Exception
+ {
+ _logger.debug("public void testPingLatency(int numPings): called");
+
+ // Ensure that at least one ping was requeusted.
+ if (numPings == 0)
+ {
+ _logger.error("Number of pings requested was zero.");
+ }
+
+ // Get the per thread test setup to run the test through.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+ PingClient pingClient = perThreadSetup._pingClient;
+
+ // Advance the correlation id of messages to send, to make it unique for this run.
+ String messageCorrelationId = Long.toString(corellationIdGenerator.incrementAndGet());
+ _logger.debug("messageCorrelationId = " + messageCorrelationId);
+
+ // Initialize the count and timing controller for the new correlation id.
+ PerCorrelationId perCorrelationId = new PerCorrelationId();
+ TimingController tc = getTimingController().getControllerForCurrentThread();
+ perCorrelationId._tc = tc;
+ perCorrelationId._expectedCount = numPings;
+ perCorrelationIds.put(messageCorrelationId, perCorrelationId);
+
+ // Attach the chained message listener to the ping producer to listen asynchronously for the replies to these
+ // messages.
+ pingClient.setChainedMessageListener(batchedResultsListener);
+
+ // Generate a sample message of the specified size.
+ ObjectMessage msg =
+ pingClient.getTestMessage(perThreadSetup._pingClient.getReplyDestinations().get(0),
+ testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME),
+ testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME));
+
+ // Send the requested number of messages, and wait until they have all been received.
+ long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME));
+ int numReplies = pingClient.pingAndWaitForReply(msg, numPings, timeout);
+
+ // Check that all the replies were received and log a fail if they were not.
+ if (numReplies < numPings)
+ {
+ tc.completeTest(false, 0);
+ }
+
+ // Remove the chained message listener from the ping producer.
+ pingClient.removeChainedMessageListener();
+
+ // Remove the expected count and timing controller for the message correlation id, to ensure they are cleaned up.
+ perCorrelationIds.remove(messageCorrelationId);
+ }
+
+ /**
+ * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
+ */
+ public void threadSetUp()
+ {
+ _logger.debug("public void threadSetUp(): called");
+
+ try
+ {
+ // Call the set up method in the super class. This creates a PingClient pinger.
+ super.threadSetUp();
+
+ // Create the chained message listener, only if it has not already been created. This is set up with the
+ // batch size property, to tell it what batch size to output results on. A synchronized block is used to
+ // ensure that only one thread creates this.
+ synchronized (this)
+ {
+ if (batchedResultsListener == null)
+ {
+ int batchSize = Integer.parseInt(testParameters.getProperty(TEST_RESULTS_BATCH_SIZE_PROPNAME));
+ batchedResultsListener = new BatchedResultsListener(batchSize);
+ }
+ }
+
+ // Get the set up that the super class created.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+
+ // Register the chained message listener on the pinger to do its asynchronous test timings from.
+ perThreadSetup._pingClient.setChainedMessageListener(batchedResultsListener);
+ }
+ catch (Exception e)
+ {
+ _logger.warn("There was an exception during per thread setup.", e);
+ }
+ }
+
+ /**
+ * BatchedResultsListener is a {@link org.apache.qpid.requestreply.PingPongProducer.ChainedMessageListener} that can
+ * be attached to the pinger, in order to receive notifications about every message received and the number remaining
+ * to be received. Whenever the number remaining crosses a batch size boundary this results listener outputs a test
+ * timing for the actual number of messages received in the current batch.
+ */
+ private class BatchedResultsListener implements PingPongProducer.ChainedMessageListener
+ {
+ /** The test results logging batch size. */
+ int _batchSize;
+
+ /**
+ * Creates a results listener on the specified batch size.
+ *
+ * @param batchSize The batch size to use.
+ */
+ public BatchedResultsListener(int batchSize)
+ {
+ _batchSize = batchSize;
+ }
+
+ /**
+ * This callback method is called from all of the pingers that this test creates. It uses the correlation id
+ * from the message to identify the timing controller for the test thread that was responsible for sending those
+ * messages.
+ *
+ * @param message The message.
+ * @param remainingCount The count of messages remaining to be received with a particular correlation id.
+ *
+ * @throws javax.jms.JMSException Any underlying JMSException is allowed to fall through.
+ */
+ public void onMessage(Message message, int remainingCount) throws JMSException
+ {
+ _logger.debug("public void onMessage(Message message, int remainingCount = " + remainingCount + "): called");
+
+ // Check if a batch boundary has been crossed.
+ if ((remainingCount % _batchSize) == 0)
+ {
+ // Extract the correlation id from the message.
+ String correlationId = message.getJMSCorrelationID();
+
+ // Get the details for the correlation id and check that they are not null. They can become null
+ // if a test times out.
+ PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationId);
+ if (perCorrelationId != null)
+ {
+ // Get the timing controller and expected count for this correlation id.
+ TimingController tc = perCorrelationId._tc;
+ int expected = perCorrelationId._expectedCount;
+
+ // Extract the send time from the message and work out from the current time, what the ping latency was.
+ // The ping producer time stamps messages in nanoseconds.
+ long startTime = message.getLongProperty(PingPongProducer.MESSAGE_TIMESTAMP_PROPNAME);
+ long now = System.nanoTime();
+ long pingTime = now - startTime;
+
+ // Calculate how many messages were actually received in the last batch. This will be the batch size
+ // except where the number expected is not a multiple of the batch size and this is the first remaining
+ // count to cross a batch size boundary, in which case it will be the number expected modulo the batch
+ // size.
+ int receivedInBatch = ((expected - remainingCount) < _batchSize) ? (expected % _batchSize) : _batchSize;
+
+ // Register a test result for the correlation id.
+ try
+ {
+
+ tc.completeTest(true, receivedInBatch, pingTime);
+ }
+ catch (InterruptedException e)
+ {
+ // Ignore this. It means the test runner wants to stop as soon as possible.
+ _logger.warn("Got InterruptedException.", e);
+ }
+ }
+ // Else ignore, test timed out. Should log a fail here?
+ }
+ }
+ }
+
+ /**
+ * Holds state specific to each correlation id, needed to output test results. This consists of the count of
+ * the total expected number of messages, and the timing controller for the thread sending those message ids.
+ */
+ private static class PerCorrelationId
+ {
+ public int _expectedCount;
+ public TimingController _tc;
+ }
+}
diff --git a/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingTestPerf.java b/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingTestPerf.java
index 774c6f94b8..f21352926b 100644
--- a/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingTestPerf.java
+++ b/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingTestPerf.java
@@ -1,7 +1,25 @@
+/*
+ *
+ * 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.qpid.ping;
-import java.util.Properties;
-
import javax.jms.*;
import junit.framework.Assert;
@@ -10,169 +28,85 @@ import junit.framework.TestSuite;
import org.apache.log4j.Logger;
+import org.apache.qpid.requestreply.PingPongProducer;
+
import uk.co.thebadgerset.junit.extensions.AsymptoticTestCase;
+import uk.co.thebadgerset.junit.extensions.TestThreadAware;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
/**
* PingTestPerf is a ping test, that has been written with the intention of being scaled up to run many times
* simultaneously to simluate many clients/producers/connections.
- * <p/>
+ *
* <p/>A single run of the test using the default JUnit test runner will result in the sending and timing of a single
* full round trip ping. This test may be scaled up using a suitable JUnit test runner.
- * <p/>
+ *
* <p/>The setup/teardown cycle establishes a connection to a broker and sets up a queue to send ping messages to and a
* temporary queue for replies. This setup is only established once for all the test repeats/threads that may be run,
* except if the connection is lost in which case an attempt to re-establish the setup is made.
- * <p/>
+ *
* <p/>The test cycle is: Connects to a queue, creates a temporary queue, creates messages containing a property that
* is the name of the temporary queue, fires off a message on the original queue and waits for a response on the
* temporary queue.
- * <p/>
+ *
* <p/>Configurable test properties: message size, transacted or not, persistent or not. Broker connection details.
- * <p/>
+ *
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* </table>
*
* @author Rupert Smith
*/
-public class PingTestPerf extends AsymptoticTestCase //implements TimingControllerAware
+public class PingTestPerf extends AsymptoticTestCase implements TestThreadAware
{
private static Logger _logger = Logger.getLogger(PingTestPerf.class);
- /**
- * Holds the name of the property to get the test message size from.
- */
- protected static final String MESSAGE_SIZE_PROPNAME = "messagesize";
-
- /**
- * Holds the name of the property to get the ping queue name from.
- */
- protected static final String PING_DESTINATION_NAME_PROPNAME = "destinationname";
-
- /**
- * holds the queue count, if the test is being performed with multiple queues
- */
- protected static final String PING_DESTINATION_COUNT_PROPNAME = "destinationscount";
-
- /**
- * Holds the name of the property to get the test delivery mode from.
- */
- protected static final String PERSISTENT_MODE_PROPNAME = "persistent";
-
- /**
- * Holds the name of the property to get the test transactional mode from.
- */
- protected static final String TRANSACTED_PROPNAME = "transacted";
-
- /**
- * Holds the name of the property to get the test broker url from.
- */
- protected static final String BROKER_PROPNAME = "broker";
-
- /**
- * Holds the name of the property to get the test broker virtual path.
- */
- protected static final String VIRTUAL_PATH_PROPNAME = "virtualPath";
-
- /**
- * Holds the name of the property to get the waiting timeout for response messages.
- */
- protected static final String TIMEOUT_PROPNAME = "timeout";
-
- /** Holds the name of the property to get the message rate from. */
- protected static final String RATE_PROPNAME = "rate";
-
- protected static final String VERBOSE_OUTPUT_PROPNAME = "verbose";
-
- /** Holds the true or false depending on wether it is P2P test or PubSub */
- protected static final String IS_PUBSUB_PROPNAME = "pubsub";
- /**
- * Holds the size of message body to attach to the ping messages.
- */
- protected static final int MESSAGE_SIZE_DEFAULT = 1024;
-
- protected static final int BATCH_SIZE_DEFAULT = 1000;
-
- protected static final int COMMIT_BATCH_SIZE_DEFAULT = BATCH_SIZE_DEFAULT;
-
- /**
- * Holds the name of the queue to which pings are sent.
- */
- private static final String PING_DESTINATION_NAME_DEFAULT = "ping";
-
- /**
- * Holds the message delivery mode to use for the test.
- */
- protected static final boolean PERSISTENT_MODE_DEFAULT = false;
-
- /**
- * Holds the transactional mode to use for the test.
- */
- protected static final boolean TRANSACTED_DEFAULT = false;
-
- /**
- * Holds the default broker url for the test.
- */
- protected static final String BROKER_DEFAULT = "tcp://localhost:5672";
-
- /**
- * Holds the default virtual path for the test.
- */
- protected static final String VIRTUAL_PATH_DEFAULT = "/test";
-
- /**
- * Sets a default ping timeout.
- */
- protected static final long TIMEOUT_DEFAULT = 3000;
-
- /** Holds the default rate. A value of zero means infinity, only values of 1 or greater are meaningfull. */
- private static final int RATE_DEFAULT = 0;
-
- protected static final String FAIL_AFTER_COMMIT = "FailAfterCommit";
- protected static final String FAIL_BEFORE_COMMIT = "FailBeforeCommit";
- protected static final String FAIL_AFTER_SEND = "FailAfterSend";
- protected static final String FAIL_BEFORE_SEND = "FailBeforeSend";
- protected static final String COMMIT_BATCH_SIZE = "CommitBatchSize";
- protected static final String BATCH_SIZE = "BatchSize";
- protected static final String FAIL_ONCE = "FailOnce";
-
- /**
- * Thread local to hold the per-thread test setup fields.
- */
+ /** Thread local to hold the per-thread test setup fields. */
ThreadLocal<PerThreadSetup> threadSetup = new ThreadLocal<PerThreadSetup>();
- Object _lock = new Object();
-
- // Set up a property reader to extract the test parameters from. Once ContextualProperties is available in
- // the project dependencies, use it to get property overrides for configurable tests and to notify the test runner
- // of the test parameters to log with the results.
- protected Properties testParameters = System.getProperties();
- //private Properties testParameters = new ContextualProperties(System.getProperties());
+ /** Holds a property reader to extract the test parameters from. */
+ protected ParsedProperties testParameters = new ParsedProperties(System.getProperties());
public PingTestPerf(String name)
{
super(name);
- // Sets up the test parameters with defaults.
- setSystemPropertyIfNull(FAIL_AFTER_COMMIT, "false");
- setSystemPropertyIfNull(FAIL_BEFORE_COMMIT, "false");
- setSystemPropertyIfNull(FAIL_AFTER_SEND, "false");
- setSystemPropertyIfNull(FAIL_BEFORE_SEND, "false");
- setSystemPropertyIfNull(FAIL_ONCE, "true");
-
- setSystemPropertyIfNull(BATCH_SIZE, Integer.toString(BATCH_SIZE_DEFAULT));
- setSystemPropertyIfNull(COMMIT_BATCH_SIZE, Integer.toString(COMMIT_BATCH_SIZE_DEFAULT));
- setSystemPropertyIfNull(MESSAGE_SIZE_PROPNAME, Integer.toString(MESSAGE_SIZE_DEFAULT));
- setSystemPropertyIfNull(PING_DESTINATION_NAME_PROPNAME, PING_DESTINATION_NAME_DEFAULT);
- setSystemPropertyIfNull(PERSISTENT_MODE_PROPNAME, Boolean.toString(PERSISTENT_MODE_DEFAULT));
- setSystemPropertyIfNull(TRANSACTED_PROPNAME, Boolean.toString(TRANSACTED_DEFAULT));
- setSystemPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
- setSystemPropertyIfNull(VIRTUAL_PATH_PROPNAME, VIRTUAL_PATH_DEFAULT);
- setSystemPropertyIfNull(TIMEOUT_PROPNAME, Long.toString(TIMEOUT_DEFAULT));
- setSystemPropertyIfNull(PING_DESTINATION_COUNT_PROPNAME, Integer.toString(0));
- setSystemPropertyIfNull(VERBOSE_OUTPUT_PROPNAME, Boolean.toString(false));
- setSystemPropertyIfNull(RATE_PROPNAME, Integer.toString(RATE_DEFAULT));
- setSystemPropertyIfNull(IS_PUBSUB_PROPNAME, Boolean.toString(false));
+ // Sets up the test parameters with defaults.
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.COMMIT_BATCH_SIZE_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_TX_BATCH_SIZE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.MESSAGE_SIZE_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_MESSAGE_SIZE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.PING_QUEUE_NAME_PROPNAME,
+ PingPongProducer.DEFAULT_PING_DESTINATION_NAME);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.PERSISTENT_MODE_PROPNAME,
+ Boolean.toString(PingPongProducer.DEFAULT_PERSISTENT_MODE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.TRANSACTED_PROPNAME,
+ Boolean.toString(PingPongProducer.DEFAULT_TRANSACTED));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.BROKER_PROPNAME, PingPongProducer.DEFAULT_BROKER);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.USERNAME_PROPNAME, PingPongProducer.DEFAULT_USERNAME);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.PASSWORD_PROPNAME, PingPongProducer.DEFAULT_PASSWORD);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.VIRTUAL_PATH_PROPNAME, PingPongProducer.DEFAULT_VIRTUAL_PATH);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.VERBOSE_OUTPUT_PROPNAME,
+ Boolean.toString(PingPongProducer.DEFAULT_VERBOSE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.RATE_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_RATE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.IS_PUBSUB_PROPNAME,
+ Boolean.toString(PingPongProducer.DEFAULT_PUBSUB));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.COMMIT_BATCH_SIZE_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_TX_BATCH_SIZE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.TIMEOUT_PROPNAME,
+ Long.toString(PingPongProducer.DEFAULT_TIMEOUT));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.PING_DESTINATION_COUNT_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_DESTINATION_COUNT));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_AFTER_COMMIT_PROPNAME,
+ PingPongProducer.DEFAULT_FAIL_AFTER_COMMIT);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_BEFORE_COMMIT_PROPNAME,
+ PingPongProducer.DEFAULT_FAIL_BEFORE_COMMIT);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_AFTER_SEND_PROPNAME,
+ PingPongProducer.DEFAULT_FAIL_AFTER_SEND);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_BEFORE_SEND_PROPNAME,
+ PingPongProducer.DEFAULT_FAIL_BEFORE_SEND);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_ONCE_PROPNAME, PingPongProducer.DEFAULT_FAIL_ONCE);
}
/**
@@ -187,20 +121,6 @@ public class PingTestPerf extends AsymptoticTestCase //implements TimingControll
suite.addTest(new PingTestPerf("testPingOk"));
return suite;
- //return new junit.framework.TestSuite(PingTestPerf.class);
- }
-
- protected static void setSystemPropertyIfNull(String propName, String propValue)
- {
- if (System.getProperty(propName) == null)
- {
- System.setProperty(propName, propValue);
- }
- }
-
- public void testPing(int jim) throws Exception
- {
- testPingOk(1);
}
public void testPingOk(int numPings) throws Exception
@@ -214,15 +134,15 @@ public class PingTestPerf extends AsymptoticTestCase //implements TimingControll
// Generate a sample message. This message is already time stamped and has its reply-to destination set.
ObjectMessage msg =
- perThreadSetup._pingItselfClient.getTestMessage(null,
- Integer.parseInt(testParameters.getProperty(
- MESSAGE_SIZE_PROPNAME)),
- Boolean.parseBoolean(testParameters.getProperty(
- PERSISTENT_MODE_PROPNAME)));
+ perThreadSetup._pingClient.getTestMessage(perThreadSetup._pingClient.getReplyDestinations().get(0),
+ testParameters.getPropertyAsInteger(
+ PingPongProducer.MESSAGE_SIZE_PROPNAME),
+ testParameters.getPropertyAsBoolean(
+ PingPongProducer.PERSISTENT_MODE_PROPNAME));
// start the test
- long timeout = Long.parseLong(testParameters.getProperty(TIMEOUT_PROPNAME));
- int numReplies = perThreadSetup._pingItselfClient.pingAndWaitForReply(msg, numPings, timeout);
+ long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME));
+ int numReplies = perThreadSetup._pingClient.pingAndWaitForReply(msg, numPings, timeout);
// Fail the test if the timeout was exceeded.
if (numReplies != numPings)
@@ -232,75 +152,87 @@ public class PingTestPerf extends AsymptoticTestCase //implements TimingControll
}
}
-
- protected void setUp() throws Exception
+ /**
+ * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
+ */
+ public void threadSetUp()
{
- // Log4j will propagate the test name as a thread local in all log output.
- // Carefull when using this, it can cause memory leaks when not cleaned up properly.
- //NDC.push(getName());
+ _logger.debug("public void threadSetUp(): called");
- // Create the test setups on a per thread basis, only if they have not already been created.
-
- if (threadSetup.get() == null)
+ try
{
PerThreadSetup perThreadSetup = new PerThreadSetup();
// Extract the test set up paramaeters.
- String brokerDetails = testParameters.getProperty(BROKER_PROPNAME);
- String username = "guest";
- String password = "guest";
- String virtualpath = testParameters.getProperty(VIRTUAL_PATH_PROPNAME);
- int destinationscount = Integer.parseInt(testParameters.getProperty(PING_DESTINATION_COUNT_PROPNAME));
- String destinationname = testParameters.getProperty(PING_DESTINATION_NAME_PROPNAME);
- boolean persistent = Boolean.parseBoolean(testParameters.getProperty(PERSISTENT_MODE_PROPNAME));
- boolean transacted = Boolean.parseBoolean(testParameters.getProperty(TRANSACTED_PROPNAME));
- String selector = null;
- boolean verbose = Boolean.parseBoolean(testParameters.getProperty(VERBOSE_OUTPUT_PROPNAME));
- int messageSize = Integer.parseInt(testParameters.getProperty(MESSAGE_SIZE_PROPNAME));
- int rate = Integer.parseInt(testParameters.getProperty(RATE_PROPNAME));
- boolean pubsub = Boolean.parseBoolean(testParameters.getProperty(IS_PUBSUB_PROPNAME));
-
- boolean afterCommit = Boolean.parseBoolean(testParameters.getProperty(FAIL_AFTER_COMMIT));
- boolean beforeCommit = Boolean.parseBoolean(testParameters.getProperty(FAIL_BEFORE_COMMIT));
- boolean afterSend = Boolean.parseBoolean(testParameters.getProperty(FAIL_AFTER_SEND));
- boolean beforeSend = Boolean.parseBoolean(testParameters.getProperty(FAIL_BEFORE_SEND));
- boolean failOnce = Boolean.parseBoolean(testParameters.getProperty(FAIL_ONCE));
+ String brokerDetails = testParameters.getProperty(PingPongProducer.BROKER_PROPNAME);
+ String username = testParameters.getProperty(PingPongProducer.USERNAME_PROPNAME);
+ String password = testParameters.getProperty(PingPongProducer.PASSWORD_PROPNAME);
+ String virtualPath = testParameters.getProperty(PingPongProducer.VIRTUAL_PATH_PROPNAME);
+ String destinationName = testParameters.getProperty(PingPongProducer.PING_QUEUE_NAME_PROPNAME);
+ boolean persistent = testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME);
+ boolean transacted = testParameters.getPropertyAsBoolean(PingPongProducer.TRANSACTED_PROPNAME);
+ String selector = testParameters.getProperty(PingPongProducer.SELECTOR_PROPNAME);
+ boolean verbose = testParameters.getPropertyAsBoolean(PingPongProducer.VERBOSE_OUTPUT_PROPNAME);
+ int messageSize = testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME);
+ int rate = testParameters.getPropertyAsInteger(PingPongProducer.RATE_PROPNAME);
+ boolean pubsub = testParameters.getPropertyAsBoolean(PingPongProducer.IS_PUBSUB_PROPNAME);
+ boolean failAfterCommit = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_AFTER_COMMIT_PROPNAME);
+ boolean failBeforeCommit = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_BEFORE_COMMIT_PROPNAME);
+ boolean failAfterSend = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_AFTER_SEND_PROPNAME);
+ boolean failBeforeSend = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_BEFORE_SEND_PROPNAME);
+ int batchSize = testParameters.getPropertyAsInteger(PingPongProducer.COMMIT_BATCH_SIZE_PROPNAME);
+ Boolean failOnce = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_ONCE_PROPNAME);
- int batchSize = Integer.parseInt(testParameters.getProperty(BATCH_SIZE));
+ // Extract the test set up paramaeters.
+ int destinationscount =
+ Integer.parseInt(testParameters.getProperty(PingPongProducer.PING_DESTINATION_COUNT_PROPNAME));
// This is synchronized because there is a race condition, which causes one connection to sleep if
- // all threads try to create connection concurrently
- synchronized (_lock)
+ // all threads try to create connection concurrently.
+ synchronized (this)
{
// Establish a client to ping a Destination and listen the reply back from same Destination
- perThreadSetup._pingItselfClient = new TestPingItself(brokerDetails, username, password, virtualpath,
- destinationname, selector, transacted, persistent,
- messageSize, verbose, afterCommit, beforeCommit,
- afterSend, beforeSend, failOnce, batchSize, destinationscount,
- rate, pubsub);
+ perThreadSetup._pingClient = new PingClient(brokerDetails, username, password, virtualPath, destinationName,
+ selector, transacted, persistent, messageSize, verbose,
+ failAfterCommit, failBeforeCommit, failAfterSend, failBeforeSend,
+ failOnce, batchSize, destinationscount, rate, pubsub);
}
// Start the client connection
- perThreadSetup._pingItselfClient.getConnection().start();
+ perThreadSetup._pingClient.getConnection().start();
// Attach the per-thread set to the thread.
threadSetup.set(perThreadSetup);
}
+ catch (Exception e)
+ {
+ _logger.warn("There was an exception during per thread setup.", e);
+ }
}
- protected void tearDown() throws Exception
+ /**
+ * Performs test fixture clean
+ */
+ public void threadTearDown()
{
+ _logger.debug("public void threadTearDown(): called");
+
try
{
- /*
- if ((_pingItselfClient != null) && (_pingItselfClient.getConnection() != null))
+ // Get the per thread test fixture.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+
+ // Close the pingers so that it cleans up its connection cleanly.
+ synchronized (this)
{
- _pingItselfClient.getConnection().close();
+ perThreadSetup._pingClient.close();
}
- */
+
+ // Ensure the per thread fixture is reclaimed.
+ threadSetup.remove();
}
- finally
+ catch (JMSException e)
{
- //NDC.pop();
+ _logger.warn("There was an exception during per thread tear down.");
}
}
@@ -309,6 +241,6 @@ public class PingTestPerf extends AsymptoticTestCase //implements TimingControll
/**
* Holds the test ping client.
*/
- protected TestPingItself _pingItselfClient;
+ protected PingClient _pingClient;
}
}
diff --git a/qpid/java/perftests/src/test/java/org/apache/qpid/ping/ThrottleTestPerf.java b/qpid/java/perftests/src/test/java/org/apache/qpid/ping/ThrottleTestPerf.java
deleted file mode 100644
index 7183d4746a..0000000000
--- a/qpid/java/perftests/src/test/java/org/apache/qpid/ping/ThrottleTestPerf.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.apache.qpid.ping;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import uk.co.thebadgerset.junit.extensions.AsymptoticTestCase;
-
-/**
- * Tests the {@link Throttle} implementation. Test timings can be taken using this test class to confirm that the
- * throttle works as it should, and what the maximum rate is that it works reliably.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Enable test timings to be taken to confirm that the throttle works at the correct rate.
- * </table>
- *
- * @author Rupert Smith
- */
-public class ThrottleTestPerf extends AsymptoticTestCase
-{
- ThreadLocal<Throttle> threadSetup = new ThreadLocal<Throttle>();
-
- public ThrottleTestPerf(String name)
- {
- super(name);
- }
-
- /**
- * Compile all the tests into a test suite.
- */
- public static Test suite()
- {
- // Build a new test suite
- TestSuite suite = new TestSuite("Ping-Pong Performance Tests");
-
- // Run performance tests in read committed mode.
- suite.addTest(new ThrottleTestPerf("testThrottle"));
-
- return suite;
- }
-
- public void testThrottle(int opsPerSecond)
- {
- Throttle throttle = threadSetup.get();
-
- // Setting this on every test call won't cause any harm, convenient to use the size parameter for this.
- throttle.setRate(opsPerSecond);
-
- // Run the test at the throttled rate, do this for the num of opsPerSecond, then every test should take 1 second.
- for (int i = 0; i < opsPerSecond; i++)
- {
- throttle.throttle();
- }
- }
-
- protected void setUp()
- {
- if (threadSetup.get() == null)
- {
- threadSetup.set(new Throttle());
- }
- }
-}
diff --git a/qpid/java/perftests/src/test/java/org/apache/qpid/requestreply/PingPongTestPerf.java b/qpid/java/perftests/src/test/java/org/apache/qpid/requestreply/PingPongTestPerf.java
index 62af73e53d..63969d0293 100644
--- a/qpid/java/perftests/src/test/java/org/apache/qpid/requestreply/PingPongTestPerf.java
+++ b/qpid/java/perftests/src/test/java/org/apache/qpid/requestreply/PingPongTestPerf.java
@@ -1,7 +1,25 @@
+/*
+ *
+ * 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.qpid.requestreply;
-import java.util.Properties;
-
import javax.jms.*;
import junit.framework.Assert;
@@ -11,149 +29,87 @@ import junit.framework.TestSuite;
import org.apache.log4j.Logger;
import uk.co.thebadgerset.junit.extensions.AsymptoticTestCase;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
/**
* PingPongTestPerf is a full round trip ping test, that has been written with the intention of being scaled up to run
* many times simultaneously to simluate many clients/producer/connections. A full round trip ping sends a message from
* a producer to a conumer, then the consumer replies to the message on a temporary queue.
- * <p/>
+ *
* <p/>A single run of the test using the default JUnit test runner will result in the sending and timing of the number
* of pings specified by the test size and time how long it takes for all of these to complete. This test may be scaled
- * up using a suitable JUnit test runner. See {@link TKTestRunner} or {@link PPTestRunner} for more information on how
- * to do this.
- * <p/>
+ * up using a suitable JUnit test runner. See {@link uk.co.thebadgerset.junit.extensions.TKTestRunner} for more
+ * information on how to do this.
+ *
* <p/>The setup/teardown cycle establishes a connection to a broker and sets up a queue to send ping messages to and a
* temporary queue for replies. This setup is only established once for all the test repeats, but each test threads
* gets its own connection/producer/consumer, this is only re-established if the connection is lost.
- * <p/>
+ *
* <p/>The test cycle is: Connects to a queue, creates a temporary queue, creates messages containing a property that
* is the name of the temporary queue, fires off many messages on the original queue and waits for them all to come
* back on the temporary queue.
- * <p/>
+ *
* <p/>Configurable test properties: message size, transacted or not, persistent or not. Broker connection details.
- * <p/>
+ *
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* </table>
*
* @author Rupert Smith
*/
-public class PingPongTestPerf extends AsymptoticTestCase //implements TimingControllerAware
+public class PingPongTestPerf extends AsymptoticTestCase
{
private static Logger _logger = Logger.getLogger(PingPongTestPerf.class);
- /**
- * Holds the name of the property to get the test message size from.
- */
- private static final String MESSAGE_SIZE_PROPNAME = "messagesize";
-
- /**
- * Holds the name of the property to get the ping queue name from.
- */
- private static final String PING_QUEUE_NAME_PROPNAME = "destinationname";
-
- /**
- * Holds the name of the property to get the test delivery mode from.
- */
- private static final String PERSISTENT_MODE_PROPNAME = "persistent";
-
- /**
- * Holds the name of the property to get the test transactional mode from.
- */
- private static final String TRANSACTED_PROPNAME = "transacted";
-
- /**
- * Holds the name of the property to get the test broker url from.
- */
- private static final String BROKER_PROPNAME = "broker";
-
- /**
- * Holds the name of the property to get the test broker virtual path.
- */
- private static final String VIRTUAL_PATH_PROPNAME = "virtualPath";
-
- /**
- * Holds the size of message body to attach to the ping messages.
- */
- private static final int MESSAGE_SIZE_DEFAULT = 0;
-
- private static final int BATCH_SIZE_DEFAULT = 2;
-
- /**
- * Holds the name of the queue to which pings are sent.
- */
- private static final String PING_QUEUE_NAME_DEFAULT = "ping";
-
- /**
- * Holds the message delivery mode to use for the test.
- */
- private static final boolean PERSISTENT_MODE_DEFAULT = false;
-
- /**
- * Holds the transactional mode to use for the test.
- */
- private static final boolean TRANSACTED_DEFAULT = false;
-
- /**
- * Holds the default broker url for the test.
- */
- private static final String BROKER_DEFAULT = "tcp://localhost:5672";
-
- /**
- * Holds the default virtual path for the test.
- */
- private static final String VIRTUAL_PATH_DEFAULT = "/test";
-
- /**
- * Sets a default ping timeout.
- */
- private static final long TIMEOUT = 15000;
-
- /** Holds the name of the property to get the message rate from. */
- private static final String RATE_PROPNAME = "rate";
-
- private static final String VERBOSE_OUTPUT_PROPNAME = "verbose";
-
- /** Holds the true or false depending on wether it is P2P test or PubSub */
- private static final String IS_PUBSUB_PROPNAME = "pubsub";
-
- /** Holds the default rate. A value of zero means infinity, only values of 1 or greater are meaningfull. */
- private static final int RATE_DEFAULT = 0;
-
- private static final String FAIL_AFTER_COMMIT = "FailAfterCommit";
- private static final String FAIL_BEFORE_COMMIT = "FailBeforeCommit";
- private static final String FAIL_AFTER_SEND = "FailAfterSend";
- private static final String FAIL_BEFORE_SEND = "FailBeforeSend";
- private static final String BATCH_SIZE = "BatchSize";
- private static final String FAIL_ONCE = "FailOnce";
-
- /**
- * Thread local to hold the per-thread test setup fields.
- */
+ /** Thread local to hold the per-thread test setup fields. */
ThreadLocal<PerThreadSetup> threadSetup = new ThreadLocal<PerThreadSetup>();
- Object _lock = new Object();
// Set up a property reader to extract the test parameters from. Once ContextualProperties is available in
// the project dependencies, use it to get property overrides for configurable tests and to notify the test runner
// of the test parameters to log with the results. It also providers some basic type parsing convenience methods.
- private Properties testParameters = System.getProperties();
- //private Properties testParameters = new ContextualProperties(System.getProperties());
+ //private Properties testParameters = System.getProperties();
+ private ParsedProperties testParameters = new ParsedProperties(System.getProperties());
public PingPongTestPerf(String name)
{
super(name);
// Sets up the test parameters with defaults.
- setSystemPropertyIfNull(BATCH_SIZE, Integer.toString(BATCH_SIZE_DEFAULT));
- setSystemPropertyIfNull(MESSAGE_SIZE_PROPNAME, Integer.toString(MESSAGE_SIZE_DEFAULT));
- setSystemPropertyIfNull(PING_QUEUE_NAME_PROPNAME, PING_QUEUE_NAME_DEFAULT);
- setSystemPropertyIfNull(PERSISTENT_MODE_PROPNAME, Boolean.toString(PERSISTENT_MODE_DEFAULT));
- setSystemPropertyIfNull(TRANSACTED_PROPNAME, Boolean.toString(TRANSACTED_DEFAULT));
- setSystemPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
- setSystemPropertyIfNull(VIRTUAL_PATH_PROPNAME, VIRTUAL_PATH_DEFAULT);
- setSystemPropertyIfNull(VERBOSE_OUTPUT_PROPNAME, Boolean.toString(false));
- setSystemPropertyIfNull(RATE_PROPNAME, Integer.toString(RATE_DEFAULT));
- setSystemPropertyIfNull(IS_PUBSUB_PROPNAME, Boolean.toString(false));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.COMMIT_BATCH_SIZE_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_TX_BATCH_SIZE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.MESSAGE_SIZE_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_MESSAGE_SIZE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.PING_QUEUE_NAME_PROPNAME,
+ PingPongProducer.DEFAULT_PING_DESTINATION_NAME);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.PERSISTENT_MODE_PROPNAME,
+ Boolean.toString(PingPongProducer.DEFAULT_PERSISTENT_MODE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.TRANSACTED_PROPNAME,
+ Boolean.toString(PingPongProducer.DEFAULT_TRANSACTED));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.BROKER_PROPNAME, PingPongProducer.DEFAULT_BROKER);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.USERNAME_PROPNAME, PingPongProducer.DEFAULT_USERNAME);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.PASSWORD_PROPNAME, PingPongProducer.DEFAULT_PASSWORD);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.VIRTUAL_PATH_PROPNAME, PingPongProducer.DEFAULT_VIRTUAL_PATH);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.VERBOSE_OUTPUT_PROPNAME,
+ Boolean.toString(PingPongProducer.DEFAULT_VERBOSE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.RATE_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_RATE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.IS_PUBSUB_PROPNAME,
+ Boolean.toString(PingPongProducer.DEFAULT_PUBSUB));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.COMMIT_BATCH_SIZE_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_TX_BATCH_SIZE));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.TIMEOUT_PROPNAME,
+ Long.toString(PingPongProducer.DEFAULT_TIMEOUT));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.PING_DESTINATION_COUNT_PROPNAME,
+ Integer.toString(PingPongProducer.DEFAULT_DESTINATION_COUNT));
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_AFTER_COMMIT_PROPNAME,
+ PingPongProducer.DEFAULT_FAIL_AFTER_COMMIT);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_BEFORE_COMMIT_PROPNAME,
+ PingPongProducer.DEFAULT_FAIL_BEFORE_COMMIT);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_AFTER_SEND_PROPNAME,
+ PingPongProducer.DEFAULT_FAIL_AFTER_SEND);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_BEFORE_SEND_PROPNAME,
+ PingPongProducer.DEFAULT_FAIL_BEFORE_SEND);
+ ParsedProperties.setSysPropertyIfNull(PingPongProducer.FAIL_ONCE_PROPNAME, PingPongProducer.DEFAULT_FAIL_ONCE);
}
/**
@@ -185,19 +141,15 @@ public class PingPongTestPerf extends AsymptoticTestCase //implements TimingCont
// Generate a sample message. This message is already time stamped and has its reply-to destination set.
ObjectMessage msg =
- perThreadSetup._testPingProducer.getTestMessage(perThreadSetup._testPingProducer.getReplyDestination(),
- Integer.parseInt(testParameters.getProperty(
- MESSAGE_SIZE_PROPNAME)),
- Boolean.parseBoolean(testParameters.getProperty(
- PERSISTENT_MODE_PROPNAME)));
-
- // Use the test timing controller to reset the test timer now and obtain the current time.
- // This can be used to remove the message creation time from the test.
- //TestTimingController timingUtils = getTimingController();
- //long startTime = timingUtils.restart();
+ perThreadSetup._testPingProducer.getTestMessage(perThreadSetup._testPingProducer.getReplyDestinations().get(0),
+ testParameters.getPropertyAsInteger(
+ PingPongProducer.MESSAGE_SIZE_PROPNAME),
+ testParameters.getPropertyAsBoolean(
+ PingPongProducer.PERSISTENT_MODE_PROPNAME));
// Send the message and wait for a reply.
- int numReplies = perThreadSetup._testPingProducer.pingAndWaitForReply(msg, numPings, TIMEOUT);
+ int numReplies =
+ perThreadSetup._testPingProducer.pingAndWaitForReply(msg, numPings, PingPongProducer.DEFAULT_TIMEOUT);
// Fail the test if the timeout was exceeded.
if (numReplies != numPings)
@@ -206,82 +158,93 @@ public class PingPongTestPerf extends AsymptoticTestCase //implements TimingCont
}
}
- protected void setUp() throws Exception
+ /**
+ * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
+ */
+ public void threadSetUp()
{
- // Log4j will propagate the test name as a thread local in all log output.
- // Carefull when using this, it can cause memory leaks when not cleaned up properly.
- //NDC.push(getName());
-
- // Create the test setups on a per thread basis, only if they have not already been created.
- if (threadSetup.get() == null)
+ try
{
PerThreadSetup perThreadSetup = new PerThreadSetup();
// Extract the test set up paramaeters.
- String brokerDetails = testParameters.getProperty(BROKER_PROPNAME);
- String username = "guest";
- String password = "guest";
- String virtualpath = testParameters.getProperty(VIRTUAL_PATH_PROPNAME);
- String queueName = testParameters.getProperty(PING_QUEUE_NAME_PROPNAME);
- boolean persistent = Boolean.parseBoolean(testParameters.getProperty(PERSISTENT_MODE_PROPNAME));
- boolean transacted = Boolean.parseBoolean(testParameters.getProperty(TRANSACTED_PROPNAME));
- String selector = null;
- boolean verbose = Boolean.parseBoolean(testParameters.getProperty(VERBOSE_OUTPUT_PROPNAME));
- int messageSize = Integer.parseInt(testParameters.getProperty(MESSAGE_SIZE_PROPNAME));
- int rate = Integer.parseInt(testParameters.getProperty(RATE_PROPNAME));
- boolean pubsub = Boolean.parseBoolean(testParameters.getProperty(IS_PUBSUB_PROPNAME));
-
- boolean afterCommit = Boolean.parseBoolean(testParameters.getProperty(FAIL_AFTER_COMMIT));
- boolean beforeCommit = Boolean.parseBoolean(testParameters.getProperty(FAIL_BEFORE_COMMIT));
- boolean afterSend = Boolean.parseBoolean(testParameters.getProperty(FAIL_AFTER_SEND));
- boolean beforeSend = Boolean.parseBoolean(testParameters.getProperty(FAIL_BEFORE_SEND));
- int batchSize = Integer.parseInt(testParameters.getProperty(BATCH_SIZE));
- Boolean failOnce = Boolean.parseBoolean(testParameters.getProperty(FAIL_ONCE));
-
- synchronized(_lock)
+ String brokerDetails = testParameters.getProperty(PingPongProducer.BROKER_PROPNAME);
+ String username = testParameters.getProperty(PingPongProducer.USERNAME_PROPNAME);
+ String password = testParameters.getProperty(PingPongProducer.PASSWORD_PROPNAME);
+ String virtualPath = testParameters.getProperty(PingPongProducer.VIRTUAL_PATH_PROPNAME);
+ String destinationName = testParameters.getProperty(PingPongProducer.PING_QUEUE_NAME_PROPNAME);
+ boolean persistent = testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME);
+ boolean transacted = testParameters.getPropertyAsBoolean(PingPongProducer.TRANSACTED_PROPNAME);
+ String selector = testParameters.getProperty(PingPongProducer.SELECTOR_PROPNAME);
+ boolean verbose = testParameters.getPropertyAsBoolean(PingPongProducer.VERBOSE_OUTPUT_PROPNAME);
+ int messageSize = testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME);
+ int rate = testParameters.getPropertyAsInteger(PingPongProducer.RATE_PROPNAME);
+ boolean pubsub = testParameters.getPropertyAsBoolean(PingPongProducer.IS_PUBSUB_PROPNAME);
+ boolean failAfterCommit = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_AFTER_COMMIT_PROPNAME);
+ boolean failBeforeCommit = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_BEFORE_COMMIT_PROPNAME);
+ boolean failAfterSend = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_AFTER_SEND_PROPNAME);
+ boolean failBeforeSend = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_BEFORE_SEND_PROPNAME);
+ int batchSize = testParameters.getPropertyAsInteger(PingPongProducer.COMMIT_BATCH_SIZE_PROPNAME);
+ Boolean failOnce = testParameters.getPropertyAsBoolean(PingPongProducer.FAIL_ONCE_PROPNAME);
+
+ synchronized (this)
{
// Establish a bounce back client on the ping queue to bounce back the pings.
- perThreadSetup._testPingBouncer = new PingPongBouncer(brokerDetails, username, password, virtualpath,
- queueName, persistent, transacted, selector, verbose, pubsub);
+ perThreadSetup._testPingBouncer = new PingPongBouncer(brokerDetails, username, password, virtualPath,
+ destinationName, persistent, transacted, selector,
+ verbose, pubsub);
// Start the connections for client and producer running.
perThreadSetup._testPingBouncer.getConnection().start();
// Establish a ping-pong client on the ping queue to send the pings with.
- perThreadSetup._testPingProducer = new PingPongProducer(brokerDetails, username, password, virtualpath,
- queueName, selector, transacted, persistent, messageSize,
- verbose, afterCommit, beforeCommit, afterSend,
- beforeSend, failOnce, batchSize, 0, rate, pubsub);
+ perThreadSetup._testPingProducer = new PingPongProducer(brokerDetails, username, password, virtualPath,
+ destinationName, selector, transacted, persistent,
+ messageSize, verbose, failAfterCommit,
+ failBeforeCommit, failAfterSend, failBeforeSend,
+ failOnce, batchSize, 0, rate, pubsub);
perThreadSetup._testPingProducer.getConnection().start();
}
// Attach the per-thread set to the thread.
threadSetup.set(perThreadSetup);
}
+ catch (Exception e)
+ {
+ _logger.warn("There was an exception during per thread setup.", e);
+ }
}
- protected void tearDown() throws Exception
+ /**
+ * Performs test fixture clean
+ */
+ public void threadTearDown()
{
+ _logger.debug("public void threadTearDown(): called");
+
try
{
- /**if ((_testPingBouncer != null) && (_testPingBouncer.getConnection() != null))
- {
- _testPingBouncer.getConnection().close();
- }
-
- if ((_testPingProducer != null) && (_testPingProducer.getConnection() != null))
- {
- _testPingProducer.getConnection().close();
- }*/
+ // Get the per thread test fixture.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+
+ // Close the pingers so that it cleans up its connection cleanly.
+ synchronized (this)
+ {
+ perThreadSetup._testPingProducer.close();
+ //perThreadSetup._testPingBouncer.close();
+ }
+
+ // Ensure the per thread fixture is reclaimed.
+ threadSetup.remove();
}
- finally
+ catch (JMSException e)
{
- //NDC.pop();
+ _logger.warn("There was an exception during per thread tear down.");
}
}
- private static class PerThreadSetup
+ protected static class PerThreadSetup
{
/**
* Holds the test ping-pong producer.
diff --git a/qpid/java/pom.xml b/qpid/java/pom.xml
index 099f55897d..f5c4a2d309 100644
--- a/qpid/java/pom.xml
+++ b/qpid/java/pom.xml
@@ -458,7 +458,7 @@
<groupId>uk.co.thebadgerset</groupId>
<artifactId>junit-toolkit</artifactId>
<version>0.5-SNAPSHOT</version>
- <scope>test</scope>
+ <scope>compile</scope>
</dependency>
<!-- Qpid Version Dependencies -->