summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles E. Rolke <chug@apache.org>2012-02-27 17:40:42 +0000
committerCharles E. Rolke <chug@apache.org>2012-02-27 17:40:42 +0000
commitc3a0c2ec78970005da38d524f38939cc7f2fb3a7 (patch)
treee0efc6e350bc0867c5f114ca10fc7b48a3cfa033
parent879da6a01706268adbb75c42182027bde4a1d430 (diff)
downloadqpid-python-c3a0c2ec78970005da38d524f38939cc7f2fb3a7.tar.gz
Merge from trunk into branch
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-3799-acl@1294242 13f79535-47bb-0310-9956-ffa450edef68
-rwxr-xr-xcpp/bindings/qmf/tests/run_interop_tests3
-rw-r--r--cpp/bindings/qpid/Makefile.am2
-rw-r--r--cpp/bindings/qpid/dotnet/Makefile.am2
-rw-r--r--cpp/configure.ac31
-rw-r--r--cpp/include/qpid/framing/SequenceNumber.h6
-rw-r--r--cpp/include/qpid/framing/SequenceSet.h6
-rw-r--r--cpp/include/qpid/types/Variant.h4
-rwxr-xr-xcpp/managementgen/qmfgen/schema.py2
-rw-r--r--cpp/managementgen/qmfgen/templates/Class.h51
-rw-r--r--cpp/managementgen/qmfgen/templates/Event.h13
-rw-r--r--cpp/managementgen/qmfgen/templates/Package.h5
-rw-r--r--cpp/src/CMakeLists.txt42
-rw-r--r--cpp/src/Makefile.am20
-rw-r--r--cpp/src/config.h.cmake1
-rw-r--r--cpp/src/qmf.mk1
-rw-r--r--cpp/src/qmf/BrokerImportExport.h42
-rw-r--r--cpp/src/qpid/broker/Broker.h86
-rw-r--r--cpp/src/qpid/broker/ExchangeRegistry.h6
-rw-r--r--cpp/src/qpid/broker/Link.h17
-rw-r--r--cpp/src/qpid/broker/LinkRegistry.cpp14
-rw-r--r--cpp/src/qpid/broker/LinkRegistry.h110
-rw-r--r--cpp/src/qpid/broker/Queue.h82
-rw-r--r--cpp/src/qpid/broker/SemanticState.h64
-rw-r--r--cpp/src/qpid/client/TCPConnector.cpp8
-rw-r--r--cpp/src/qpid/ha/Backup.cpp2
-rw-r--r--cpp/src/qpid/ha/BrokerReplicator.cpp9
-rw-r--r--cpp/src/qpid/ha/HaBroker.cpp34
-rw-r--r--cpp/src/qpid/ha/HaBroker.h2
-rw-r--r--cpp/src/qpid/ha/HaPlugin.cpp21
-rw-r--r--cpp/src/qpid/ha/QueueReplicator.cpp8
-rw-r--r--cpp/src/qpid/ha/ReplicatingSubscription.h2
-rw-r--r--cpp/src/qpid/ha/Settings.h3
-rw-r--r--cpp/src/qpid/ha/management-schema.xml26
-rw-r--r--cpp/src/qpid/sys/MemStat.h (renamed from cpp/include/qpid/sys/MemStat.h)0
-rw-r--r--cpp/src/qpid/sys/Probes.h65
-rw-r--r--cpp/src/qpid/sys/apr/APRBase.cpp89
-rw-r--r--cpp/src/qpid/sys/apr/APRBase.h74
-rw-r--r--cpp/src/qpid/sys/apr/Condition.h84
-rw-r--r--cpp/src/qpid/sys/apr/Mutex.h124
-rw-r--r--cpp/src/qpid/sys/apr/Shlib.cpp49
-rw-r--r--cpp/src/qpid/sys/apr/Socket.cpp114
-rw-r--r--cpp/src/qpid/sys/apr/Thread.h106
-rw-r--r--cpp/src/qpid/sys/posix/AsynchIO.cpp30
-rw-r--r--cpp/src/tests/CMakeLists.txt10
-rw-r--r--cpp/src/tests/Makefile.am3
-rwxr-xr-xcpp/src/tests/acl.py60
-rwxr-xr-xcpp/src/tests/cli_tests.py136
-rwxr-xr-xcpp/src/tests/cluster_tests.py4
-rwxr-xr-xcpp/src/tests/clustered_replication_test10
-rwxr-xr-xcpp/src/tests/federated_cluster_test12
-rwxr-xr-xcpp/src/tests/ha_tests.py149
-rwxr-xr-xcpp/src/tests/ipv6_test6
-rw-r--r--cpp/src/tests/python_tests.ps15
-rw-r--r--cpp/src/tests/queue_flow_limit_tests.py2
-rwxr-xr-xcpp/src/tests/reliable_replication_test6
-rwxr-xr-xcpp/src/tests/replication_test34
-rwxr-xr-xcpp/src/tests/ring_queue_test2
-rw-r--r--cpp/src/tests/run_acl_tests.ps15
-rw-r--r--cpp/src/tests/run_federation_tests.ps13
-rw-r--r--cpp/src/tests/run_header_test.ps13
-rwxr-xr-xcpp/src/tests/run_msg_group_tests8
-rwxr-xr-xcpp/src/tests/run_msg_group_tests_soak4
-rw-r--r--cpp/src/tests/run_store_tests.ps19
-rw-r--r--cpp/src/tests/run_test.ps15
-rwxr-xr-xcpp/src/tests/sasl_fed16
-rwxr-xr-xcpp/src/tests/sasl_fed_ex12
-rw-r--r--cpp/src/tests/test_env.sh.in1
-rw-r--r--cpp/src/tests/testlib.py4
-rw-r--r--doc/book/src/LVQ.xml11
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java140
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/Xid.java (renamed from cpp/src/qpid/sys/apr/APRPool.cpp)45
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/PreparedTransaction.java46
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/PreparedTransactionTB.java122
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/XidTB.java58
-rw-r--r--java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java1
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Broker.java66
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java21
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java42
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java46
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java173
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java18
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java363
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java10
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java144
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java387
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/AlreadyKnownDtxException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java246
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java348
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxException.java (renamed from cpp/src/qpid/sys/apr/APRPool.h)56
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxNotSelectedException.java (renamed from cpp/src/qpid/sys/apr/Time.cpp)24
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java333
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/IncorrectDtxStateException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/JoinAndResumeDtxException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/NotAssociatedDtxException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/RollbackOnlyDtxException.java (renamed from cpp/src/qpid/sys/apr/Thread.cpp)24
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/SuspendAndFailDtxException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/TimeoutDtxException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/UnknownDtxBranchException.java32
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java14
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java205
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java30
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java5
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java21
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java5
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java8
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java8
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java8
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java12
-rw-r--r--java/build.deps5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQQueueBrowser.java64
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession.java56
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java64
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java19
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java205
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java17
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java11
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java3
-rw-r--r--java/common/src/main/java/org/apache/qpid/properties/ConnectionStartProperties.java21
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Session.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java2
-rwxr-xr-xjava/genpom34
-rw-r--r--java/lib/org.apache.felix.main-2.0.5.jar (renamed from java/lib/org.apache.felix.framework-2.0.5.jar)bin391763 -> 391763 bytes
-rw-r--r--java/lib/poms/commons-digester-1.8.1.xml6
-rw-r--r--java/lib/poms/org.apache.felix.main-2.0.5.xml (renamed from java/lib/poms/org.apache.felix.framework-2.0.5.xml)20
-rw-r--r--java/lib/poms/org.osgi.core-1.0.0.xml22
-rw-r--r--java/lib/poms/xalan-2.7.0.xml8
-rw-r--r--java/module.xml2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java239
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java5
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java11
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java101
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/ImmediateAndMandatoryPublishingTest.java98
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java11
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java18
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java43
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java72
-rw-r--r--java/test-profiles/JavaExcludes3
-rw-r--r--java/test-profiles/JavaPre010Excludes4
-rw-r--r--java/test-profiles/JavaTransientExcludes7
-rw-r--r--java/test-profiles/java-bdb-spawn.0-8.testprofile2
-rw-r--r--java/test-profiles/java-bdb-spawn.0-9-1.testprofile2
-rw-r--r--java/test-profiles/java-bdb-spawn.0-9.testprofile2
-rw-r--r--java/test-profiles/java-bdb.0-8.testprofile2
-rw-r--r--java/test-profiles/java-bdb.0-9-1.testprofile2
-rw-r--r--java/test-profiles/java-bdb.0-9.testprofile2
-rw-r--r--java/test-profiles/java-dby-spawn.0-8.testprofile2
-rw-r--r--java/test-profiles/java-dby-spawn.0-9-1.testprofile2
-rw-r--r--java/test-profiles/java-dby-spawn.0-9.testprofile2
-rw-r--r--java/test-profiles/java-dby.0-8.testprofile2
-rw-r--r--java/test-profiles/java-dby.0-9-1.testprofile2
-rw-r--r--java/test-profiles/java-dby.0-9.testprofile2
-rw-r--r--java/test-profiles/java-mms-spawn.0-8.testprofile2
-rw-r--r--java/test-profiles/java-mms-spawn.0-9-1.testprofile2
-rw-r--r--java/test-profiles/java-mms-spawn.0-9.testprofile2
-rw-r--r--java/test-profiles/java-mms.0-8.testprofile2
-rw-r--r--java/test-profiles/java-mms.0-9-1.testprofile2
-rw-r--r--java/test-profiles/java-mms.0-9.testprofile2
-rw-r--r--java/test-profiles/python_tests/Java010PythonExcludes55
-rw-r--r--java/test-profiles/testprofile.defaults2
-rw-r--r--python/qpid/testlib.py12
-rw-r--r--python/qpid/tests/messaging/endpoints.py10
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/msg_groups.py8
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/new_api.py3
-rwxr-xr-xtools/setup.py21
-rwxr-xr-xtools/src/py/qpid-config184
-rwxr-xr-xtools/src/py/qpid-ha239
-rwxr-xr-xtools/src/py/qpid-ha-tool183
-rwxr-xr-xtools/src/py/qpid-stat187
-rw-r--r--tools/src/py/qpidtoollibs/broker.py95
-rw-r--r--tools/src/py/qpidtoollibs/disp.py41
193 files changed, 5331 insertions, 2386 deletions
diff --git a/cpp/bindings/qmf/tests/run_interop_tests b/cpp/bindings/qmf/tests/run_interop_tests
index 83e7f2593b..c370f211af 100755
--- a/cpp/bindings/qmf/tests/run_interop_tests
+++ b/cpp/bindings/qmf/tests/run_interop_tests
@@ -24,6 +24,7 @@ MY_DIR=`dirname \`which $0\``
QPID_DIR=${MY_DIR}/../../../..
BUILD_DIR=../../..
PYTHON_DIR=${QPID_DIR}/python
+TOOLS_PY_DIR=${QPID_DIR}/tools/src/py
QMF_DIR=${QPID_DIR}/extras/qmf
QMF_DIR_PY=${QMF_DIR}/src/py
BROKER_DIR=${BUILD_DIR}/src
@@ -68,7 +69,7 @@ TESTS_FAILED=0
if test -d ${PYTHON_DIR} ; then
start_broker
echo "Running qmf interop tests using broker on port $BROKER_PORT"
- PYTHONPATH=${PYTHON_DIR}:${QMF_DIR_PY}:${MY_DIR}
+ PYTHONPATH=${PYTHON_DIR}:${QMF_DIR_PY}:${MY_DIR}:${TOOLS_PY_DIR}
export PYTHONPATH
if test -d ${PYTHON_LIB_DIR} ; then
diff --git a/cpp/bindings/qpid/Makefile.am b/cpp/bindings/qpid/Makefile.am
index eaf45c2076..ae81696f27 100644
--- a/cpp/bindings/qpid/Makefile.am
+++ b/cpp/bindings/qpid/Makefile.am
@@ -35,7 +35,7 @@ if HAVE_PERL_DEVEL
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src -I$(PERL_INC)
-EXTRA_DIST += perl/perl.i
+EXTRA_DIST += perl/perl.i perl/CMakeLists.txt
BUILT_SOURCES = perl/cqpid_perl.cpp
SWIG_FLAGS = -w362,401
diff --git a/cpp/bindings/qpid/dotnet/Makefile.am b/cpp/bindings/qpid/dotnet/Makefile.am
index f212a37bbe..82ae315578 100644
--- a/cpp/bindings/qpid/dotnet/Makefile.am
+++ b/cpp/bindings/qpid/dotnet/Makefile.am
@@ -80,7 +80,6 @@ EXTRA_DIST = configure-windows.ps1 \
examples/msvc9/csharp.map.callback.sender/csharp.map.callback.sender.csproj \
examples/msvc9/csharp.map.receiver/csharp.map.receiver.csproj \
examples/msvc9/csharp.map.sender/csharp.map.sender.csproj \
- extra_dist.txt \
Makefile.am \
msvc10/org.apache.qpid.messaging.sessionreceiver.sln \
msvc10/org.apache.qpid.messaging.sln \
@@ -93,7 +92,6 @@ EXTRA_DIST = configure-windows.ps1 \
src/AssemblyInfo.cpp \
src/Connection.cpp \
src/Connection.h \
- src/Duration.cpp \
src/Duration.h \
src/FailoverUpdates.cpp \
src/FailoverUpdates.h \
diff --git a/cpp/configure.ac b/cpp/configure.ac
index 8729ace169..6ba5f62f0e 100644
--- a/cpp/configure.ac
+++ b/cpp/configure.ac
@@ -448,7 +448,7 @@ AC_ARG_WITH([poller],
[AS_HELP_STRING([--with-poller], [The low level poller implementation: poll/solaris-ecf/epoll])],
[case ${withval} in
poll)
- AC_CHECK_HEADERS([sys/poll.h],[poller=no],[AC_MSG_ERROR([Can't find poll.h header file for poll])])
+ AC_CHECK_HEADERS([sys/poll.h],[poller=poll],[AC_MSG_ERROR([Can't find poll.h header file for poll])])
;;
solaris-ecf)
AC_CHECK_HEADERS([port.h],[poller=solaris-ecf],[AC_MSG_ERROR([Can't find port.h header file for solaris-ecf])])
@@ -458,14 +458,17 @@ AC_ARG_WITH([poller],
;;
esac],
[
- AC_CHECK_HEADERS([sys/poll.h],[poller=no],)
- AC_CHECK_HEADERS([port.h],[poller=solaris-ecf],)
+ # We check for poll first so that it is overridden
+ AC_CHECK_HEADERS([sys/poll.h],[poller=poll],)
+ # Not currently supported - WIP
+ #AC_CHECK_HEADERS([port.h],[poller=solaris-ecf],)
AC_CHECK_HEADERS([sys/epoll.h],[poller=epoll],)
]
)
-AM_CONDITIONAL([HAVE_ECF], [test x$poller = xsolaris-ecf])
-AM_CONDITIONAL([HAVE_EPOLL], [test x$poller = xepoll])
+AM_CONDITIONAL([USE_ECF], [test x$poller = xsolaris-ecf])
+AM_CONDITIONAL([USE_POLL], [test x$poller = xpoll])
+AM_CONDITIONAL([USE_EPOLL], [test x$poller = xepoll])
#Filter not implemented or invalid mechanisms
if test $poller = xno; then
@@ -480,6 +483,24 @@ case "$host" in
esac
AM_CONDITIONAL([SUNOS], [test x$arch = xsolaris])
+# Check whether we've got the header for dtrace static probes
+AC_ARG_WITH([probes],
+ [AS_HELP_STRING([--with-probes], [Build with dtrace/systemtap static probes])],
+ [case ${withval} in
+ yes)
+ AC_CHECK_HEADERS([sys/sdt.h])
+ ;;
+ no)
+ ;;
+ *)
+ AC_MSG_ERROR([Bad value for --with-probes: ${withval}])
+ ;;
+ esac],
+ [
+ AC_CHECK_HEADERS([sys/sdt.h])
+ ]
+)
+
# Check for some syslog capabilities not present in all systems
AC_TRY_COMPILE([#include <sys/syslog.h>],
[int v = LOG_AUTHPRIV;],
diff --git a/cpp/include/qpid/framing/SequenceNumber.h b/cpp/include/qpid/framing/SequenceNumber.h
index eed15a4b75..dd85d97a52 100644
--- a/cpp/include/qpid/framing/SequenceNumber.h
+++ b/cpp/include/qpid/framing/SequenceNumber.h
@@ -52,9 +52,9 @@ boost::equality_comparable<
uint32_t getValue() const { return uint32_t(value); }
operator uint32_t() const { return uint32_t(value); }
- void encode(Buffer& buffer) const;
- void decode(Buffer& buffer);
- uint32_t encodedSize() const;
+ QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
+ QPID_COMMON_EXTERN void decode(Buffer& buffer);
+ QPID_COMMON_EXTERN uint32_t encodedSize() const;
template <class S> void serialize(S& s) { s(value); }
diff --git a/cpp/include/qpid/framing/SequenceSet.h b/cpp/include/qpid/framing/SequenceSet.h
index 0a78e418ba..827c8999b3 100644
--- a/cpp/include/qpid/framing/SequenceSet.h
+++ b/cpp/include/qpid/framing/SequenceSet.h
@@ -38,9 +38,9 @@ class QPID_COMMON_CLASS_EXTERN SequenceSet : public RangeSet<SequenceNumber> {
SequenceSet(const SequenceNumber& start, const SequenceNumber finish) { add(start,finish); }
- void encode(Buffer& buffer) const;
- void decode(Buffer& buffer);
- uint32_t encodedSize() const;
+ QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
+ QPID_COMMON_EXTERN void decode(Buffer& buffer);
+ QPID_COMMON_EXTERN uint32_t encodedSize() const;
QPID_COMMON_EXTERN bool contains(const SequenceNumber& s) const;
QPID_COMMON_EXTERN void add(const SequenceNumber& s);
diff --git a/cpp/include/qpid/types/Variant.h b/cpp/include/qpid/types/Variant.h
index 3feba4a0ec..3493559777 100644
--- a/cpp/include/qpid/types/Variant.h
+++ b/cpp/include/qpid/types/Variant.h
@@ -60,9 +60,9 @@ enum VariantType {
VAR_UUID
};
-std::string getTypeName(VariantType type);
+QPID_TYPES_EXTERN std::string getTypeName(VariantType type);
-bool isIntegerType(VariantType type);
+QPID_TYPES_EXTERN bool isIntegerType(VariantType type);
class VariantImpl;
diff --git a/cpp/managementgen/qmfgen/schema.py b/cpp/managementgen/qmfgen/schema.py
index b8a1d26fb0..c48ae572d2 100755
--- a/cpp/managementgen/qmfgen/schema.py
+++ b/cpp/managementgen/qmfgen/schema.py
@@ -1471,7 +1471,7 @@ class SchemaClass:
def genMethodIdDeclarations (self, stream, variables):
number = 1
for method in self.methods:
- stream.write (" static const uint32_t METHOD_" + method.getName().upper() +\
+ stream.write (" QPID_BROKER_EXTERN static const uint32_t METHOD_" + method.getName().upper() +\
" = %d;\n" % number)
number = number + 1
diff --git a/cpp/managementgen/qmfgen/templates/Class.h b/cpp/managementgen/qmfgen/templates/Class.h
index 90f1b4dd4a..0527d53536 100644
--- a/cpp/managementgen/qmfgen/templates/Class.h
+++ b/cpp/managementgen/qmfgen/templates/Class.h
@@ -24,6 +24,7 @@
/*MGEN:Root.Disclaimer*/
#include "qpid/management/ManagementObject.h"
+#include "qmf/BrokerImportExport.h"
namespace qpid {
namespace management {
@@ -34,7 +35,7 @@ namespace qpid {
namespace qmf {
/*MGEN:Class.OpenNamespaces*/
-class /*MGEN:Class.NameCap*/ : public ::qpid::management::ManagementObject
+QPID_BROKER_CLASS_EXTERN class /*MGEN:Class.NameCap*/ : public ::qpid::management::ManagementObject
{
private:
@@ -72,25 +73,25 @@ class /*MGEN:Class.NameCap*/ : public ::qpid::management::ManagementObject
void aggregatePerThreadStats(struct PerThreadStats*) const;
/*MGEN:ENDIF*/
public:
- static void writeSchema(std::string& schema);
- void mapEncodeValues(::qpid::types::Variant::Map& map,
- bool includeProperties=true,
- bool includeStatistics=true);
- void mapDecodeValues(const ::qpid::types::Variant::Map& map);
- void doMethod(std::string& methodName,
- const ::qpid::types::Variant::Map& inMap,
- ::qpid::types::Variant::Map& outMap,
- const std::string& userId);
- std::string getKey() const;
+ QPID_BROKER_EXTERN static void writeSchema(std::string& schema);
+ QPID_BROKER_EXTERN void mapEncodeValues(::qpid::types::Variant::Map& map,
+ bool includeProperties=true,
+ bool includeStatistics=true);
+ QPID_BROKER_EXTERN void mapDecodeValues(const ::qpid::types::Variant::Map& map);
+ QPID_BROKER_EXTERN void doMethod(std::string& methodName,
+ const ::qpid::types::Variant::Map& inMap,
+ ::qpid::types::Variant::Map& outMap,
+ const std::string& userId);
+ QPID_BROKER_EXTERN std::string getKey() const;
/*MGEN:IF(Root.GenQMFv1)*/
- uint32_t writePropertiesSize() const;
- void readProperties(const std::string& buf);
- void writeProperties(std::string& buf) const;
- void writeStatistics(std::string& buf, bool skipHeaders = false);
- void doMethod(std::string& methodName,
- const std::string& inBuf,
- std::string& outBuf,
- const std::string& userId);
+ QPID_BROKER_EXTERN uint32_t writePropertiesSize() const;
+ QPID_BROKER_EXTERN void readProperties(const std::string& buf);
+ QPID_BROKER_EXTERN void writeProperties(std::string& buf) const;
+ QPID_BROKER_EXTERN void writeStatistics(std::string& buf, bool skipHeaders = false);
+ QPID_BROKER_EXTERN void doMethod(std::string& methodName,
+ const std::string& inBuf,
+ std::string& outBuf,
+ const std::string& userId);
/*MGEN:ENDIF*/
writeSchemaCall_t getWriteSchemaCall() { return writeSchema; }
@@ -100,13 +101,17 @@ class /*MGEN:Class.NameCap*/ : public ::qpid::management::ManagementObject
bool hasInst() { return false; }
/*MGEN:ENDIF*/
- /*MGEN:Class.NameCap*/(::qpid::management::ManagementAgent* agent,
- ::qpid::management::Manageable* coreObject/*MGEN:Class.ParentArg*//*MGEN:Class.ConstructorArgs*/);
- ~/*MGEN:Class.NameCap*/();
+ QPID_BROKER_EXTERN /*MGEN:Class.NameCap*/(
+ ::qpid::management::ManagementAgent* agent,
+ ::qpid::management::Manageable* coreObject/*MGEN:Class.ParentArg*//*MGEN:Class.ConstructorArgs*/);
+
+ QPID_BROKER_EXTERN ~/*MGEN:Class.NameCap*/();
/*MGEN:Class.SetGeneralReferenceDeclaration*/
- static void registerSelf(::qpid::management::ManagementAgent* agent);
+ QPID_BROKER_EXTERN static void registerSelf(
+ ::qpid::management::ManagementAgent* agent);
+
std::string& getPackageName() const { return packageName; }
std::string& getClassName() const { return className; }
uint8_t* getMd5Sum() const { return md5Sum; }
diff --git a/cpp/managementgen/qmfgen/templates/Event.h b/cpp/managementgen/qmfgen/templates/Event.h
index 5fa5f8e576..592ae08c73 100644
--- a/cpp/managementgen/qmfgen/templates/Event.h
+++ b/cpp/managementgen/qmfgen/templates/Event.h
@@ -24,11 +24,12 @@
/*MGEN:Root.Disclaimer*/
#include "qpid/management/ManagementEvent.h"
+#include "qmf/BrokerImportExport.h"
namespace qmf {
/*MGEN:Event.OpenNamespaces*/
-class Event/*MGEN:Event.NameCap*/ : public ::qpid::management::ManagementEvent
+QPID_BROKER_CLASS_EXTERN class Event/*MGEN:Event.NameCap*/ : public ::qpid::management::ManagementEvent
{
private:
static void writeSchema (std::string& schema);
@@ -41,18 +42,18 @@ class Event/*MGEN:Event.NameCap*/ : public ::qpid::management::ManagementEvent
public:
writeSchemaCall_t getWriteSchemaCall(void) { return writeSchema; }
- Event/*MGEN:Event.NameCap*/(/*MGEN:Event.ConstructorArgs*/);
- ~Event/*MGEN:Event.NameCap*/() {};
+ QPID_BROKER_EXTERN Event/*MGEN:Event.NameCap*/(/*MGEN:Event.ConstructorArgs*/);
+ QPID_BROKER_EXTERN ~Event/*MGEN:Event.NameCap*/() {};
static void registerSelf(::qpid::management::ManagementAgent* agent);
std::string& getPackageName() const { return packageName; }
std::string& getEventName() const { return eventName; }
uint8_t* getMd5Sum() const { return md5Sum; }
uint8_t getSeverity() const { return /*MGEN:Event.Severity*/; }
- void encode(std::string& buffer) const;
- void mapEncode(::qpid::types::Variant::Map& map) const;
+ QPID_BROKER_EXTERN void encode(std::string& buffer) const;
+ QPID_BROKER_EXTERN void mapEncode(::qpid::types::Variant::Map& map) const;
- static bool match(const std::string& evt, const std::string& pkg);
+ QPID_BROKER_EXTERN static bool match(const std::string& evt, const std::string& pkg);
};
}/*MGEN:Event.CloseNamespaces*/
diff --git a/cpp/managementgen/qmfgen/templates/Package.h b/cpp/managementgen/qmfgen/templates/Package.h
index 569c7cfb33..3a42f12f9d 100644
--- a/cpp/managementgen/qmfgen/templates/Package.h
+++ b/cpp/managementgen/qmfgen/templates/Package.h
@@ -24,6 +24,7 @@
/*MGEN:Root.Disclaimer*/
#include "qpid//*MGEN:Class.AgentHeaderLocation*//ManagementAgent.h"
+#include "qmf/BrokerImportExport.h"
namespace qmf {
/*MGEN:Class.OpenNamespaces*/
@@ -31,8 +32,8 @@ namespace qmf {
class Package
{
public:
- Package (::qpid::management::ManagementAgent* agent);
- ~Package () {}
+ QPID_BROKER_EXTERN Package (::qpid::management::ManagementAgent* agent);
+ QPID_BROKER_EXTERN ~Package () {}
};
}/*MGEN:Class.CloseNamespaces*/
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index e8e543b672..cfcdead883 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -477,6 +477,29 @@ else (NOT CLOCK_GETTIME_IN_RT)
set(QPID_HAS_CLOCK_GETTIME YES CACHE BOOL "Platform has clock_gettime")
endif (NOT CLOCK_GETTIME_IN_RT)
+# Check for header file for dtrace static probes
+check_include_files(sys/sdt.h HAVE_SYS_SDT_H)
+if (HAVE_SYS_SDT_H)
+ set(probes_default ON)
+endif (HAVE_SYS_SDT_H)
+option(BUILD_PROBES "Build with DTrace/systemtap static probes" ${probes_default})
+if (NOT BUILD_PROBES)
+ set (HAVE_SYS_SDT_H 0)
+endif (NOT BUILD_PROBES)
+
+# Check for poll/epoll header files
+check_include_files(sys/poll.h HAVE_POLL)
+check_include_files(sys/epoll.h HAVE_EPOLL)
+
+# Set default poller implementation (check from general to specific to allow overriding)
+if (HAVE_POLL)
+ set(poller_default poll)
+endif (HAVE_POLL)
+if (HAVE_EPOLL)
+ set(poller_default epoll)
+endif (HAVE_EPOLL)
+set(POLLER ${poller_default} CACHE STRING "Poller implementation (poll/epoll)")
+
# If not windows ensure that we have uuid library
if (NOT CMAKE_SYSTEM_NAME STREQUAL Windows)
CHECK_LIBRARY_EXISTS (uuid uuid_compare "" HAVE_UUID)
@@ -740,9 +763,18 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
# POSIX (Non-Windows) platforms have a lot of overlap in sources; the only
# major difference is the poller module.
- if (CMAKE_SYSTEM_NAME STREQUAL Linux)
+ if (POLLER STREQUAL poll)
+ set (qpid_poller_module
+ qpid/sys/posix/PosixPoller.cpp
+ )
+ elseif (POLLER STREQUAL epoll)
set (qpid_poller_module
qpid/sys/epoll/EpollPoller.cpp
+ )
+ endif (POLLER STREQUAL poll)
+
+ if (CMAKE_SYSTEM_NAME STREQUAL Linux)
+ set (qpid_system_module
qpid/sys/posix/SystemInfo.cpp
)
add_definitions(-pthread)
@@ -754,13 +786,12 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
set (qpidtypes_platform_SOURCES)
set (qpidtypes_platform_LIBS
- uuid
- ${Boost_SYSTEM_LIBRARY}
+ uuid
+ ${Boost_SYSTEM_LIBRARY}
)
if (CMAKE_SYSTEM_NAME STREQUAL SunOS)
- set (qpid_poller_module
- qpid/sys/posix/PosixPoller.cpp
+ set (qpid_system_module
qpid/sys/solaris/SystemInfo.cpp
)
# On Sun we want -lpthread -lthread as the 2nd last and last libs passed to linker
@@ -789,6 +820,7 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
qpid/sys/posix/Time.cpp
qpid/SaslFactory.cpp
+ ${qpid_system_module}
${qpid_poller_module}
)
set (qpidcommon_platform_LIBS
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index 4f733e985b..e03c88ec8b 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -102,15 +102,16 @@ $(srcdir)/rubygen.cmake: $(rgen_generator) $(specs)
# Management generator.
mgen_dir=$(top_srcdir)/managementgen
-mgen_cmd=$(mgen_dir)/qmf-gen -m $(srcdir)/managementgen.mk \
- -c $(srcdir)/managementgen.cmake -q -b -o qmf \
- $(top_srcdir)/../specs/management-schema.xml \
+mgen_xml=$(top_srcdir)/../specs/management-schema.xml \
$(srcdir)/qpid/acl/management-schema.xml \
$(srcdir)/qpid/cluster/management-schema.xml \
$(srcdir)/qpid/ha/management-schema.xml
+mgen_cmd=$(mgen_dir)/qmf-gen -m $(srcdir)/managementgen.mk \
+ -c $(srcdir)/managementgen.cmake -q -b -o qmf \
+ $(mgen_xml)
$(srcdir)/managementgen.mk $(mgen_broker_cpp) $(dist_qpid_management_HEADERS): mgen.timestamp
-mgen.timestamp: $(mgen_generator)
+mgen.timestamp: $(mgen_generator) $(mgen_xml)
$(mgen_cmd); touch $@
$(mgen_generator):
@@ -183,11 +184,15 @@ nobase_include_HEADERS += \
../include/qpid/sys/posix/Time.h \
../include/qpid/sys/posix/check.h
-if HAVE_EPOLL
+if USE_EPOLL
poller = qpid/sys/epoll/EpollPoller.cpp
endif
-if HAVE_ECF
+if USE_POLL
+ poller = qpid/sys/posix/PosixPoller.cpp
+endif
+
+if USE_ECF
poller = qpid/sys/solaris/ECFPoller.cpp
endif
@@ -481,12 +486,14 @@ libqpidcommon_la_SOURCES += \
qpid/sys/Fork.h \
qpid/sys/LockFile.h \
qpid/sys/LockPtr.h \
+ qpid/sys/MemStat.h \
qpid/sys/OutputControl.h \
qpid/sys/OutputTask.h \
qpid/sys/PipeHandle.h \
qpid/sys/PollableCondition.h \
qpid/sys/PollableQueue.h \
qpid/sys/Poller.h \
+ qpid/sys/Probes.h \
qpid/sys/ProtocolFactory.h \
qpid/sys/Runnable.cpp \
qpid/sys/ScopedIncrement.h \
@@ -632,7 +639,6 @@ libqpidbroker_la_SOURCES = \
qpid/broker/QueuedMessage.h \
qpid/broker/QueueFlowLimit.h \
qpid/broker/QueueFlowLimit.cpp \
- qpid/broker/RateFlowcontrol.h \
qpid/broker/RecoverableConfig.h \
qpid/broker/RecoverableExchange.h \
qpid/broker/RecoverableMessage.h \
diff --git a/cpp/src/config.h.cmake b/cpp/src/config.h.cmake
index 2bb84c6e47..f55f68afde 100644
--- a/cpp/src/config.h.cmake
+++ b/cpp/src/config.h.cmake
@@ -60,6 +60,7 @@
#cmakedefine HAVE_OPENAIS_CPG_H ${HAVE_OPENAIS_CPG_H}
#cmakedefine HAVE_COROSYNC_CPG_H ${HAVE_COROSYNC_CPG_H}
#cmakedefine HAVE_LIBCMAN_H ${HAVE_LIBCMAN_H}
+#cmakedefine HAVE_SYS_SDT_H ${HAVE_SYS_SDT_H}
#cmakedefine HAVE_LOG_AUTHPRIV
#cmakedefine HAVE_LOG_FTP
diff --git a/cpp/src/qmf.mk b/cpp/src/qmf.mk
index 95d3d5c9b0..9b5df6c808 100644
--- a/cpp/src/qmf.mk
+++ b/cpp/src/qmf.mk
@@ -96,6 +96,7 @@ libqmf2_la_SOURCES = \
qmf/AgentSessionImpl.h \
qmf/AgentSubscription.cpp \
qmf/AgentSubscription.h \
+ qmf/BrokerImportExport.h \
qmf/ConsoleEvent.cpp \
qmf/ConsoleEventImpl.h \
qmf/ConsoleSession.cpp \
diff --git a/cpp/src/qmf/BrokerImportExport.h b/cpp/src/qmf/BrokerImportExport.h
new file mode 100644
index 0000000000..ee05788063
--- /dev/null
+++ b/cpp/src/qmf/BrokerImportExport.h
@@ -0,0 +1,42 @@
+#ifndef QPID_BROKER_IMPORT_EXPORT_H
+#define QPID_BROKER_IMPORT_EXPORT_H
+
+/*
+ * 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.
+ */
+
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
+# if defined(BROKER_EXPORT) || defined (qpidbroker_EXPORTS)
+# define QPID_BROKER_EXTERN __declspec(dllexport)
+# else
+# define QPID_BROKER_EXTERN __declspec(dllimport)
+# endif
+# ifdef _MSC_VER
+# define QPID_BROKER_CLASS_EXTERN
+# define QPID_BROKER_INLINE_EXTERN QPID_BROKER_EXTERN
+# else
+# define QPID_BROKER_CLASS_EXTERN QPID_BROKER_EXTERN
+# define QPID_BROKER_INLINE_EXTERN
+# endif
+#else
+# define QPID_BROKER_EXTERN
+# define QPID_BROKER_CLASS_EXTERN
+# define QPID_BROKER_INLINE_EXTERN
+#endif
+
+#endif
diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h
index b6eab894f3..a812c28b80 100644
--- a/cpp/src/qpid/broker/Broker.h
+++ b/cpp/src/qpid/broker/Broker.h
@@ -205,7 +205,7 @@ public:
ConsumerFactories consumerFactories;
public:
- virtual ~Broker();
+ QPID_BROKER_EXTERN virtual ~Broker();
QPID_BROKER_EXTERN Broker(const Options& configuration);
static QPID_BROKER_EXTERN boost::intrusive_ptr<Broker> create(const Options& configuration);
@@ -217,16 +217,16 @@ public:
* port, which will be different if the configured port is
* 0.
*/
- virtual uint16_t getPort(const std::string& name) const;
+ QPID_BROKER_EXTERN virtual uint16_t getPort(const std::string& name) const;
/**
* Run the broker. Implements Runnable::run() so the broker
* can be run in a separate thread.
*/
- virtual void run();
+ QPID_BROKER_EXTERN virtual void run();
/** Shut down the broker */
- virtual void shutdown();
+ QPID_BROKER_EXTERN virtual void shutdown();
QPID_BROKER_EXTERN void setStore (boost::shared_ptr<MessageStore>& store);
MessageStore& getStore() { return *store; }
@@ -246,14 +246,14 @@ public:
SessionManager& getSessionManager() { return sessionManager; }
const std::string& getFederationTag() const { return federationTag; }
- management::ManagementObject* GetManagementObject (void) const;
- management::Manageable* GetVhostObject (void) const;
- management::Manageable::status_t ManagementMethod (uint32_t methodId,
- management::Args& args,
- std::string& text);
+ QPID_BROKER_EXTERN management::ManagementObject* GetManagementObject() const;
+ QPID_BROKER_EXTERN management::Manageable* GetVhostObject() const;
+ QPID_BROKER_EXTERN management::Manageable::status_t ManagementMethod(
+ uint32_t methodId, management::Args& args, std::string& text);
/** Add to the broker's protocolFactorys */
- void registerProtocolFactory(const std::string& name, boost::shared_ptr<sys::ProtocolFactory>);
+ QPID_BROKER_EXTERN void registerProtocolFactory(
+ const std::string& name, boost::shared_ptr<sys::ProtocolFactory>);
/** Accept connections */
QPID_BROKER_EXTERN void accept();
@@ -271,15 +271,17 @@ public:
/** Move messages from one queue to another.
A zero quantity means to move all messages
*/
- uint32_t queueMoveMessages( const std::string& srcQueue,
- const std::string& destQueue,
- uint32_t qty,
- const qpid::types::Variant::Map& filter);
+ QPID_BROKER_EXTERN uint32_t queueMoveMessages(
+ const std::string& srcQueue,
+ const std::string& destQueue,
+ uint32_t qty,
+ const qpid::types::Variant::Map& filter);
- boost::shared_ptr<sys::ProtocolFactory> getProtocolFactory(const std::string& name = TCP_TRANSPORT) const;
+ QPID_BROKER_EXTERN boost::shared_ptr<sys::ProtocolFactory> getProtocolFactory(
+ const std::string& name = TCP_TRANSPORT) const;
/** Expose poller so plugins can register their descriptors. */
- boost::shared_ptr<sys::Poller> getPoller();
+ QPID_BROKER_EXTERN boost::shared_ptr<sys::Poller> getPoller();
boost::shared_ptr<sys::ConnectionCodec::Factory> getConnectionFactory() { return factory; }
void setConnectionFactory(boost::shared_ptr<sys::ConnectionCodec::Factory> f) { factory = f; }
@@ -289,7 +291,7 @@ public:
/** Timer for tasks that must be synchronized if we are in a cluster */
sys::Timer& getClusterTimer() { return clusterTimer.get() ? *clusterTimer : timer; }
- void setClusterTimer(std::auto_ptr<sys::Timer>);
+ QPID_BROKER_EXTERN void setClusterTimer(std::auto_ptr<sys::Timer>);
boost::function<std::vector<Url> ()> getKnownBrokers;
@@ -320,15 +322,14 @@ public:
* context.
*@return true if delivery of a message should be deferred.
*/
- boost::function<bool (const std::string& queue,
- const boost::intrusive_ptr<Message>& msg)> deferDelivery;
+ boost::function<bool (const std::string& queue, const boost::intrusive_ptr<Message>& msg)> deferDelivery;
bool isAuthenticating ( ) { return config.auth; }
bool isTimestamping() { return config.timestampRcvMsgs; }
typedef boost::function1<void, boost::shared_ptr<Queue> > QueueFunctor;
- std::pair<boost::shared_ptr<Queue>, bool> createQueue(
+ QPID_BROKER_EXTERN std::pair<boost::shared_ptr<Queue>, bool> createQueue(
const std::string& name,
bool durable,
bool autodelete,
@@ -337,30 +338,39 @@ public:
const qpid::framing::FieldTable& arguments,
const std::string& userId,
const std::string& connectionId);
- void deleteQueue(const std::string& name,
- const std::string& userId,
- const std::string& connectionId,
- QueueFunctor check = QueueFunctor());
- std::pair<Exchange::shared_ptr, bool> createExchange(
+
+ QPID_BROKER_EXTERN void deleteQueue(
+ const std::string& name,
+ const std::string& userId,
+ const std::string& connectionId,
+ QueueFunctor check = QueueFunctor());
+
+ QPID_BROKER_EXTERN std::pair<Exchange::shared_ptr, bool> createExchange(
const std::string& name,
const std::string& type,
bool durable,
const std::string& alternateExchange,
const qpid::framing::FieldTable& args,
const std::string& userId, const std::string& connectionId);
- void deleteExchange(const std::string& name, const std::string& userId,
- const std::string& connectionId);
- void bind(const std::string& queue,
- const std::string& exchange,
- const std::string& key,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId);
- void unbind(const std::string& queue,
- const std::string& exchange,
- const std::string& key,
- const std::string& userId,
- const std::string& connectionId);
+
+ QPID_BROKER_EXTERN void deleteExchange(
+ const std::string& name, const std::string& userId,
+ const std::string& connectionId);
+
+ QPID_BROKER_EXTERN void bind(
+ const std::string& queue,
+ const std::string& exchange,
+ const std::string& key,
+ const qpid::framing::FieldTable& arguments,
+ const std::string& userId,
+ const std::string& connectionId);
+
+ QPID_BROKER_EXTERN void unbind(
+ const std::string& queue,
+ const std::string& exchange,
+ const std::string& key,
+ const std::string& userId,
+ const std::string& connectionId);
ConsumerFactories& getConsumerFactories() { return consumerFactories; }
ConnectionObservers& getConnectionObservers() { return connectionObservers; }
diff --git a/cpp/src/qpid/broker/ExchangeRegistry.h b/cpp/src/qpid/broker/ExchangeRegistry.h
index 90ef81b49e..27b705fbe5 100644
--- a/cpp/src/qpid/broker/ExchangeRegistry.h
+++ b/cpp/src/qpid/broker/ExchangeRegistry.h
@@ -54,7 +54,7 @@ class ExchangeRegistry{
bool durable,
const qpid::framing::FieldTable& args = framing::FieldTable());
QPID_BROKER_EXTERN void destroy(const std::string& name);
- Exchange::shared_ptr getDefault();
+ QPID_BROKER_EXTERN Exchange::shared_ptr getDefault();
/**
* Find the named exchange. Return 0 if not found.
@@ -75,7 +75,7 @@ class ExchangeRegistry{
/** Register an exchange instance.
*@return true if registered, false if exchange with same name is already registered.
*/
- bool registerExchange(const Exchange::shared_ptr&);
+ QPID_BROKER_EXTERN bool registerExchange(const Exchange::shared_ptr&);
QPID_BROKER_EXTERN void registerType(const std::string& type, FactoryFunction);
@@ -85,7 +85,7 @@ class ExchangeRegistry{
for (ExchangeMap::const_iterator i = exchanges.begin(); i != exchanges.end(); ++i)
f(i->second);
}
-
+
private:
typedef std::map<std::string, Exchange::shared_ptr> ExchangeMap;
typedef std::map<std::string, FactoryFunction > FunctionMap;
diff --git a/cpp/src/qpid/broker/Link.h b/cpp/src/qpid/broker/Link.h
index 4085c3bfcf..c7c8209db3 100644
--- a/cpp/src/qpid/broker/Link.h
+++ b/cpp/src/qpid/broker/Link.h
@@ -24,9 +24,11 @@
#include <boost/shared_ptr.hpp>
#include "qpid/Url.h"
+#include "qpid/broker/BrokerImportExport.h"
#include "qpid/broker/MessageStore.h"
#include "qpid/broker/PersistableConfig.h"
#include "qpid/broker/Bridge.h"
+#include "qpid/broker/BrokerImportExport.h"
#include "qpid/sys/Mutex.h"
#include "qpid/framing/FieldTable.h"
#include "qpid/management/Manageable.h"
@@ -94,6 +96,13 @@ class Link : public PersistableConfig, public management::Manageable {
bool tryFailoverLH(); // Called during maintenance visit
bool hideManagement() const;
+ void established(Connection*); // Called when connection is create
+ void opened(); // Called when connection is open (after create)
+ void closed(int, std::string); // Called when connection goes away
+ void reconnectLH(const Address&); //called by LinkRegistry
+
+ friend class LinkRegistry; // to call established, opened, closed
+
public:
typedef boost::shared_ptr<Link> shared_ptr;
@@ -119,13 +128,9 @@ class Link : public PersistableConfig, public management::Manageable {
uint nextChannel();
void add(Bridge::shared_ptr);
void cancel(Bridge::shared_ptr);
- void setUrl(const Url&); // Set URL for reconnection.
- void established(Connection*); // Called when connection is create
- void opened(); // Called when connection is open (after create)
- void closed(int, std::string); // Called when connection goes away
- void reconnectLH(const Address&); //called by LinkRegistry
- void close(); // Close the link from within the broker.
+ QPID_BROKER_EXTERN void setUrl(const Url&); // Set URL for reconnection.
+ QPID_BROKER_EXTERN void close(); // Close the link from within the broker.
std::string getAuthMechanism() { return authMechanism; }
std::string getUsername() { return username; }
diff --git a/cpp/src/qpid/broker/LinkRegistry.cpp b/cpp/src/qpid/broker/LinkRegistry.cpp
index bb602bb953..c6c5a1ac05 100644
--- a/cpp/src/qpid/broker/LinkRegistry.cpp
+++ b/cpp/src/qpid/broker/LinkRegistry.cpp
@@ -25,7 +25,9 @@
#include <iostream>
#include <boost/format.hpp>
-using namespace qpid::broker;
+namespace qpid {
+namespace broker {
+
using namespace qpid::sys;
using std::string;
using std::pair;
@@ -45,16 +47,15 @@ LinkRegistry::LinkRegistry () :
{
}
-namespace {
-struct ConnectionObserverImpl : public ConnectionObserver {
+class LinkRegistryConnectionObserver : public ConnectionObserver {
LinkRegistry& links;
- ConnectionObserverImpl(LinkRegistry& l) : links(l) {}
+ public:
+ LinkRegistryConnectionObserver(LinkRegistry& l) : links(l) {}
void connection(Connection& c) { links.notifyConnection(c.getMgmtId(), &c); }
void opened(Connection& c) { links.notifyOpened(c.getMgmtId()); }
void closed(Connection& c) { links.notifyClosed(c.getMgmtId()); }
void forced(Connection& c, const string& text) { links.notifyConnectionForced(c.getMgmtId(), text); }
};
-}
LinkRegistry::LinkRegistry (Broker* _broker) :
broker(_broker),
@@ -62,7 +63,7 @@ LinkRegistry::LinkRegistry (Broker* _broker) :
realm(broker->getOptions().realm)
{
broker->getConnectionObservers().add(
- boost::shared_ptr<ConnectionObserver>(new ConnectionObserverImpl(*this)));
+ boost::shared_ptr<ConnectionObserver>(new LinkRegistryConnectionObserver(*this)));
}
LinkRegistry::~LinkRegistry() {}
@@ -368,3 +369,4 @@ void LinkRegistry::eachBridge(boost::function<void(boost::shared_ptr<Bridge>)> f
for (BridgeMap::iterator i = bridges.begin(); i != bridges.end(); ++i) f(i->second);
}
+}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/LinkRegistry.h b/cpp/src/qpid/broker/LinkRegistry.h
index 753f6bfe9e..8e9d2f4b0d 100644
--- a/cpp/src/qpid/broker/LinkRegistry.h
+++ b/cpp/src/qpid/broker/LinkRegistry.h
@@ -23,6 +23,7 @@
*/
#include <map>
+#include "qpid/broker/BrokerImportExport.h"
#include "qpid/broker/Bridge.h"
#include "qpid/broker/MessageStore.h"
#include "qpid/Address.h"
@@ -56,43 +57,50 @@ namespace broker {
static std::string createKey(const Address& address);
static std::string createKey(const std::string& host, uint16_t port);
+ // Methods called by the connection observer.
+ void notifyConnection (const std::string& key, Connection* c);
+ void notifyOpened (const std::string& key);
+ void notifyClosed (const std::string& key);
+ void notifyConnectionForced (const std::string& key, const std::string& text);
+ friend class LinkRegistryConnectionObserver;
+
public:
- LinkRegistry (); // Only used in store tests
- LinkRegistry (Broker* _broker);
- ~LinkRegistry();
-
- std::pair<boost::shared_ptr<Link>, bool>
- declare(const std::string& host,
- uint16_t port,
- const std::string& transport,
- bool durable,
- const std::string& authMechanism,
- const std::string& username,
- const std::string& password);
-
- std::pair<Bridge::shared_ptr, bool>
- declare(const std::string& host,
- uint16_t port,
- bool durable,
- const std::string& src,
- const std::string& dest,
- const std::string& key,
- bool isQueue,
- bool isLocal,
- const std::string& id,
- const std::string& excludes,
- bool dynamic,
- uint16_t sync,
- Bridge::InitializeCallback=0
- );
-
- void destroy(const std::string& host, const uint16_t port);
-
- void destroy(const std::string& host,
- const uint16_t port,
- const std::string& src,
- const std::string& dest,
- const std::string& key);
+ QPID_BROKER_EXTERN LinkRegistry (); // Only used in store tests
+ QPID_BROKER_EXTERN LinkRegistry (Broker* _broker);
+ QPID_BROKER_EXTERN ~LinkRegistry();
+
+ QPID_BROKER_EXTERN std::pair<boost::shared_ptr<Link>, bool>
+ declare(const std::string& host,
+ uint16_t port,
+ const std::string& transport,
+ bool durable,
+ const std::string& authMechanism,
+ const std::string& username,
+ const std::string& password);
+
+ QPID_BROKER_EXTERN std::pair<Bridge::shared_ptr, bool>
+ declare(const std::string& host,
+ uint16_t port,
+ bool durable,
+ const std::string& src,
+ const std::string& dest,
+ const std::string& key,
+ bool isQueue,
+ bool isLocal,
+ const std::string& id,
+ const std::string& excludes,
+ bool dynamic,
+ uint16_t sync,
+ Bridge::InitializeCallback=0
+ );
+
+ QPID_BROKER_EXTERN void destroy(const std::string& host, const uint16_t port);
+
+ QPID_BROKER_EXTERN void destroy(const std::string& host,
+ const uint16_t port,
+ const std::string& src,
+ const std::string& dest,
+ const std::string& key);
/**
* Register the manageable parent for declared queues
@@ -102,24 +110,20 @@ namespace broker {
/**
* Set the store to use. May only be called once.
*/
- void setStore (MessageStore*);
+ QPID_BROKER_EXTERN void setStore (MessageStore*);
/**
* Return the message store used.
*/
- MessageStore* getStore() const;
+ QPID_BROKER_EXTERN MessageStore* getStore() const;
- void notifyConnection (const std::string& key, Connection* c);
- void notifyOpened (const std::string& key);
- void notifyClosed (const std::string& key);
- void notifyConnectionForced (const std::string& key, const std::string& text);
- std::string getAuthMechanism (const std::string& key);
- std::string getAuthCredentials (const std::string& key);
- std::string getAuthIdentity (const std::string& key);
- std::string getUsername (const std::string& key);
- std::string getPassword (const std::string& key);
- std::string getHost (const std::string& key);
- uint16_t getPort (const std::string& key);
+ QPID_BROKER_EXTERN std::string getAuthMechanism (const std::string& key);
+ QPID_BROKER_EXTERN std::string getAuthCredentials (const std::string& key);
+ QPID_BROKER_EXTERN std::string getAuthIdentity (const std::string& key);
+ QPID_BROKER_EXTERN std::string getUsername (const std::string& key);
+ QPID_BROKER_EXTERN std::string getPassword (const std::string& key);
+ QPID_BROKER_EXTERN std::string getHost (const std::string& key);
+ QPID_BROKER_EXTERN uint16_t getPort (const std::string& key);
/**
* Called by links failing over to new address
@@ -132,13 +136,13 @@ namespace broker {
* updated but links won't actually establish connections and
* bridges won't therefore pull or push any messages.
*/
- void setPassive(bool);
- bool isPassive() { return passive; }
+ QPID_BROKER_EXTERN void setPassive(bool);
+ QPID_BROKER_EXTERN bool isPassive() { return passive; }
/** Iterate over each link in the registry. Used for cluster updates. */
- void eachLink(boost::function<void(boost::shared_ptr<Link>)> f);
+ QPID_BROKER_EXTERN void eachLink(boost::function<void(boost::shared_ptr<Link>)> f);
/** Iterate over each bridge in the registry. Used for cluster updates. */
- void eachBridge(boost::function<void(boost::shared_ptr< Bridge>)> f);
+ QPID_BROKER_EXTERN void eachBridge(boost::function<void(boost::shared_ptr< Bridge>)> f);
};
}
}
diff --git a/cpp/src/qpid/broker/Queue.h b/cpp/src/qpid/broker/Queue.h
index e8573c17cc..66efe4eca3 100644
--- a/cpp/src/qpid/broker/Queue.h
+++ b/cpp/src/qpid/broker/Queue.h
@@ -235,8 +235,9 @@ class Queue : public boost::enable_shared_from_this<Queue>,
/**
* Bind self to specified exchange, and record that binding for unbinding on delete.
*/
- bool bind(boost::shared_ptr<Exchange> exchange, const std::string& key,
- const qpid::framing::FieldTable& arguments=qpid::framing::FieldTable());
+ QPID_BROKER_EXTERN bool bind(
+ boost::shared_ptr<Exchange> exchange, const std::string& key,
+ const qpid::framing::FieldTable& arguments=qpid::framing::FieldTable());
/** Acquire the message at the given position if it is available for acquire. Not to
* be used by clients, but used by the broker for queue management.
@@ -271,28 +272,29 @@ class Queue : public boost::enable_shared_from_this<Queue>,
bool exclusive = false);
QPID_BROKER_EXTERN void cancel(Consumer::shared_ptr c);
- uint32_t purge(const uint32_t purge_request=0, //defaults to all messages
+ QPID_BROKER_EXTERN uint32_t purge(const uint32_t purge_request=0, //defaults to all messages
boost::shared_ptr<Exchange> dest=boost::shared_ptr<Exchange>(),
const ::qpid::types::Variant::Map *filter=0);
QPID_BROKER_EXTERN void purgeExpired(sys::Duration);
//move qty # of messages to destination Queue destq
- uint32_t move(const Queue::shared_ptr destq, uint32_t qty,
- const qpid::types::Variant::Map *filter=0);
+ QPID_BROKER_EXTERN uint32_t move(
+ const Queue::shared_ptr destq, uint32_t qty,
+ const qpid::types::Variant::Map *filter=0);
QPID_BROKER_EXTERN uint32_t getMessageCount() const;
QPID_BROKER_EXTERN uint32_t getEnqueueCompleteMessageCount() const;
QPID_BROKER_EXTERN uint32_t getConsumerCount() const;
inline const std::string& getName() const { return name; }
- bool isExclusiveOwner(const OwnershipToken* const o) const;
- void releaseExclusiveOwnership();
- bool setExclusiveOwner(const OwnershipToken* const o);
- bool hasExclusiveConsumer() const;
- bool hasExclusiveOwner() const;
+ QPID_BROKER_EXTERN bool isExclusiveOwner(const OwnershipToken* const o) const;
+ QPID_BROKER_EXTERN void releaseExclusiveOwnership();
+ QPID_BROKER_EXTERN bool setExclusiveOwner(const OwnershipToken* const o);
+ QPID_BROKER_EXTERN bool hasExclusiveConsumer() const;
+ QPID_BROKER_EXTERN bool hasExclusiveOwner() const;
inline bool isDurable() const { return store != 0; }
inline const framing::FieldTable& getSettings() const { return settings; }
inline bool isAutoDelete() const { return autodelete; }
- bool canAutoDelete() const;
+ QPID_BROKER_EXTERN bool canAutoDelete() const;
const QueueBindings& getBindings() const { return bindings; }
/**
@@ -301,8 +303,8 @@ class Queue : public boost::enable_shared_from_this<Queue>,
QPID_BROKER_EXTERN void setLastNodeFailure();
QPID_BROKER_EXTERN void clearLastNodeFailure();
- bool enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg, bool suppressPolicyCheck = false);
- void enqueueAborted(boost::intrusive_ptr<Message> msg);
+ QPID_BROKER_EXTERN bool enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg, bool suppressPolicyCheck = false);
+ QPID_BROKER_EXTERN void enqueueAborted(boost::intrusive_ptr<Message> msg);
/**
* dequeue from store (only done once messages is acknowledged)
*/
@@ -311,7 +313,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
* Inform the queue that a previous transactional dequeue
* committed.
*/
- void dequeueCommitted(const QueuedMessage& msg);
+ QPID_BROKER_EXTERN void dequeueCommitted(const QueuedMessage& msg);
/**
* Inform queue of messages that were enqueued, have since
@@ -319,7 +321,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
* thus are still logically on the queue) - used in
* clustered broker.
*/
- void updateEnqueued(const QueuedMessage& msg);
+ QPID_BROKER_EXTERN void updateEnqueued(const QueuedMessage& msg);
/**
* Test whether the specified message (identified by its
@@ -328,7 +330,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
* have been delievered to a subscriber who has not yet
* accepted it).
*/
- bool isEnqueued(const QueuedMessage& msg);
+ QPID_BROKER_EXTERN bool isEnqueued(const QueuedMessage& msg);
/**
* Acquires the next available (oldest) message
@@ -338,17 +340,17 @@ class Queue : public boost::enable_shared_from_this<Queue>,
/** Get the message at position pos, returns true if found and sets msg */
QPID_BROKER_EXTERN bool find(framing::SequenceNumber pos, QueuedMessage& msg ) const;
- const QueuePolicy* getPolicy();
+ QPID_BROKER_EXTERN const QueuePolicy* getPolicy();
- void setAlternateExchange(boost::shared_ptr<Exchange> exchange);
- boost::shared_ptr<Exchange> getAlternateExchange();
- bool isLocal(boost::intrusive_ptr<Message>& msg);
+ QPID_BROKER_EXTERN void setAlternateExchange(boost::shared_ptr<Exchange> exchange);
+ QPID_BROKER_EXTERN boost::shared_ptr<Exchange> getAlternateExchange();
+ QPID_BROKER_EXTERN bool isLocal(boost::intrusive_ptr<Message>& msg);
//PersistableQueue support:
- uint64_t getPersistenceId() const;
- void setPersistenceId(uint64_t persistenceId) const;
- void encode(framing::Buffer& buffer) const;
- uint32_t encodedSize() const;
+ QPID_BROKER_EXTERN uint64_t getPersistenceId() const;
+ QPID_BROKER_EXTERN void setPersistenceId(uint64_t persistenceId) const;
+ QPID_BROKER_EXTERN void encode(framing::Buffer& buffer) const;
+ QPID_BROKER_EXTERN uint32_t encodedSize() const;
/**
* Restores a queue from encoded data (used in recovery)
@@ -362,15 +364,15 @@ class Queue : public boost::enable_shared_from_this<Queue>,
virtual void setExternalQueueStore(ExternalQueueStore* inst);
// Increment the rejected-by-consumer counter.
- void countRejected() const;
- void countFlowedToDisk(uint64_t size) const;
- void countLoadedFromDisk(uint64_t size) const;
+ QPID_BROKER_EXTERN void countRejected() const;
+ QPID_BROKER_EXTERN void countFlowedToDisk(uint64_t size) const;
+ QPID_BROKER_EXTERN void countLoadedFromDisk(uint64_t size) const;
// Manageable entry points
- management::ManagementObject* GetManagementObject (void) const;
+ QPID_BROKER_EXTERN management::ManagementObject* GetManagementObject (void) const;
management::Manageable::status_t
- ManagementMethod (uint32_t methodId, management::Args& args, std::string& text);
- void query(::qpid::types::Variant::Map&) const;
+ QPID_BROKER_EXTERN ManagementMethod (uint32_t methodId, management::Args& args, std::string& text);
+ QPID_BROKER_EXTERN void query(::qpid::types::Variant::Map&) const;
/** Apply f to each Message on the queue. */
template <class F> void eachMessage(F f) {
@@ -396,31 +398,31 @@ class Queue : public boost::enable_shared_from_this<Queue>,
/** return current position sequence number for the next message on the queue.
*/
QPID_BROKER_EXTERN framing::SequenceNumber getPosition();
- void addObserver(boost::shared_ptr<QueueObserver>);
- void removeObserver(boost::shared_ptr<QueueObserver>);
+ QPID_BROKER_EXTERN void addObserver(boost::shared_ptr<QueueObserver>);
+ QPID_BROKER_EXTERN void removeObserver(boost::shared_ptr<QueueObserver>);
QPID_BROKER_EXTERN void insertSequenceNumbers(const std::string& key);
/**
* Notify queue that recovery has completed.
*/
- void recoveryComplete(ExchangeRegistry& exchanges);
+ QPID_BROKER_EXTERN void recoveryComplete(ExchangeRegistry& exchanges);
// For cluster update
- QueueListeners& getListeners();
- Messages& getMessages();
- const Messages& getMessages() const;
+ QPID_BROKER_EXTERN QueueListeners& getListeners();
+ QPID_BROKER_EXTERN Messages& getMessages();
+ QPID_BROKER_EXTERN const Messages& getMessages() const;
/**
* Reserve space in policy for an enqueued message that
* has been recovered in the prepared state (dtx only)
*/
- void recoverPrepared(boost::intrusive_ptr<Message>& msg);
+ QPID_BROKER_EXTERN void recoverPrepared(boost::intrusive_ptr<Message>& msg);
- void flush();
+ QPID_BROKER_EXTERN void flush();
- Broker* getBroker();
+ QPID_BROKER_EXTERN Broker* getBroker();
uint32_t getDequeueSincePurge() { return dequeueSincePurge.get(); }
- void setDequeueSincePurge(uint32_t value);
+ QPID_BROKER_EXTERN void setDequeueSincePurge(uint32_t value);
};
}
}
diff --git a/cpp/src/qpid/broker/SemanticState.h b/cpp/src/qpid/broker/SemanticState.h
index f7c9760821..e5e1d2da16 100644
--- a/cpp/src/qpid/broker/SemanticState.h
+++ b/cpp/src/qpid/broker/SemanticState.h
@@ -22,6 +22,7 @@
*
*/
+#include "qpid/broker/BrokerImportExport.h"
#include "qpid/broker/Consumer.h"
#include "qpid/broker/Credit.h"
#include "qpid/broker/Deliverable.h"
@@ -98,42 +99,44 @@ class SemanticState : private boost::noncopyable {
bool haveCredit();
protected:
- virtual bool doDispatch();
+ QPID_BROKER_EXTERN virtual bool doDispatch();
size_t unacked() { return parent->unacked.size(); }
public:
typedef boost::shared_ptr<ConsumerImpl> shared_ptr;
- ConsumerImpl(SemanticState* parent,
- const std::string& name, boost::shared_ptr<Queue> queue,
- bool ack, bool acquire, bool exclusive,
- const std::string& tag, const std::string& resumeId, uint64_t resumeTtl, const framing::FieldTable& arguments);
- virtual ~ConsumerImpl();
- OwnershipToken* getSession();
- virtual bool deliver(QueuedMessage& msg);
- bool filter(boost::intrusive_ptr<Message> msg);
- bool accept(boost::intrusive_ptr<Message> msg);
- void cancel() {}
-
- void disableNotify();
- void enableNotify();
- void notify();
- bool isNotifyEnabled() const;
-
- void requestDispatch();
-
- void setWindowMode();
- void setCreditMode();
- void addByteCredit(uint32_t value);
- void addMessageCredit(uint32_t value);
- void flush();
- void stop();
- void complete(DeliveryRecord&);
+ QPID_BROKER_EXTERN ConsumerImpl(
+ SemanticState* parent,
+ const std::string& name, boost::shared_ptr<Queue> queue,
+ bool ack, bool acquire, bool exclusive,
+ const std::string& tag, const std::string& resumeId, uint64_t resumeTtl,
+ const framing::FieldTable& arguments);
+ QPID_BROKER_EXTERN virtual ~ConsumerImpl();
+ QPID_BROKER_EXTERN OwnershipToken* getSession();
+ QPID_BROKER_EXTERN virtual bool deliver(QueuedMessage& msg);
+ QPID_BROKER_EXTERN bool filter(boost::intrusive_ptr<Message> msg);
+ QPID_BROKER_EXTERN bool accept(boost::intrusive_ptr<Message> msg);
+ QPID_BROKER_EXTERN void cancel() {}
+
+ QPID_BROKER_EXTERN void disableNotify();
+ QPID_BROKER_EXTERN void enableNotify();
+ QPID_BROKER_EXTERN void notify();
+ QPID_BROKER_EXTERN bool isNotifyEnabled() const;
+
+ QPID_BROKER_EXTERN void requestDispatch();
+
+ QPID_BROKER_EXTERN void setWindowMode();
+ QPID_BROKER_EXTERN void setCreditMode();
+ QPID_BROKER_EXTERN void addByteCredit(uint32_t value);
+ QPID_BROKER_EXTERN void addMessageCredit(uint32_t value);
+ QPID_BROKER_EXTERN void flush();
+ QPID_BROKER_EXTERN void stop();
+ QPID_BROKER_EXTERN void complete(DeliveryRecord&);
boost::shared_ptr<Queue> getQueue() const { return queue; }
bool isBlocked() const { return blocked; }
bool setBlocked(bool set) { std::swap(set, blocked); return set; }
- bool doOutput();
+ QPID_BROKER_EXTERN bool doOutput();
Credit& getCredit() { return credit; }
const Credit& getCredit() const { return credit; }
@@ -151,8 +154,11 @@ class SemanticState : private boost::noncopyable {
void acknowledged(const broker::QueuedMessage&) {}
// manageable entry points
- management::ManagementObject* GetManagementObject (void) const;
- management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args, std::string& text);
+ QPID_BROKER_EXTERN management::ManagementObject*
+ GetManagementObject(void) const;
+
+ QPID_BROKER_EXTERN management::Manageable::status_t
+ ManagementMethod(uint32_t methodId, management::Args& args, std::string& text);
};
typedef std::map<std::string, DtxBuffer::shared_ptr> DtxBufferMap;
diff --git a/cpp/src/qpid/client/TCPConnector.cpp b/cpp/src/qpid/client/TCPConnector.cpp
index 51eacf77e8..4660a41c07 100644
--- a/cpp/src/qpid/client/TCPConnector.cpp
+++ b/cpp/src/qpid/client/TCPConnector.cpp
@@ -97,7 +97,7 @@ void TCPConnector::connect(const std::string& host, const std::string& port) {
boost::bind(&TCPConnector::connected, this, _1),
boost::bind(&TCPConnector::connectFailed, this, _3));
closed = false;
- identifier = str(format("[%1%]") % socket.getFullAddress());
+
connector->start(poller);
}
@@ -120,6 +120,8 @@ void TCPConnector::start(sys::AsynchIO* aio_) {
for (int i = 0; i < 4; i++) {
aio->queueReadBuffer(new Buff(maxFrameSize));
}
+
+ identifier = str(format("[%1%]") % socket.getFullAddress());
}
void TCPConnector::initAmqp() {
@@ -129,7 +131,7 @@ void TCPConnector::initAmqp() {
void TCPConnector::connectFailed(const std::string& msg) {
connector = 0;
- QPID_LOG(warning, "Connect failed: " << msg << " " << identifier);
+ QPID_LOG(warning, "Connect failed: " << msg);
socket.close();
if (!closed)
closed = true;
@@ -183,7 +185,7 @@ sys::ShutdownHandler* TCPConnector::getShutdownHandler() const {
return shutdownHandler;
}
-const std::string& TCPConnector::getIdentifier() const {
+const std::string& TCPConnector::getIdentifier() const {
return identifier;
}
diff --git a/cpp/src/qpid/ha/Backup.cpp b/cpp/src/qpid/ha/Backup.cpp
index 5acbfb9d5f..3d65e07202 100644
--- a/cpp/src/qpid/ha/Backup.cpp
+++ b/cpp/src/qpid/ha/Backup.cpp
@@ -52,7 +52,7 @@ Backup::Backup(broker::Broker& b, const Settings& s) :
void Backup::initialize(const Url& url) {
assert(!url.empty());
- QPID_LOG(notice, "Ha: Backup started: " << url);
+ QPID_LOG(notice, "HA: Backup started: " << url);
string protocol = url[0].protocol.empty() ? "tcp" : url[0].protocol;
// Declare the link
std::pair<Link::shared_ptr, bool> result = broker.getLinks().declare(
diff --git a/cpp/src/qpid/ha/BrokerReplicator.cpp b/cpp/src/qpid/ha/BrokerReplicator.cpp
index a8f05c1fe3..75e4ed893d 100644
--- a/cpp/src/qpid/ha/BrokerReplicator.cpp
+++ b/cpp/src/qpid/ha/BrokerReplicator.cpp
@@ -266,6 +266,7 @@ void BrokerReplicator::route(Deliverable& msg, const string& /*key*/, const fram
}
void BrokerReplicator::doEventQueueDeclare(Variant::Map& values) {
+ QPID_LOG(debug, "HA: Backup queue declare event " << values);
string name = values[QNAME].asString();
Variant::Map argsMap = asMapVoid(values[ARGS]);
if (values[DISP] == CREATED && replicateLevel(argsMap)) {
@@ -296,6 +297,7 @@ void BrokerReplicator::doEventQueueDeclare(Variant::Map& values) {
}
void BrokerReplicator::doEventQueueDelete(Variant::Map& values) {
+ QPID_LOG(debug, "HA: Backup queue delete event " << values);
// The remote queue has already been deleted so replicator
// sessions may be closed by a "queue deleted" exception.
string name = values[QNAME].asString();
@@ -314,6 +316,7 @@ void BrokerReplicator::doEventQueueDelete(Variant::Map& values) {
}
void BrokerReplicator::doEventExchangeDeclare(Variant::Map& values) {
+ QPID_LOG(debug, "HA: Backup exchange declare event " << values);
Variant::Map argsMap(asMapVoid(values[ARGS]));
if (values[DISP] == CREATED && replicateLevel(argsMap)) {
string name = values[EXNAME].asString();
@@ -338,6 +341,7 @@ void BrokerReplicator::doEventExchangeDeclare(Variant::Map& values) {
}
void BrokerReplicator::doEventExchangeDelete(Variant::Map& values) {
+ QPID_LOG(debug, "HA: Backup exchange delete event " << values);
string name = values[EXNAME].asString();
try {
boost::shared_ptr<Exchange> exchange = broker.getExchanges().find(name);
@@ -352,6 +356,7 @@ void BrokerReplicator::doEventExchangeDelete(Variant::Map& values) {
}
void BrokerReplicator::doEventBind(Variant::Map& values) {
+ QPID_LOG(debug, "HA: Backup bind event " << values);
boost::shared_ptr<Exchange> exchange =
broker.getExchanges().find(values[EXNAME].asString());
boost::shared_ptr<Queue> queue =
@@ -372,6 +377,7 @@ void BrokerReplicator::doEventBind(Variant::Map& values) {
}
void BrokerReplicator::doEventUnbind(Variant::Map& values) {
+ QPID_LOG(debug, "HA: Backup unbind event " << values);
boost::shared_ptr<Exchange> exchange =
broker.getExchanges().find(values[EXNAME].asString());
boost::shared_ptr<Queue> queue =
@@ -392,6 +398,7 @@ void BrokerReplicator::doEventUnbind(Variant::Map& values) {
}
void BrokerReplicator::doResponseQueue(Variant::Map& values) {
+ QPID_LOG(debug, "HA: Backup queue response " << values);
// FIXME aconway 2011-11-22: more flexible ways & defaults to indicate replication
Variant::Map argsMap(asMapVoid(values[ARGUMENTS]));
if (!replicateLevel(argsMap)) return;
@@ -419,6 +426,7 @@ void BrokerReplicator::doResponseQueue(Variant::Map& values) {
}
void BrokerReplicator::doResponseExchange(Variant::Map& values) {
+ QPID_LOG(debug, "HA: Backup exchange response " << values);
Variant::Map argsMap(asMapVoid(values[ARGUMENTS]));
if (!replicateLevel(argsMap)) return;
framing::FieldTable args;
@@ -460,6 +468,7 @@ const std::string QUEUE_REF("queueRef");
} // namespace
void BrokerReplicator::doResponseBind(Variant::Map& values) {
+ QPID_LOG(debug, "HA: Backup bind response " << values);
std::string exName = getRefName(EXCHANGE_REF_PREFIX, values[EXCHANGE_REF]);
std::string qName = getRefName(QUEUE_REF_PREFIX, values[QUEUE_REF]);
boost::shared_ptr<Exchange> exchange = broker.getExchanges().find(exName);
diff --git a/cpp/src/qpid/ha/HaBroker.cpp b/cpp/src/qpid/ha/HaBroker.cpp
index 0d3bd51439..d92749abeb 100644
--- a/cpp/src/qpid/ha/HaBroker.cpp
+++ b/cpp/src/qpid/ha/HaBroker.cpp
@@ -27,8 +27,9 @@
#include "qpid/broker/Broker.h"
#include "qpid/management/ManagementAgent.h"
#include "qmf/org/apache/qpid/ha/Package.h"
-#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetClientAddresses.h"
-#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetBrokerAddresses.h"
+#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetBrokers.h"
+#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetPublicBrokers.h"
+#include "qmf/org/apache/qpid/ha/ArgsHaBrokerSetExpectedBackups.h"
#include "qpid/log/Statement.h"
namespace qpid {
@@ -88,18 +89,19 @@ Manageable::status_t HaBroker::ManagementMethod (uint32_t methodId, Args& args,
}
break;
}
- case _qmf::HaBroker::METHOD_SETCLIENTADDRESSES: {
- setClientUrl(
- Url(dynamic_cast<_qmf::ArgsHaBrokerSetClientAddresses&>(args).
- i_clientAddresses), l);
+ case _qmf::HaBroker::METHOD_SETBROKERS: {
+ setBrokerUrl(Url(dynamic_cast<_qmf::ArgsHaBrokerSetBrokers&>(args).i_url), l);
break;
}
- case _qmf::HaBroker::METHOD_SETBROKERADDRESSES: {
- setBrokerUrl(
- Url(dynamic_cast<_qmf::ArgsHaBrokerSetBrokerAddresses&>(args)
- .i_brokerAddresses), l);
+ case _qmf::HaBroker::METHOD_SETPUBLICBROKERS: {
+ setClientUrl(Url(dynamic_cast<_qmf::ArgsHaBrokerSetPublicBrokers&>(args).i_url), l);
break;
}
+ case _qmf::HaBroker::METHOD_SETEXPECTEDBACKUPS: {
+ setExpectedBackups(dynamic_cast<_qmf::ArgsHaBrokerSetExpectedBackups&>(args).i_expectedBackups, l);
+ break;
+ }
+
default:
return Manageable::STATUS_UNKNOWN_METHOD;
}
@@ -115,21 +117,27 @@ void HaBroker::setClientUrl(const Url& url, const sys::Mutex::ScopedLock& l) {
void HaBroker::updateClientUrl(const sys::Mutex::ScopedLock&) {
Url url = clientUrl.empty() ? brokerUrl : clientUrl;
assert(!url.empty());
- mgmtObject->set_clientAddresses(url.str());
+ mgmtObject->set_publicBrokers(url.str());
knownBrokers.clear();
knownBrokers.push_back(url);
- QPID_LOG(debug, "HA: Setting client known-brokers to: " << url);
+ QPID_LOG(debug, "HA: Setting client URL to: " << url);
}
void HaBroker::setBrokerUrl(const Url& url, const sys::Mutex::ScopedLock& l) {
if (url.empty()) throw Exception("Invalid empty URL for HA broker failover");
+ QPID_LOG(debug, "HA: Setting broker URL to: " << url);
brokerUrl = url;
- mgmtObject->set_brokerAddresses(brokerUrl.str());
+ mgmtObject->set_brokers(brokerUrl.str());
if (backup.get()) backup->setBrokerUrl(brokerUrl);
// Updating broker URL also updates defaulted client URL:
if (clientUrl.empty()) updateClientUrl(l);
}
+void HaBroker::setExpectedBackups(size_t n, const sys::Mutex::ScopedLock&) {
+ expectedBackups = n;
+ mgmtObject->set_expectedBackups(n);
+}
+
std::vector<Url> HaBroker::getKnownBrokers() const {
return knownBrokers;
}
diff --git a/cpp/src/qpid/ha/HaBroker.h b/cpp/src/qpid/ha/HaBroker.h
index 835a47c749..4f4ee4c944 100644
--- a/cpp/src/qpid/ha/HaBroker.h
+++ b/cpp/src/qpid/ha/HaBroker.h
@@ -55,6 +55,7 @@ class HaBroker : public management::Manageable
private:
void setClientUrl(const Url&, const sys::Mutex::ScopedLock&);
void setBrokerUrl(const Url&, const sys::Mutex::ScopedLock&);
+ void setExpectedBackups(size_t, const sys::Mutex::ScopedLock&);
void updateClientUrl(const sys::Mutex::ScopedLock&);
bool isPrimary(const sys::Mutex::ScopedLock&) { return !backup.get(); }
std::vector<Url> getKnownBrokers() const;
@@ -67,6 +68,7 @@ class HaBroker : public management::Manageable
qmf::org::apache::qpid::ha::HaBroker* mgmtObject;
Url clientUrl, brokerUrl;
std::vector<Url> knownBrokers;
+ size_t expectedBackups;
};
}} // namespace qpid::ha
diff --git a/cpp/src/qpid/ha/HaPlugin.cpp b/cpp/src/qpid/ha/HaPlugin.cpp
index fc9e48411d..b3080330fb 100644
--- a/cpp/src/qpid/ha/HaPlugin.cpp
+++ b/cpp/src/qpid/ha/HaPlugin.cpp
@@ -31,12 +31,20 @@ struct Options : public qpid::Options {
Settings& settings;
Options(Settings& s) : qpid::Options("HA Options"), settings(s) {
addOptions()
- ("ha-enable", optValue(settings.enabled, "yes|no"), "Enable High Availability features")
- ("ha-client-url", optValue(settings.clientUrl,"URL"), "URL that clients use to connect and fail over.")
- ("ha-broker-url", optValue(settings.brokerUrl,"URL"), "URL that backup brokers use to connect and fail over.")
- ("ha-username", optValue(settings.username, "USER"), "Username for connections between brokers")
- ("ha-password", optValue(settings.password, "PASS"), "Password for connections between brokers")
- ("ha-mechanism", optValue(settings.mechanism, "MECH"), "Authentication mechanism for connections between brokers")
+ ("ha-cluster", optValue(settings.enabled, "yes|no"),
+ "Join a HA active/passive cluster.")
+ ("ha-brokers", optValue(settings.brokerUrl,"URL"),
+ "URL that backup brokers use to connect and fail over.")
+ ("ha-public-brokers", optValue(settings.clientUrl,"URL"),
+ "URL that clients use to connect and fail over, defaults to ha-brokers.")
+ ("ha-expected-backups", optValue(settings.expectedBackups, "N"),
+ "Number of backups expected to be active in the HA cluster.")
+ ("ha-username", optValue(settings.username, "USER"),
+ "Username for connections between HA brokers")
+ ("ha-password", optValue(settings.password, "PASS"),
+ "Password for connections between HA brokers")
+ ("ha-mechanism", optValue(settings.mechanism, "MECH"),
+ "Authentication mechanism for connections between HA brokers")
;
}
};
@@ -56,6 +64,7 @@ struct HaPlugin : public Plugin {
void initialize(Plugin::Target& target) {
broker::Broker* broker = dynamic_cast<broker::Broker*>(&target);
if (broker && settings.enabled) {
+ QPID_LOG(notice, "HA: Enabled");
haBroker.reset(new ha::HaBroker(*broker, settings));
} else
QPID_LOG(notice, "HA: Disabled");
diff --git a/cpp/src/qpid/ha/QueueReplicator.cpp b/cpp/src/qpid/ha/QueueReplicator.cpp
index 0017cc82cd..7351a8d74d 100644
--- a/cpp/src/qpid/ha/QueueReplicator.cpp
+++ b/cpp/src/qpid/ha/QueueReplicator.cpp
@@ -31,7 +31,6 @@
#include "qpid/framing/FieldTable.h"
#include "qpid/log/Statement.h"
#include <boost/shared_ptr.hpp>
-#include <sstream>
namespace {
const std::string QPID_REPLICATOR_("qpid.replicator-");
@@ -54,9 +53,7 @@ std::string QueueReplicator::replicatorName(const std::string& queueName) {
QueueReplicator::QueueReplicator(boost::shared_ptr<Queue> q, boost::shared_ptr<Link> l)
: Exchange(replicatorName(q->getName()), 0, q->getBroker()), queue(q), link(l)
{
- std::stringstream ss;
- ss << "HA: Backup " << queue->getName() << ": ";
- logPrefix = ss.str();
+ logPrefix = "HA: Backup " + queue->getName() + ": ";
QPID_LOG(info, logPrefix << "Created, settings: " << q->getSettings());
}
@@ -155,9 +152,6 @@ void QueueReplicator::route(Deliverable& msg, const std::string& key, const Fiel
QPID_LOG(trace, logPrefix << "Position moved from " << queue->getPosition()
<< " to " << position);
assert(queue->getPosition() <= position);
- //TODO aconway 2011-12-14: Optimize this?
- for (SequenceNumber i = queue->getPosition(); i < position; ++i)
- dequeue(i,l);
queue->setPosition(position);
} else {
msg.deliverTo(queue);
diff --git a/cpp/src/qpid/ha/ReplicatingSubscription.h b/cpp/src/qpid/ha/ReplicatingSubscription.h
index e311f9505a..cbcb230bc1 100644
--- a/cpp/src/qpid/ha/ReplicatingSubscription.h
+++ b/cpp/src/qpid/ha/ReplicatingSubscription.h
@@ -33,7 +33,7 @@ namespace qpid {
namespace broker {
class Message;
class Queue;
-class QueuedMessage;
+struct QueuedMessage;
class OwnershipToken;
}
diff --git a/cpp/src/qpid/ha/Settings.h b/cpp/src/qpid/ha/Settings.h
index 049c873b9f..52a64c8330 100644
--- a/cpp/src/qpid/ha/Settings.h
+++ b/cpp/src/qpid/ha/Settings.h
@@ -33,10 +33,11 @@ namespace ha {
class Settings
{
public:
- Settings() : enabled(false) {}
+ Settings() : enabled(false), expectedBackups(0) {}
bool enabled;
std::string clientUrl;
std::string brokerUrl;
+ size_t expectedBackups;
std::string username, password, mechanism;
private:
};
diff --git a/cpp/src/qpid/ha/management-schema.xml b/cpp/src/qpid/ha/management-schema.xml
index fe4a14d111..05ed5f02ce 100644
--- a/cpp/src/qpid/ha/management-schema.xml
+++ b/cpp/src/qpid/ha/management-schema.xml
@@ -22,16 +22,30 @@
<!-- Monitor and control HA status of a broker. -->
<class name="HaBroker">
<property name="name" type="sstr" access="RC" index="y" desc="Primary Key"/>
+
<property name="status" type="sstr" desc="HA status: primary or backup"/>
- <property name="clientAddresses" type="sstr" desc="List of addresses used by clients to connect to the HA cluster."/>
- <property name="brokerAddresses" type="sstr" desc="List of addresses used by HA brokers to connect to each other."/>
+
+ <property name="brokers" type="sstr"
+ desc="Multiple-address URL used by HA brokers to connect to each other."/>
+
+ <property name="publicBrokers" type="sstr"
+ desc="Multiple-address URL used by clients to connect to the HA brokers."/>
+
+ <property name="expectedBackups" type="uint16"
+ desc="Number of HA backup brokers expected."/>>
<method name="promote" desc="Promote a backup broker to primary."/>
- <method name="setClientAddresses" desc="Set HA client addresses">
- <arg name="clientAddresses" type="sstr" dir="I"/>
+
+ <method name="setBrokers" desc="Set URL for HA brokers to connect to each other.">
+ <arg name="url" type="sstr" dir="I"/>
+ </method>
+
+ <method name="setPublicBrokers" desc="Set URL for clients to connect to HA brokers">
+ <arg name="url" type="sstr" dir="I"/>
</method>
- <method name="setBrokerAddresses" desc="Set HA broker addresses">
- <arg name="brokerAddresses" type="sstr" dir="I"/>
+
+ <method name="setExpectedBackups" desc="Set number of backups expected">
+ <arg name="expectedBackups" type="uint16" dir="I"/>
</method>
</class>
diff --git a/cpp/include/qpid/sys/MemStat.h b/cpp/src/qpid/sys/MemStat.h
index d855786cd5..d855786cd5 100644
--- a/cpp/include/qpid/sys/MemStat.h
+++ b/cpp/src/qpid/sys/MemStat.h
diff --git a/cpp/src/qpid/sys/Probes.h b/cpp/src/qpid/sys/Probes.h
new file mode 100644
index 0000000000..d30181c357
--- /dev/null
+++ b/cpp/src/qpid/sys/Probes.h
@@ -0,0 +1,65 @@
+#ifndef _sys_Probes
+#define _sys_Probes
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#ifdef HAVE_SYS_SDT_H
+#include <sys/sdt.h>
+#endif
+
+// Pragmatically it seems that Linux and Solaris versions of sdt.h which support
+// user static probes define up to DTRACE_PROBE8, but FreeBSD 8 which doesn't
+// support usdt only defines up to DTRACE_PROBE4 - FreeBSD 9 which does support usdt
+// defines up to DTRACE_PROBE5.
+
+#ifdef DTRACE_PROBE5
+// Versions for Linux Systemtap/Solaris/FreeBSD 9
+#define QPID_PROBE(probe) DTRACE_PROBE(qpid, probe)
+#define QPID_PROBE1(probe, p1) DTRACE_PROBE1(qpid, probe, p1)
+#define QPID_PROBE2(probe, p1, p2) DTRACE_PROBE2(qpid, probe, p1, p2)
+#define QPID_PROBE3(probe, p1, p2, p3) DTRACE_PROBE3(qpid, probe, p1, p2, p3)
+#define QPID_PROBE4(probe, p1, p2, p3, p4) DTRACE_PROBE4(qpid, probe, p1, p2, p3, p4)
+#define QPID_PROBE5(probe, p1, p2, p3, p4, p5) DTRACE_PROBE5(qpid, probe, p1, p2, p3, p4, p5)
+#else
+// FreeBSD 8
+#define QPID_PROBE(probe)
+#define QPID_PROBE1(probe, p1)
+#define QPID_PROBE2(probe, p1, p2)
+#define QPID_PROBE3(probe, p1, p2, p3)
+#define QPID_PROBE4(probe, p1, p2, p3, p4)
+#define QPID_PROBE5(probe, p1, p2, p3, p4, p5)
+#endif
+
+#ifdef DTRACE_PROBE8
+// Versions for Linux Systemtap
+#define QPID_PROBE6(probe, p1, p2, p3, p4, p5, p6) DTRACE_PROBE6(qpid, probe, p1, p2, p3, p4, p5, p6)
+#define QPID_PROBE7(probe, p1, p2, p3, p4, p5, p6, p7) DTRACE_PROBE7(qpid, probe, p1, p2, p3, p4, p5, p6, p7)
+#define QPID_PROBE8(probe, p1, p2, p3, p4, p5, p6, p7, p8) DTRACE_PROBE8(qpid, probe, p1, p2, p3, p4, p5, p6, p7, p8)
+#else
+// Versions for Solaris/FreeBSD
+#define QPID_PROBE6(probe, p1, p2, p3, p4, p5, p6)
+#define QPID_PROBE7(probe, p1, p2, p3, p4, p5, p6, p7)
+#define QPID_PROBE8(probe, p1, p2, p3, p4, p5, p6, p7, p8)
+#endif
+
+#endif // _sys_Probes
diff --git a/cpp/src/qpid/sys/apr/APRBase.cpp b/cpp/src/qpid/sys/apr/APRBase.cpp
deleted file mode 100644
index 8bdba66bdc..0000000000
--- a/cpp/src/qpid/sys/apr/APRBase.cpp
+++ /dev/null
@@ -1,89 +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.
- *
- */
-#include <iostream>
-#include "qpid/log/Statement.h"
-#include "qpid/sys/apr/APRBase.h"
-
-using namespace qpid::sys;
-
-APRBase* APRBase::instance = 0;
-
-APRBase* APRBase::getInstance(){
- if(instance == 0){
- instance = new APRBase();
- }
- return instance;
-}
-
-
-APRBase::APRBase() : count(0){
- apr_initialize();
- CHECK_APR_SUCCESS(apr_pool_create(&pool, 0));
- CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, pool));
-}
-
-APRBase::~APRBase(){
- CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex));
- apr_pool_destroy(pool);
- apr_terminate();
-}
-
-bool APRBase::_increment(){
- bool deleted(false);
- CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex));
- if(this == instance){
- count++;
- }else{
- deleted = true;
- }
- CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex));
- return !deleted;
-}
-
-void APRBase::_decrement(){
- APRBase* copy = 0;
- CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex));
- if(--count == 0){
- copy = instance;
- instance = 0;
- }
- CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex));
- if(copy != 0){
- delete copy;
- }
-}
-
-void APRBase::increment(){
- int count = 0;
- while(count++ < 2 && !getInstance()->_increment())
- QPID_LOG(warning, "APR initialization triggered concurrently with termination.");
-}
-
-void APRBase::decrement(){
- getInstance()->_decrement();
-}
-
-std::string qpid::sys::get_desc(apr_status_t status){
- const int size = 50;
- char tmp[size];
- return std::string(apr_strerror(status, tmp, size));
-}
-
diff --git a/cpp/src/qpid/sys/apr/APRBase.h b/cpp/src/qpid/sys/apr/APRBase.h
deleted file mode 100644
index 7b5644a129..0000000000
--- a/cpp/src/qpid/sys/apr/APRBase.h
+++ /dev/null
@@ -1,74 +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.
- *
- */
-#ifndef _APRBase_
-#define _APRBase_
-
-#include <string>
-#include <apr_thread_mutex.h>
-#include <apr_errno.h>
-
-namespace qpid {
-namespace sys {
-
- /**
- * Use of APR libraries necessitates explicit init and terminate
- * calls. Any class using APR libs should obtain the reference to
- * this singleton and increment on construction, decrement on
- * destruction. This class can then correctly initialise apr
- * before the first use and terminate after the last use.
- */
- class APRBase{
- static APRBase* instance;
- apr_pool_t* pool;
- apr_thread_mutex_t* mutex;
- int count;
-
- APRBase();
- ~APRBase();
- static APRBase* getInstance();
- bool _increment();
- void _decrement();
- public:
- static void increment();
- static void decrement();
- };
-
- //this is also a convenient place for a helper function for error checking:
- void check(apr_status_t status, const char* file, const int line);
- std::string get_desc(apr_status_t status);
-
-#define CHECK_APR_SUCCESS(A) qpid::sys::check(A, __FILE__, __LINE__);
-
-}
-}
-
-// Inlined as it is called *a lot*
-void inline qpid::sys::check(apr_status_t status, const char* file, const int line){
- if (status != APR_SUCCESS){
- char tmp[256];
- throw Exception(QPID_MSG(apr_strerror(status, tmp, size)))
- }
-}
-
-
-
-
-#endif
diff --git a/cpp/src/qpid/sys/apr/Condition.h b/cpp/src/qpid/sys/apr/Condition.h
deleted file mode 100644
index 66d465ca75..0000000000
--- a/cpp/src/qpid/sys/apr/Condition.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef _sys_apr_Condition_h
-#define _sys_apr_Condition_h
-
-/*
- *
- * 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.
- *
- */
-
-#include "qpid/sys/apr/APRPool.h"
-#include "qpid/sys/Mutex.h"
-#include "qpid/sys/Time.h"
-
-#include <sys/errno.h>
-#include <boost/noncopyable.hpp>
-#include <apr_thread_cond.h>
-
-namespace qpid {
-namespace sys {
-
-/**
- * A condition variable for thread synchronization.
- */
-class Condition
-{
- public:
- inline Condition();
- inline ~Condition();
- inline void wait(Mutex&);
- inline bool wait(Mutex&, const AbsTime& absoluteTime);
- inline void notify();
- inline void notifyAll();
-
- private:
- apr_thread_cond_t* condition;
-};
-
-
-Condition::Condition() {
- CHECK_APR_SUCCESS(apr_thread_cond_create(&condition, APRPool::get()));
-}
-
-Condition::~Condition() {
- CHECK_APR_SUCCESS(apr_thread_cond_destroy(condition));
-}
-
-void Condition::wait(Mutex& mutex) {
- CHECK_APR_SUCCESS(apr_thread_cond_wait(condition, mutex.mutex));
-}
-
-bool Condition::wait(Mutex& mutex, const AbsTime& absoluteTime){
- // APR uses microseconds.
- apr_status_t status =
- apr_thread_cond_timedwait(
- condition, mutex.mutex, Duration(now(), absoluteTime)/TIME_USEC);
- if(status != APR_TIMEUP) CHECK_APR_SUCCESS(status);
- return status == 0;
-}
-
-void Condition::notify(){
- CHECK_APR_SUCCESS(apr_thread_cond_signal(condition));
-}
-
-void Condition::notifyAll(){
- CHECK_APR_SUCCESS(apr_thread_cond_broadcast(condition));
-}
-
-}}
-#endif /*!_sys_apr_Condition_h*/
diff --git a/cpp/src/qpid/sys/apr/Mutex.h b/cpp/src/qpid/sys/apr/Mutex.h
deleted file mode 100644
index cb75f5b339..0000000000
--- a/cpp/src/qpid/sys/apr/Mutex.h
+++ /dev/null
@@ -1,124 +0,0 @@
-#ifndef _sys_apr_Mutex_h
-#define _sys_apr_Mutex_h
-
-/*
- *
- * 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.
- *
- */
-
-#include "qpid/sys/apr/APRBase.h"
-#include "qpid/sys/apr/APRPool.h"
-
-#include <boost/noncopyable.hpp>
-#include <apr_thread_mutex.h>
-
-namespace qpid {
-namespace sys {
-
-class Condition;
-
-/**
- * Mutex lock.
- */
-class Mutex : private boost::noncopyable {
- public:
- typedef ScopedLock<Mutex> ScopedLock;
- typedef ScopedUnlock<Mutex> ScopedUnlock;
-
- inline Mutex();
- inline ~Mutex();
- inline void lock();
- inline void unlock();
- inline bool trylock();
-
- protected:
- apr_thread_mutex_t* mutex;
- friend class Condition;
-};
-
-Mutex::Mutex() {
- CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, APRPool::get()));
-}
-
-Mutex::~Mutex(){
- CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex));
-}
-
-void Mutex::lock() {
- CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex));
-}
-void Mutex::unlock() {
- CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex));
-}
-
-bool Mutex::trylock() {
- return apr_thread_mutex_trylock(mutex) == 0;
-}
-
-
-/**
- * RW lock.
- */
-class RWlock : private boost::noncopyable {
- friend class Condition;
-
-public:
- typedef ScopedRlock<RWlock> ScopedRlock;
- typedef ScopedWlock<RWlock> ScopedWlock;
-
- inline RWlock();
- inline ~RWlock();
- inline void wlock(); // will write-lock
- inline void rlock(); // will read-lock
- inline void unlock();
- inline bool trywlock(); // will write-try
- inline bool tryrlock(); // will read-try
-
- protected:
- apr_thread_mutex_t* mutex;
-};
-
-RWlock::RWlock() {
- CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, APRPool::get()));
-}
-
-RWlock::~RWlock(){
- CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex));
-}
-
-void RWlock::wlock() {
- CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex));
-}
-
-void RWlock::rlock() {
- CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex));
-}
-
-void RWlock::unlock() {
- CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex));
-}
-
-bool RWlock::trywlock() {
- return apr_thread_mutex_trylock(mutex) == 0;
-}
-
-bool RWlock::tryrlock() {
- return apr_thread_mutex_trylock(mutex) == 0;
-}
-
-
-}}
-#endif /*!_sys_apr_Mutex_h*/
diff --git a/cpp/src/qpid/sys/apr/Shlib.cpp b/cpp/src/qpid/sys/apr/Shlib.cpp
deleted file mode 100644
index b7ee13a03b..0000000000
--- a/cpp/src/qpid/sys/apr/Shlib.cpp
+++ /dev/null
@@ -1,49 +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.
- *
- */
-
-#include "qpid/sys/Shlib.h"
-#include "qpid/sys/apr/APRBase.h"
-#include "qpid/sys/apr/APRPool.h"
-#include <apr_dso.h>
-
-namespace qpid {
-namespace sys {
-
-void Shlib::load(const char* libname) {
- apr_dso_handle_t* aprHandle;
- CHECK_APR_SUCCESS(
- apr_dso_load(&aprHandle, libname, APRPool::get()));
- handle=aprHandle;
-}
-
-void Shlib::unload() {
- CHECK_APR_SUCCESS(
- apr_dso_unload(static_cast<apr_dso_handle_t*>(handle)));
-}
-
-void* Shlib::getSymbol(const char* name) {
- apr_dso_handle_sym_t symbol;
- CHECK_APR_SUCCESS(apr_dso_sym(&symbol,
- static_cast<apr_dso_handle_t*>(handle),
- name));
- return (void*) symbol;
-}
-
-}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/apr/Socket.cpp b/cpp/src/qpid/sys/apr/Socket.cpp
deleted file mode 100644
index d9024d11c1..0000000000
--- a/cpp/src/qpid/sys/apr/Socket.cpp
+++ /dev/null
@@ -1,114 +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.
- *
- */
-
-
-#include "qpid/sys/Socket.h"
-
-#include "qpid/sys/apr/APRBase.h"
-#include "qpid/sys/apr/APRPool.h"
-
-#include <apr_network_io.h>
-
-namespace qpid {
-namespace sys {
-
-class SocketPrivate {
-public:
- SocketPrivate(apr_socket_t* s = 0) :
- socket(s)
- {}
-
- apr_socket_t* socket;
-};
-
-Socket::Socket() :
- impl(new SocketPrivate)
-{
- createTcp();
-}
-
-Socket::Socket(SocketPrivate* sp) :
- impl(sp)
-{}
-
-Socket::~Socket() {
- delete impl;
-}
-
-void Socket::createTcp() const {
- apr_socket_t*& socket = impl->socket;
- apr_socket_t* s;
- CHECK_APR_SUCCESS(
- apr_socket_create(
- &s, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
- APRPool::get()));
- socket = s;
-}
-
-void Socket::setTimeout(const Duration& interval) const {
- apr_socket_t*& socket = impl->socket;
- apr_socket_timeout_set(socket, interval/TIME_USEC);
-}
-
-void Socket::connect(const std::string& host, int port) const {
- apr_socket_t*& socket = impl->socket;
- apr_sockaddr_t* address;
- CHECK_APR_SUCCESS(
- apr_sockaddr_info_get(
- &address, host.c_str(), APR_UNSPEC, port, APR_IPV4_ADDR_OK,
- APRPool::get()));
- CHECK_APR_SUCCESS(apr_socket_connect(socket, address));
-}
-
-void Socket::close() const {
- apr_socket_t*& socket = impl->socket;
- if (socket == 0) return;
- CHECK_APR_SUCCESS(apr_socket_close(socket));
- socket = 0;
-}
-
-ssize_t Socket::send(const void* data, size_t size) const
-{
- apr_socket_t*& socket = impl->socket;
- apr_size_t sent = size;
- apr_status_t status =
- apr_socket_send(socket, reinterpret_cast<const char*>(data), &sent);
- if (APR_STATUS_IS_TIMEUP(status)) return SOCKET_TIMEOUT;
- if (APR_STATUS_IS_EOF(status)) return SOCKET_EOF;
- CHECK_APR_SUCCESS(status);
- return sent;
-}
-
-ssize_t Socket::recv(void* data, size_t size) const
-{
- apr_socket_t*& socket = impl->socket;
- apr_size_t received = size;
- apr_status_t status =
- apr_socket_recv(socket, reinterpret_cast<char*>(data), &received);
- if (APR_STATUS_IS_TIMEUP(status))
- return SOCKET_TIMEOUT;
- if (APR_STATUS_IS_EOF(status))
- return SOCKET_EOF;
- CHECK_APR_SUCCESS(status);
- return received;
-}
-
-}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/apr/Thread.h b/cpp/src/qpid/sys/apr/Thread.h
deleted file mode 100644
index 6cc63db5c9..0000000000
--- a/cpp/src/qpid/sys/apr/Thread.h
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef _sys_apr_Thread_h
-#define _sys_apr_Thread_h
-
-/*
- *
- * 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.
- *
- */
-
-#include "qpid/sys/apr/APRPool.h"
-#include "qpid/sys/apr/APRBase.h"
-
-#include <apr_thread_proc.h>
-#include <apr_portable.h>
-
-namespace qpid {
-namespace sys {
-
-class Runnable;
-
-class Thread
-{
- public:
- inline static Thread current();
-
- /** ID of current thread for logging.
- * Workaround for broken Thread::current() in APR
- */
- inline static long logId();
-
- inline static void yield();
-
- inline Thread();
- inline explicit Thread(qpid::sys::Runnable*);
- inline explicit Thread(qpid::sys::Runnable&);
-
- inline void join();
-
- inline long id();
-
- private:
- static void* APR_THREAD_FUNC runRunnable(apr_thread_t* thread, void *data);
- inline Thread(apr_thread_t* t);
- apr_thread_t* thread;
-};
-
-Thread::Thread() : thread(0) {}
-
-Thread::Thread(Runnable* runnable) {
- CHECK_APR_SUCCESS(
- apr_thread_create(&thread, 0, runRunnable, runnable, APRPool::get()));
-}
-
-Thread::Thread(Runnable& runnable) {
- CHECK_APR_SUCCESS(
- apr_thread_create(&thread, 0, runRunnable, &runnable, APRPool::get()));
-}
-
-void Thread::join(){
- apr_status_t status;
- if (thread != 0)
- CHECK_APR_SUCCESS(apr_thread_join(&status, thread));
-}
-
-long Thread::id() {
- return long(thread);
-}
-
-/** ID of current thread for logging.
- * Workaround for broken Thread::current() in APR
- */
-long Thread::logId() {
- return static_cast<long>(apr_os_thread_current());
-}
-
-Thread::Thread(apr_thread_t* t) : thread(t) {}
-
-Thread Thread::current(){
- apr_thread_t* thr;
- apr_os_thread_t osthr = apr_os_thread_current();
- CHECK_APR_SUCCESS(apr_os_thread_put(&thr, &osthr, APRPool::get()));
- return Thread(thr);
-}
-
-void Thread::yield()
-{
- apr_thread_yield();
-}
-
-}}
-#endif /*!_sys_apr_Thread_h*/
diff --git a/cpp/src/qpid/sys/posix/AsynchIO.cpp b/cpp/src/qpid/sys/posix/AsynchIO.cpp
index a1c161b596..c25159985e 100644
--- a/cpp/src/qpid/sys/posix/AsynchIO.cpp
+++ b/cpp/src/qpid/sys/posix/AsynchIO.cpp
@@ -23,6 +23,7 @@
#include "qpid/sys/Socket.h"
#include "qpid/sys/SocketAddress.h"
#include "qpid/sys/Poller.h"
+#include "qpid/sys/Probes.h"
#include "qpid/sys/DispatchHandle.h"
#include "qpid/sys/Time.h"
#include "qpid/log/Statement.h"
@@ -423,9 +424,12 @@ AsynchIO::BufferBase* AsynchIO::getQueuedBuffer() {
void AsynchIO::readable(DispatchHandle& h) {
if (readingStopped) {
// We have been flow controlled.
+ QPID_PROBE1(asynchio_read_flowcontrolled, &h);
return;
}
AbsTime readStartTime = AbsTime::now();
+ size_t total = 0;
+ int readCalls = 0;
do {
// (Try to) get a buffer
if (!bufferQueue.empty()) {
@@ -436,23 +440,29 @@ void AsynchIO::readable(DispatchHandle& h) {
errno = 0;
int readCount = buff->byteCount-buff->dataCount;
int rc = socket.read(buff->bytes + buff->dataCount, readCount);
+ int64_t duration = Duration(readStartTime, AbsTime::now());
+ ++readCalls;
if (rc > 0) {
buff->dataCount += rc;
threadReadTotal += rc;
+ total += rc;
readCallback(*this, buff);
if (readingStopped) {
// We have been flow controlled.
+ QPID_PROBE4(asynchio_read_finished_flowcontrolled, &h, duration, total, readCalls);
break;
}
if (rc != readCount) {
// If we didn't fill the read buffer then time to stop reading
+ QPID_PROBE4(asynchio_read_finished_done, &h, duration, total, readCalls);
break;
}
// Stop reading if we've overrun our timeslot
- if (Duration(readStartTime, AbsTime::now()) > threadMaxIoTimeNs) {
+ if ( duration > threadMaxIoTimeNs) {
+ QPID_PROBE4(asynchio_read_finished_maxtime, &h, duration, total, readCalls);
break;
}
@@ -461,6 +471,7 @@ void AsynchIO::readable(DispatchHandle& h) {
bufferQueue.push_front(buff);
assert(buff);
+ QPID_PROBE5(asynchio_read_finished_error, &h, duration, total, readCalls, errno);
// Eof or other side has gone away
if (rc == 0 || errno == ECONNRESET) {
eofCallback(*this);
@@ -486,6 +497,7 @@ void AsynchIO::readable(DispatchHandle& h) {
// If we still have no buffers we can't do anything more
if (bufferQueue.empty()) {
h.unwatchRead();
+ QPID_PROBE4(asynchio_read_finished_nobuffers, &h, Duration(readStartTime, AbsTime::now()), total, readCalls);
break;
}
@@ -501,6 +513,8 @@ void AsynchIO::readable(DispatchHandle& h) {
*/
void AsynchIO::writeable(DispatchHandle& h) {
AbsTime writeStartTime = AbsTime::now();
+ size_t total = 0;
+ int writeCalls = 0;
do {
// See if we've got something to write
if (!writeQueue.empty()) {
@@ -510,14 +524,18 @@ void AsynchIO::writeable(DispatchHandle& h) {
errno = 0;
assert(buff->dataStart+buff->dataCount <= buff->byteCount);
int rc = socket.write(buff->bytes+buff->dataStart, buff->dataCount);
+ int64_t duration = Duration(writeStartTime, AbsTime::now());
+ ++writeCalls;
if (rc >= 0) {
threadWriteTotal += rc;
+ total += rc;
// If we didn't write full buffer put rest back
if (rc != buff->dataCount) {
buff->dataStart += rc;
buff->dataCount -= rc;
writeQueue.push_back(buff);
+ QPID_PROBE4(asynchio_write_finished_done, &h, duration, total, writeCalls);
break;
}
@@ -525,12 +543,15 @@ void AsynchIO::writeable(DispatchHandle& h) {
queueReadBuffer(buff);
// Stop writing if we've overrun our timeslot
- if (Duration(writeStartTime, AbsTime::now()) > threadMaxIoTimeNs) {
+ if (duration > threadMaxIoTimeNs) {
+ QPID_PROBE4(asynchio_write_finished_maxtime, &h, duration, total, writeCalls);
break;
}
} else {
// Put buffer back
writeQueue.push_back(buff);
+ QPID_PROBE5(asynchio_write_finished_error, &h, duration, total, writeCalls, errno);
+
if (errno == ECONNRESET || errno == EPIPE) {
// Just stop watching for write here - we'll get a
// disconnect callback soon enough
@@ -548,9 +569,13 @@ void AsynchIO::writeable(DispatchHandle& h) {
}
}
} else {
+ int64_t duration = Duration(writeStartTime, AbsTime::now());
+ (void) duration; // force duration to be used if no probes are compiled
+
// If we're waiting to close the socket then can do it now as there is nothing to write
if (queuedClose) {
close(h);
+ QPID_PROBE4(asynchio_write_finished_closed, &h, duration, total, writeCalls);
break;
}
// Fd is writable, but nothing to write
@@ -567,6 +592,7 @@ void AsynchIO::writeable(DispatchHandle& h) {
// desired rewatchWrite so we correct that here
if (writePending)
h.rewatchWrite();
+ QPID_PROBE4(asynchio_write_finished_nodata, &h, duration, total, writeCalls);
break;
}
}
diff --git a/cpp/src/tests/CMakeLists.txt b/cpp/src/tests/CMakeLists.txt
index 75ecffe866..79c82106cb 100644
--- a/cpp/src/tests/CMakeLists.txt
+++ b/cpp/src/tests/CMakeLists.txt
@@ -34,8 +34,14 @@ set (abs_builddir ${CMAKE_CURRENT_BINARY_DIR})
set (abs_top_srcdir ${CMAKE_SOURCE_DIR})
set (abs_top_builddir ${CMAKE_BINARY_DIR})
set (builddir_lib_suffix "")
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/test_env.sh.in
- ${CMAKE_CURRENT_BINARY_DIR}/test_env.sh)
+
+if (CMAKE_SYSTEM_NAME STREQUAL Windows)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/test_env.ps1.in
+ ${CMAKE_CURRENT_BINARY_DIR}/test_env.ps1)
+else (CMAKE_SYSTEM_NAME STREQUAL Windows)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/test_env.sh.in
+ ${CMAKE_CURRENT_BINARY_DIR}/test_env.sh)
+endif (CMAKE_SYSTEM_NAME STREQUAL Windows)
# If valgrind is selected in the configuration step, set up the path to it
diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am
index 325019fb22..a7f3bc1fbd 100644
--- a/cpp/src/tests/Makefile.am
+++ b/cpp/src/tests/Makefile.am
@@ -351,7 +351,8 @@ EXTRA_DIST += \
topictest.ps1 \
run_queue_flow_limit_tests \
run_msg_group_tests \
- ipv6_test
+ ipv6_test \
+ ha_tests.py
check_LTLIBRARIES += libdlclose_noop.la
libdlclose_noop_la_LDFLAGS = -module -rpath $(abs_builddir)
diff --git a/cpp/src/tests/acl.py b/cpp/src/tests/acl.py
index 5db3bfe85a..5cc3b9c917 100755
--- a/cpp/src/tests/acl.py
+++ b/cpp/src/tests/acl.py
@@ -48,8 +48,12 @@ class ACLTests(TestBase010):
return connection.session(str(uuid4()))
def reload_acl(self):
- acl = self.qmf.getObjects(_class="acl")[0]
- return acl.reloadACLFile()
+ result = None
+ try:
+ self.broker_access.reloadAclFile()
+ except Exception, e:
+ result = str(e)
+ return result
def get_acl_file(self):
return ACLFile(self.config.defines.get("policy-file", "data_dir/policy.acl"))
@@ -59,7 +63,7 @@ class ACLTests(TestBase010):
aclf.write('acl allow all all\n')
aclf.close()
TestBase010.setUp(self)
- self.startQmf()
+ self.startBrokerAccess()
self.reload_acl()
def tearDown(self):
@@ -84,7 +88,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -111,7 +115,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -168,7 +172,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("Insufficient tokens for acl definition",0,len(result.text)) == -1):
+ if (result.find("Insufficient tokens for acl definition",0,len(result)) == -1):
self.fail("ACL Reader should reject the acl file due to empty group name")
def test_illegal_acl_formats(self):
@@ -181,7 +185,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("Unknown ACL permission",0,len(result.text)) == -1):
+ if (result.find("Unknown ACL permission",0,len(result)) == -1):
self.fail(result)
def test_illegal_extension_lines(self):
@@ -197,10 +201,10 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("contains an illegal extension",0,len(result.text)) == -1):
+ if (result.find("contains an illegal extension",0,len(result)) == -1):
self.fail(result)
- if (result.text.find("Non-continuation line must start with \"group\" or \"acl\"",0,len(result.text)) == -1):
+ if (result.find("Non-continuation line must start with \"group\" or \"acl\"",0,len(result)) == -1):
self.fail(result)
def test_illegal_extension_lines(self):
@@ -216,7 +220,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("ACL format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
def test_user_realm(self):
@@ -231,7 +235,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("Username 'bob' must contain a realm",0,len(result.text)) == -1):
+ if (result.find("Username 'bob' must contain a realm",0,len(result)) == -1):
self.fail(result)
def test_allowed_chars_for_username(self):
@@ -247,7 +251,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("ACL format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
aclf = self.get_acl_file()
@@ -256,7 +260,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("Username \"joe$H@EXAMPLE.com\" contains illegal characters",0,len(result.text)) == -1):
+ if (result.find("Username \"joe$H@EXAMPLE.com\" contains illegal characters",0,len(result)) == -1):
self.fail(result)
#=====================================
@@ -276,7 +280,7 @@ class ACLTests(TestBase010):
result = self.reload_acl()
expected = "ding is not a valid value for 'policytype', possible values are one of" \
" { 'ring' 'ring_strict' 'flow_to_disk' 'reject' }";
- if (result.text != expected):
+ if (result.find(expected) == -1):
self.fail(result)
def test_illegal_queuemaxsize_upper_limit_spec(self):
@@ -294,7 +298,7 @@ class ACLTests(TestBase010):
result = self.reload_acl()
expected = "-1 is not a valid value for 'queuemaxsizeupperlimit', " \
"values should be between 0 and 9223372036854775807";
- if (result.text != expected):
+ if (result.find(expected) == -1):
self.fail(result)
aclf = self.get_acl_file()
@@ -305,7 +309,7 @@ class ACLTests(TestBase010):
result = self.reload_acl()
expected = "9223372036854775808 is not a valid value for 'queuemaxsizeupperlimit', " \
"values should be between 0 and 9223372036854775807";
- if (result.text != expected):
+ if (result.find(expected) == -1):
self.fail(result)
#
@@ -351,7 +355,7 @@ class ACLTests(TestBase010):
result = self.reload_acl()
expected = "-1 is not a valid value for 'queuemaxcountupperlimit', " \
"values should be between 0 and 9223372036854775807";
- if (result.text != expected):
+ if (result.find(expected) == -1):
self.fail(result)
aclf = self.get_acl_file()
@@ -362,7 +366,7 @@ class ACLTests(TestBase010):
result = self.reload_acl()
expected = "9223372036854775808 is not a valid value for 'queuemaxcountupperlimit', " \
"values should be between 0 and 9223372036854775807";
- if (result.text != expected):
+ if (result.find(expected) == -1):
self.fail(result)
#
@@ -466,7 +470,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -573,7 +577,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -742,7 +746,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -873,7 +877,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -991,7 +995,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
bob = BrokerAdmin(self.config.broker, "bob", "bob")
@@ -1030,7 +1034,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -1078,7 +1082,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -1123,7 +1127,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -1174,7 +1178,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
session = self.get_session('bob','bob')
@@ -1242,7 +1246,7 @@ class ACLTests(TestBase010):
aclf.close()
result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
+ if (result):
self.fail(result)
ts = None
diff --git a/cpp/src/tests/cli_tests.py b/cpp/src/tests/cli_tests.py
index 6c75927461..b9a7dda15c 100755
--- a/cpp/src/tests/cli_tests.py
+++ b/cpp/src/tests/cli_tests.py
@@ -22,7 +22,6 @@ import sys
import os
import imp
from qpid.testlib import TestBase010
-# from brokertest import import_script, checkenv
from qpid.datatypes import Message
from qpid.queue import Empty
from time import sleep
@@ -61,14 +60,13 @@ class CliTests(TestBase010):
ret = os.system(self.qpid_config_command(" add queue " + qname + " " + arguments))
self.assertEqual(ret, 0)
- queues = self.qmf.getObjects(_class="queue")
- for queue in queues:
- if queue.name == qname:
- return queue
+ queue = self.broker_access.getQueue(qname)
+ if queue:
+ return queue
assert False
def test_queue_params(self):
- self.startQmf()
+ self.startBrokerAccess()
queue1 = self.makeQueue("test_queue_params1", "--limit-policy none")
queue2 = self.makeQueue("test_queue_params2", "--limit-policy reject")
queue3 = self.makeQueue("test_queue_params3", "--limit-policy flow-to-disk")
@@ -82,29 +80,21 @@ class CliTests(TestBase010):
self.assertEqual(queue4.arguments[LIMIT], "ring")
self.assertEqual(queue5.arguments[LIMIT], "ring_strict")
- queue6 = self.makeQueue("test_queue_params6", "--order fifo")
- queue7 = self.makeQueue("test_queue_params7", "--order lvq")
- queue8 = self.makeQueue("test_queue_params8", "--order lvq-no-browse")
-
- LVQ = "qpid.last_value_queue"
- LVQNB = "qpid.last_value_queue_no_browse"
+ queue6 = self.makeQueue("test_queue_params6", "--lvq-key lkey")
- assert LVQ not in queue6.arguments
- assert LVQ in queue7.arguments
- assert LVQ not in queue8.arguments
-
- assert LVQNB not in queue6.arguments
- assert LVQNB not in queue7.arguments
- assert LVQNB in queue8.arguments
+ LVQKEY = "qpid.last_value_queue_key"
+ assert LVQKEY not in queue5.arguments
+ assert LVQKEY in queue6.arguments
+ assert queue6.arguments[LVQKEY] == "lkey"
def test_queue_params_api(self):
- self.startQmf()
- queue1 = self.makeQueue("test_queue_params1", "--limit-policy none", True)
- queue2 = self.makeQueue("test_queue_params2", "--limit-policy reject", True)
- queue3 = self.makeQueue("test_queue_params3", "--limit-policy flow-to-disk", True)
- queue4 = self.makeQueue("test_queue_params4", "--limit-policy ring", True)
- queue5 = self.makeQueue("test_queue_params5", "--limit-policy ring-strict", True)
+ self.startBrokerAccess()
+ queue1 = self.makeQueue("test_queue_params_api1", "--limit-policy none", True)
+ queue2 = self.makeQueue("test_queue_params_api2", "--limit-policy reject", True)
+ queue3 = self.makeQueue("test_queue_params_api3", "--limit-policy flow-to-disk", True)
+ queue4 = self.makeQueue("test_queue_params_api4", "--limit-policy ring", True)
+ queue5 = self.makeQueue("test_queue_params_api5", "--limit-policy ring-strict", True)
LIMIT = "qpid.policy_type"
assert LIMIT not in queue1.arguments
@@ -113,30 +103,22 @@ class CliTests(TestBase010):
self.assertEqual(queue4.arguments[LIMIT], "ring")
self.assertEqual(queue5.arguments[LIMIT], "ring_strict")
- queue6 = self.makeQueue("test_queue_params6", "--order fifo", True)
- queue7 = self.makeQueue("test_queue_params7", "--order lvq", True)
- queue8 = self.makeQueue("test_queue_params8", "--order lvq-no-browse", True)
-
- LVQ = "qpid.last_value_queue"
- LVQNB = "qpid.last_value_queue_no_browse"
+ queue6 = self.makeQueue("test_queue_params_api6", "--lvq-key lkey")
- assert LVQ not in queue6.arguments
- assert LVQ in queue7.arguments
- assert LVQ not in queue8.arguments
+ LVQKEY = "qpid.last_value_queue_key"
- assert LVQNB not in queue6.arguments
- assert LVQNB not in queue7.arguments
- assert LVQNB in queue8.arguments
+ assert LVQKEY not in queue5.arguments
+ assert LVQKEY in queue6.arguments
+ assert queue6.arguments[LVQKEY] == "lkey"
def test_qpid_config(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
qname = "test_qpid_config"
ret = os.system(self.qpid_config_command(" add queue " + qname))
self.assertEqual(ret, 0)
- queues = qmf.getObjects(_class="queue")
+ queues = self.broker_access.getAllQueues()
found = False
for queue in queues:
if queue.name == qname:
@@ -146,7 +128,7 @@ class CliTests(TestBase010):
ret = os.system(self.qpid_config_command(" del queue " + qname))
self.assertEqual(ret, 0)
- queues = qmf.getObjects(_class="queue")
+ queues = self.broker_access.getAllQueues()
found = False
for queue in queues:
if queue.name == qname:
@@ -154,13 +136,12 @@ class CliTests(TestBase010):
self.assertEqual(found, False)
def test_qpid_config_api(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
qname = "test_qpid_config_api"
ret = self.qpid_config_api(" add queue " + qname)
self.assertEqual(ret, 0)
- queues = qmf.getObjects(_class="queue")
+ queues = self.broker_access.getAllQueues()
found = False
for queue in queues:
if queue.name == qname:
@@ -170,7 +151,7 @@ class CliTests(TestBase010):
ret = self.qpid_config_api(" del queue " + qname)
self.assertEqual(ret, 0)
- queues = qmf.getObjects(_class="queue")
+ queues = self.broker_access.getAllQueues()
found = False
for queue in queues:
if queue.name == qname:
@@ -179,25 +160,23 @@ class CliTests(TestBase010):
def test_qpid_config_sasl_plain_expect_succeed(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
qname = "test_qpid_config_sasl_plain_expect_succeed"
- cmd = " --sasl-mechanism PLAIN -a guest/guest@localhost:"+str(self.broker.port) + " add queue " + qname
+ cmd = " --sasl-mechanism PLAIN -b guest/guest@localhost:"+str(self.broker.port) + " add queue " + qname
ret = self.qpid_config_api(cmd)
self.assertEqual(ret, 0)
def test_qpid_config_sasl_plain_expect_fail(self):
"""Fails because no user name and password is supplied"""
- self.startQmf();
- qmf = self.qmf
- qname = "test_qpid_config_sasl_plain_expect_succeed"
- cmd = " --sasl-mechanism PLAIN -a localhost:"+str(self.broker.port) + " add queue " + qname
+ self.startBrokerAccess();
+ qname = "test_qpid_config_sasl_plain_expect_fail"
+ cmd = " --sasl-mechanism PLAIN -b localhost:"+str(self.broker.port) + " add queue " + qname
ret = self.qpid_config_api(cmd)
assert ret != 0
# helpers for some of the test methods
def helper_find_exchange(self, xchgname, typ, expected=True):
- xchgs = self.qmf.getObjects(_class = "exchange")
+ xchgs = self.broker_access.getAllExchanges()
found = False
for xchg in xchgs:
if xchg.name == xchgname:
@@ -221,7 +200,7 @@ class CliTests(TestBase010):
self.helper_find_exchange(xchgname, False, expected=False)
def helper_find_queue(self, qname, expected=True):
- queues = self.qmf.getObjects(_class="queue")
+ queues = self.broker_access.getAllQueues()
found = False
for queue in queues:
if queue.name == qname:
@@ -246,8 +225,7 @@ class CliTests(TestBase010):
# test the bind-queue-to-header-exchange functionality
def test_qpid_config_headers(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
qname = "test_qpid_config"
xchgname = "test_xchg"
@@ -277,8 +255,7 @@ class CliTests(TestBase010):
def test_qpid_config_xml(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
qname = "test_qpid_config"
xchgname = "test_xchg"
@@ -306,13 +283,12 @@ class CliTests(TestBase010):
self.helper_destroy_exchange(xchgname)
def test_qpid_config_durable(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
qname = "test_qpid_config"
ret = os.system(self.qpid_config_command(" add queue --durable " + qname))
self.assertEqual(ret, 0)
- queues = qmf.getObjects(_class="queue")
+ queues = self.broker_access.getAllQueues()
found = False
for queue in queues:
if queue.name == qname:
@@ -322,7 +298,7 @@ class CliTests(TestBase010):
ret = os.system(self.qpid_config_command(" del queue " + qname))
self.assertEqual(ret, 0)
- queues = qmf.getObjects(_class="queue")
+ queues = self.broker_access.getAllQueues()
found = False
for queue in queues:
if queue.name == qname:
@@ -330,8 +306,7 @@ class CliTests(TestBase010):
self.assertEqual(found, False)
def test_qpid_config_altex(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
exName = "testalt"
qName = "testqalt"
altName = "amq.direct"
@@ -339,7 +314,7 @@ class CliTests(TestBase010):
ret = os.system(self.qpid_config_command(" add exchange topic %s --alternate-exchange=%s" % (exName, altName)))
self.assertEqual(ret, 0)
- exchanges = qmf.getObjects(_class="exchange")
+ exchanges = self.broker_access.getAllExchanges()
found = False
for exchange in exchanges:
if exchange.name == altName:
@@ -349,20 +324,20 @@ class CliTests(TestBase010):
found = True
if not exchange.altExchange:
self.fail("Alternate exchange not set")
- self.assertEqual(exchange._altExchange_.name, altName)
+ self.assertEqual(exchange.altExchange, altName)
self.assertEqual(found, True)
ret = os.system(self.qpid_config_command(" add queue %s --alternate-exchange=%s" % (qName, altName)))
self.assertEqual(ret, 0)
- queues = qmf.getObjects(_class="queue")
+ queues = self.broker_access.getAllQueues()
found = False
for queue in queues:
if queue.name == qName:
found = True
if not queue.altExchange:
self.fail("Alternate exchange not set")
- self.assertEqual(queue._altExchange_.name, altName)
+ self.assertEqual(queue.altExchange, altName)
self.assertEqual(found, True)
def test_qpid_config_list_queues_arguments(self):
@@ -371,8 +346,7 @@ class CliTests(TestBase010):
actually a string (though still a valid value), it does not
upset qpid-config
"""
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
names = ["queue_capacity%s" % (i) for i in range(1, 6)]
for name in names:
@@ -386,15 +360,14 @@ class CliTests(TestBase010):
assert name in queues, "%s not in %s" % (name, queues)
def test_qpid_route(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
command = self.cli_dir() + "/qpid-route dynamic add guest/guest@localhost:%d %s:%d amq.topic" %\
(self.broker.port, self.remote_host(), self.remote_port())
ret = os.system(command)
self.assertEqual(ret, 0)
- links = qmf.getObjects(_class="link")
+ links = self.broker_access.getAllLinks()
found = False
for link in links:
if link.port == self.remote_port():
@@ -402,8 +375,7 @@ class CliTests(TestBase010):
self.assertEqual(found, True)
def test_qpid_route_api(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
ret = self.qpid_route_api("dynamic add "
+ "guest/guest@localhost:"+str(self.broker.port) + " "
@@ -412,7 +384,7 @@ class CliTests(TestBase010):
self.assertEqual(ret, 0)
- links = qmf.getObjects(_class="link")
+ links = self.broker_access.getAllLinks()
found = False
for link in links:
if link.port == self.remote_port():
@@ -421,8 +393,7 @@ class CliTests(TestBase010):
def test_qpid_route_api(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
ret = self.qpid_route_api("dynamic add "
+ " --client-sasl-mechanism PLAIN "
@@ -432,7 +403,7 @@ class CliTests(TestBase010):
self.assertEqual(ret, 0)
- links = qmf.getObjects(_class="link")
+ links = self.broker_access.getAllLinks()
found = False
for link in links:
if link.port == self.remote_port():
@@ -440,8 +411,7 @@ class CliTests(TestBase010):
self.assertEqual(found, True)
def test_qpid_route_api_expect_fail(self):
- self.startQmf();
- qmf = self.qmf
+ self.startBrokerAccess();
ret = self.qpid_route_api("dynamic add "
+ " --client-sasl-mechanism PLAIN "
@@ -463,11 +433,11 @@ class CliTests(TestBase010):
return None
def qpid_config_command(self, arg = ""):
- return self.cli_dir() + "/qpid-config -a localhost:%d" % self.broker.port + " " + arg
+ return self.cli_dir() + "/qpid-config -b localhost:%d" % self.broker.port + " " + arg
def qpid_config_api(self, arg = ""):
script = import_script(checkenv("QPID_CONFIG_EXEC"))
- broker = ["-a", "localhost:"+str(self.broker.port)]
+ broker = ["-b", "localhost:"+str(self.broker.port)]
return script.main(broker + arg.split())
def qpid_route_api(self, arg = ""):
diff --git a/cpp/src/tests/cluster_tests.py b/cpp/src/tests/cluster_tests.py
index cbc3df4a6b..79df21aada 100755
--- a/cpp/src/tests/cluster_tests.py
+++ b/cpp/src/tests/cluster_tests.py
@@ -277,7 +277,7 @@ acl deny all all
QMF-based tools - regression test for BZ615300."""
broker1 = self.cluster(1)[0]
broker2 = self.cluster(1)[0]
- qs = subprocess.Popen(["qpid-stat", "-e", broker1.host_port()], stdout=subprocess.PIPE)
+ qs = subprocess.Popen(["qpid-stat", "-e", "-b", broker1.host_port()], stdout=subprocess.PIPE)
out = qs.communicate()[0]
assert out.find("amq.failover") > 0
@@ -1160,7 +1160,7 @@ class LongTests(BrokerTest):
def start_mclients(broker):
"""Start management clients that make multiple connections."""
- cmd = ["qpid-stat", "-b", "localhost:%s" %(broker.port())]
+ cmd = ["qpid-cluster", "-C", "localhost:%s" %(broker.port())]
mclients.append(ClientLoop(broker, cmd))
endtime = time.time() + self.duration()
diff --git a/cpp/src/tests/clustered_replication_test b/cpp/src/tests/clustered_replication_test
index 4a57502f39..8c8522c2eb 100755
--- a/cpp/src/tests/clustered_replication_test
+++ b/cpp/src/tests/clustered_replication_test
@@ -65,8 +65,8 @@ if test -d $PYTHON_DIR; then
#start first node of primary cluster and set up test queue
echo Starting primary cluster
PRIMARY1=$(with_ais_group $QPIDD_EXEC $GENERAL_OPTS $PRIMARY_OPTS --log-to-file repl.primary.1.tmp) || fail "Could not start PRIMARY1"
- $PYTHON_COMMANDS/qpid-config -a "localhost:$PRIMARY1" add queue test-queue --generate-queue-events 2
- $PYTHON_COMMANDS/qpid-config -a "localhost:$PRIMARY1" add queue control-queue --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$PRIMARY1" add queue test-queue --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$PRIMARY1" add queue control-queue --generate-queue-events 1
#send 10 messages, consume 5 of them
for i in `seq 1 10`; do echo Message$i; done | ./sender --port $PRIMARY1
@@ -81,9 +81,9 @@ if test -d $PYTHON_DIR; then
DR1=$(with_ais_group $QPIDD_EXEC $GENERAL_OPTS $DR_OPTS --log-to-file repl.dr.1.tmp) || fail "Could not start DR1"
DR2=$(with_ais_group $QPIDD_EXEC $GENERAL_OPTS $DR_OPTS --log-to-file repl.dr.2.tmp) || fail "Could not start DR2"
- $PYTHON_COMMANDS/qpid-config -a "localhost:$DR1" add queue test-queue
- $PYTHON_COMMANDS/qpid-config -a "localhost:$DR1" add queue control-queue
- $PYTHON_COMMANDS/qpid-config -a "localhost:$DR1" add exchange replication REPLICATION_EXCHANGE
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$DR1" add queue test-queue
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$DR1" add queue control-queue
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$DR1" add exchange replication REPLICATION_EXCHANGE
$PYTHON_COMMANDS/qpid-route queue add localhost:$DR2 localhost:$PRIMARY2 REPLICATION_EXCHANGE REPLICATION_QUEUE || fail "Could not add route."
#send more messages to primary
diff --git a/cpp/src/tests/federated_cluster_test b/cpp/src/tests/federated_cluster_test
index b32455259e..50b877e666 100755
--- a/cpp/src/tests/federated_cluster_test
+++ b/cpp/src/tests/federated_cluster_test
@@ -63,20 +63,20 @@ start_brokers() {
setup() {
#create exchange on both cluster and single broker
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add exchange direct test-exchange
- $PYTHON_COMMANDS/qpid-config -a "localhost:$NODE_1" add exchange direct test-exchange
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add exchange direct test-exchange
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$NODE_1" add exchange direct test-exchange
#create dynamic routes for test exchange
$PYTHON_COMMANDS/qpid-route dynamic add "localhost:$NODE_2" "localhost:$BROKER_A" test-exchange
$PYTHON_COMMANDS/qpid-route dynamic add "localhost:$BROKER_A" "localhost:$NODE_2" test-exchange
#create test queue on cluster and bind it to the test exchange
- $PYTHON_COMMANDS/qpid-config -a "localhost:$NODE_1" add queue test-queue
- $PYTHON_COMMANDS/qpid-config -a "localhost:$NODE_1" bind test-exchange test-queue to-cluster
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$NODE_1" add queue test-queue
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$NODE_1" bind test-exchange test-queue to-cluster
#create test queue on single broker and bind it to the test exchange
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue test-queue
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" bind test-exchange test-queue from-cluster
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add queue test-queue
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" bind test-exchange test-queue from-cluster
}
run_test_pull_to_cluster_two_consumers() {
diff --git a/cpp/src/tests/ha_tests.py b/cpp/src/tests/ha_tests.py
index 97de0d1f77..264a636f29 100755
--- a/cpp/src/tests/ha_tests.py
+++ b/cpp/src/tests/ha_tests.py
@@ -18,8 +18,9 @@
# under the License.
#
-import os, signal, sys, time, imp, re, subprocess, glob, random, logging, shutil
+import os, signal, sys, time, imp, re, subprocess, glob, random, logging, shutil, math
from qpid.messaging import Message, NotFound, ConnectionError, Connection
+from qpid.datatypes import uuid4
from brokertest import *
from threading import Thread, Lock, Condition
from logging import getLogger, WARN, ERROR, DEBUG
@@ -33,21 +34,24 @@ class HaBroker(Broker):
args=["--load-module", BrokerTest.ha_lib,
# FIXME aconway 2012-02-13: workaround slow link failover.
"--link-maintenace-interval=0.1",
- "--ha-enable=yes"]
- if broker_url: args += [ "--ha-broker-url", broker_url ]
+ "--ha-cluster=yes"]
+ if broker_url: args += [ "--ha-brokers", broker_url ]
Broker.__init__(self, test, args, **kwargs)
def promote(self):
- assert os.system("qpid-ha-tool --promote %s"%(self.host_port())) == 0
+ assert os.system("$QPID_HA_EXEC promote -b %s"%(self.host_port())) == 0
def set_client_url(self, url):
assert os.system(
- "qpid-ha-tool --client-addresses=%s %s"%(url,self.host_port())) == 0
+ "$QPID_HA_EXEC set --public-brokers=%s -b %s"%(url,self.host_port())) == 0
def set_broker_url(self, url):
assert os.system(
- "qpid-ha-tool --broker-addresses=%s %s"%(url, self.host_port())) == 0
+ "$QPID_HA_EXEC set --brokers=%s -b %s"%(url, self.host_port())) == 0
+def set_broker_urls(brokers):
+ url = ",".join([b.host_port() for b in brokers])
+ for b in brokers: b.set_broker_url(url)
class ShortTests(BrokerTest):
"""Short HA functionality tests."""
@@ -59,7 +63,7 @@ class ShortTests(BrokerTest):
session.sender(address)
return True
except NotFound: return False
- assert retry(check), "Timed out waiting for %s"%(address)
+ assert retry(check), "Timed out waiting for address %s"%(address)
# Wait for address to become valid on a backup broker.
def wait_backup(self, backup, address):
@@ -109,7 +113,7 @@ class ShortTests(BrokerTest):
s3 = p.sender(exchange(prefix+"e4", "messages", prefix+"q4"))
s3.send(Message("7"))
# Use old connection to unbind
- us = primary.connect_old().session(str(qpid.datatypes.uuid4()))
+ us = primary.connect_old().session(str(uuid4()))
us.exchange_unbind(exchange=prefix+"e4", binding_key="", queue=prefix+"q4")
p.sender(prefix+"e4").send(Message("drop1")) # Should be dropped
# Need a marker so we can wait till sync is done.
@@ -298,6 +302,125 @@ class ShortTests(BrokerTest):
self.assert_browse_backup(brokers[1], "q", ["a","b"])
for b in brokers[1:]: b.kill()
+ def test_lvq(self):
+ """Verify that we replicate to an LVQ correctly"""
+ primary = HaBroker(self, name="primary")
+ primary.promote()
+ backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ s = primary.connect().session().sender("lvq; {create:always, node:{x-declare:{arguments:{'qpid.last_value_queue_key':lvq-key, 'qpid.replicate':messages}}}}")
+ def send(key,value): s.send(Message(content=value,properties={"lvq-key":key}))
+ for kv in [("a","a-1"),("b","b-1"),("a","a-2"),("a","a-3"),("c","c-1"),("c","c-2")]:
+ send(*kv)
+ self.assert_browse_backup(backup, "lvq", ["b-1", "a-3", "c-2"])
+ send("b","b-2")
+ self.assert_browse_backup(backup, "lvq", ["a-3", "c-2", "b-2"])
+ send("c","c-3")
+ self.assert_browse_backup(backup, "lvq", ["a-3", "b-2", "c-3"])
+ send("d","d-1")
+ self.assert_browse_backup(backup, "lvq", ["a-3", "b-2", "c-3", "d-1"])
+
+ def test_ring(self):
+ primary = HaBroker(self, name="primary")
+ primary.promote()
+ backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ s = primary.connect().session().sender("q; {create:always, node:{x-declare:{arguments:{'qpid.policy_type':ring, 'qpid.max_count':5, 'qpid.replicate':messages}}}}")
+ for i in range(10): s.send(Message(str(i)))
+ self.assert_browse_backup(backup, "q", [str(i) for i in range(5,10)])
+
+ def test_reject(self):
+ primary = HaBroker(self, name="primary")
+ primary.promote()
+ backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ s = primary.connect().session().sender("q; {create:always, node:{x-declare:{arguments:{'qpid.policy_type':reject, 'qpid.max_count':5, 'qpid.replicate':messages}}}}")
+ try:
+ for i in range(10): s.send(Message(str(i)), sync=False)
+ except qpid.messaging.exceptions.TargetCapacityExceeded: pass
+ self.assert_browse_backup(backup, "q", [str(i) for i in range(0,5)])
+
+ def test_priority(self):
+ """Verify priority queues replicate correctly"""
+ primary = HaBroker(self, name="primary")
+ primary.promote()
+ backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ session = primary.connect().session()
+ s = session.sender("priority-queue; {create:always, node:{x-declare:{arguments:{'qpid.priorities':10, 'qpid.replicate':messages}}}}")
+ priorities = [8,9,5,1,2,2,3,4,9,7,8,9,9,2]
+ for p in priorities: s.send(Message(priority=p))
+ # Can't use browse_backup as browser sees messages in delivery order not priority.
+ self.wait_backup(backup, "priority-queue")
+ r = self.connect_admin(backup).session().receiver("priority-queue")
+ received = [r.fetch().priority for i in priorities]
+ self.assertEqual(sorted(priorities, reverse=True), received)
+
+ def test_priority_fairshare(self):
+ """Verify priority queues replicate correctly"""
+ primary = HaBroker(self, name="primary")
+ primary.promote()
+ backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ session = primary.connect().session()
+ levels = 8
+ priorities = [4,5,3,7,8,8,2,8,2,8,8,16,6,6,6,6,6,6,8,3,5,8,3,5,5,3,3,8,8,3,7,3,7,7,7,8,8,8,2,3]
+ limits={7:0,6:4,5:3,4:2,3:2,2:2,1:2}
+ limit_policy = ",".join(["'qpid.fairshare':5"] + ["'qpid.fairshare-%s':%s"%(i[0],i[1]) for i in limits.iteritems()])
+ s = session.sender("priority-queue; {create:always, node:{x-declare:{arguments:{'qpid.priorities':%s, %s, 'qpid.replicate':messages}}}}"%(levels,limit_policy))
+ messages = [Message(content=str(uuid4()), priority = p) for p in priorities]
+ for m in messages: s.send(m)
+ self.wait_backup(backup, s.target)
+ r = self.connect_admin(backup).session().receiver("priority-queue")
+ received = [r.fetch().content for i in priorities]
+ sort = sorted(messages, key=lambda m: priority_level(m.priority, levels), reverse=True)
+ fair = [m.content for m in fairshare(sort, lambda l: limits.get(l,0), levels)]
+ self.assertEqual(received, fair)
+
+ def test_priority_ring(self):
+ primary = HaBroker(self, name="primary")
+ primary.promote()
+ backup = HaBroker(self, name="backup", broker_url=primary.host_port())
+ s = primary.connect().session().sender("q; {create:always, node:{x-declare:{arguments:{'qpid.policy_type':ring, 'qpid.max_count':5, 'qpid.priorities':10, 'qpid.replicate':messages}}}}")
+ priorities = [8,9,5,1,2,2,3,4,9,7,8,9,9,2]
+ for p in priorities: s.send(Message(priority=p))
+ # FIXME aconway 2012-02-22: there is a bug in priority ring queues that allows a low
+ # priority message to displace a high one. The following commented-out assert_browse
+ # is for the correct result, the uncommented one is for the actualy buggy result.
+ # See https://issues.apache.org/jira/browse/QPID-3866
+ #
+ # self.assert_browse_backup(backup, "q", sorted(priorities,reverse=True)[0:5], transform=lambda m: m.priority)
+ self.assert_browse_backup(backup, "q", [9,9,9,9,2], transform=lambda m: m.priority)
+
+def fairshare(msgs, limit, levels):
+ """
+ Generator to return prioritised messages in expected order for a given fairshare limit
+ """
+ count = 0
+ last_priority = None
+ postponed = []
+ while msgs or postponed:
+ if not msgs:
+ msgs = postponed
+ count = 0
+ last_priority = None
+ postponed = []
+ msg = msgs.pop(0)
+ if last_priority and priority_level(msg.priority, levels) == last_priority:
+ count += 1
+ else:
+ last_priority = priority_level(msg.priority, levels)
+ count = 1
+ l = limit(last_priority)
+ if (l and count > l):
+ postponed.append(msg)
+ else:
+ yield msg
+ return
+
+def priority_level(value, levels):
+ """
+ Method to determine which of a distinct number of priority levels
+ a given value falls into.
+ """
+ offset = 5-math.ceil(levels/2.0)
+ return min(max(value - offset, 0), levels-1)
+
class LongTests(BrokerTest):
"""Tests that can run for a long time if -DDURATION=<minutes> is set"""
@@ -311,7 +434,7 @@ class LongTests(BrokerTest):
"""Test failover with continuous send-receive"""
# FIXME aconway 2012-02-03: fails due to dropped messages,
# known issue: sending messages to new primary before
- # backups are ready.
+ # backups are ready. Enable when fixed.
# Start a cluster, all members will be killed during the test.
brokers = [ HaBroker(self, name=name, expect=EXPECT_EXIT_FAIL)
@@ -352,4 +475,10 @@ class LongTests(BrokerTest):
if __name__ == "__main__":
shutil.rmtree("brokertest.tmp", True)
- os.execvp("qpid-python-test", ["qpid-python-test", "-m", "ha_tests"] + sys.argv[1:])
+ qpid_ha = os.getenv("QPID_HA_EXEC")
+ if qpid_ha and os.path.exists(qpid_ha):
+ os.execvp("qpid-python-test",
+ ["qpid-python-test", "-m", "ha_tests"] + sys.argv[1:])
+ else:
+ print "Skipping ha_tests, qpid_ha not available"
+
diff --git a/cpp/src/tests/ipv6_test b/cpp/src/tests/ipv6_test
index d75d50fd0a..8fa272d514 100755
--- a/cpp/src/tests/ipv6_test
+++ b/cpp/src/tests/ipv6_test
@@ -93,10 +93,10 @@ else
BROKER1="[::1]:${PORTS[1]}"
TEST_QUEUE=ipv6-fed-test
- $QPID_CONFIG_EXEC -a $BROKER0 add queue $TEST_QUEUE
- $QPID_CONFIG_EXEC -a $BROKER1 add queue $TEST_QUEUE
+ $QPID_CONFIG_EXEC -b $BROKER0 add queue $TEST_QUEUE
+ $QPID_CONFIG_EXEC -b $BROKER1 add queue $TEST_QUEUE
$QPID_ROUTE_EXEC dynamic add $BROKER1 $BROKER0 amq.direct
- $QPID_CONFIG_EXEC -a $BROKER1 bind amq.direct $TEST_QUEUE $TEST_QUEUE
+ $QPID_CONFIG_EXEC -b $BROKER1 bind amq.direct $TEST_QUEUE $TEST_QUEUE
$QPID_ROUTE_EXEC route map $BROKER1
./datagen --count 100 | tee rdata-in |
diff --git a/cpp/src/tests/python_tests.ps1 b/cpp/src/tests/python_tests.ps1
index 9f8b9890c4..f7caa8f75a 100644
--- a/cpp/src/tests/python_tests.ps1
+++ b/cpp/src/tests/python_tests.ps1
@@ -26,8 +26,7 @@ if (!(Test-Path $PYTHON_DIR -pathType Container)) {
exit 1
}
-$PYTHON_TEST_DIR = "$srcdir\..\..\..\tests\src\py"
-$QMF_LIB = "$srcdir\..\..\..\extras\qmf\src\py"
+. .\test_env.ps1
if (Test-Path env:FAILING) {
$fails = "-I $env:FAILING"
@@ -39,7 +38,5 @@ else {
$tests = "$args"
}
-#cd $PYTHON_DIR
-$env:PYTHONPATH="$PYTHON_DIR;$PYTHON_TEST_DIR;$env:PYTHONPATH;$QMF_LIB"
python $PYTHON_DIR/qpid-python-test -m qpid_tests.broker_0_10 -m qpid.tests -b localhost:$env:QPID_PORT $fails $tests
exit $LASTEXITCODE
diff --git a/cpp/src/tests/queue_flow_limit_tests.py b/cpp/src/tests/queue_flow_limit_tests.py
index dec7cfb3af..d51b26a821 100644
--- a/cpp/src/tests/queue_flow_limit_tests.py
+++ b/cpp/src/tests/queue_flow_limit_tests.py
@@ -117,7 +117,7 @@ class QueueFlowLimitTests(TestBase010):
tool = environ.get("QPID_CONFIG_EXEC")
if tool:
command = tool + \
- " --broker-addr=%s:%s " % (self.broker.host, self.broker.port) \
+ " --broker=%s:%s " % (self.broker.host, self.broker.port) \
+ "add queue test01 --flow-stop-count=999" \
+ " --flow-resume-count=55 --flow-stop-size=5000000" \
+ " --flow-resume-size=100000"
diff --git a/cpp/src/tests/reliable_replication_test b/cpp/src/tests/reliable_replication_test
index 1f1dac5f2d..c660f751e5 100755
--- a/cpp/src/tests/reliable_replication_test
+++ b/cpp/src/tests/reliable_replication_test
@@ -47,12 +47,12 @@ setup() {
echo "Testing replication from port $BROKER_A to port $BROKER_B"
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add exchange replication replication
$PYTHON_COMMANDS/qpid-route --ack 500 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
#create test queue (only replicate enqueues for this test):
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-a --generate-queue-events 1
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-a
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add queue queue-a --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add queue queue-a
}
send() {
diff --git a/cpp/src/tests/replication_test b/cpp/src/tests/replication_test
index 8c37568875..f8b2136396 100755
--- a/cpp/src/tests/replication_test
+++ b/cpp/src/tests/replication_test
@@ -46,21 +46,21 @@ if test -d ${PYTHON_DIR} && test -f "$REPLICATING_LISTENER_LIB" && test -f "$REP
BROKER_B=`cat qpidd.port`
echo "Running replication test between localhost:$BROKER_A and localhost:$BROKER_B"
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add exchange replication replication
$PYTHON_COMMANDS/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
#create test queues
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-a --generate-queue-events 2
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-b --generate-queue-events 2
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-c --generate-queue-events 1
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-d --generate-queue-events 2
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-e --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add queue queue-a --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add queue queue-b --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add queue queue-c --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add queue queue-d --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add queue queue-e --generate-queue-events 1
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-a
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-b
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-c
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-e
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add queue queue-a
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add queue queue-b
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add queue queue-c
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add queue queue-e
#queue-d deliberately not declared on DR; this error case should be handled
#publish and consume from test queues on broker A:
@@ -124,13 +124,13 @@ if test -d ${PYTHON_DIR} && test -f "$REPLICATING_LISTENER_LIB" && test -f "$REP
$QPIDD_EXEC --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module $REPLICATION_EXCHANGE_LIB --log-enable info+ --log-to-file replication-dest.log --log-to-stderr 0 > qpidd.port
BROKER_B=`cat qpidd.port`
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add exchange replication replication
$PYTHON_COMMANDS/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-e --generate-queue-events 2
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-e
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-d --generate-queue-events 1
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-d
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add queue queue-e --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add queue queue-e
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_A" add queue queue-d --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add queue queue-d
i=1
while [ $i -le 10 ]; do
@@ -152,8 +152,8 @@ if test -d ${PYTHON_DIR} && test -f "$REPLICATING_LISTENER_LIB" && test -f "$REP
$QPIDD_EXEC --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module $REPLICATION_EXCHANGE_LIB --log-enable info+ --log-to-file replication-dest.log --log-to-stderr 0 > qpidd.port
BROKER_B=`cat qpidd.port`
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-e
- $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add queue queue-e
+ $PYTHON_COMMANDS/qpid-config -b "localhost:$BROKER_B" add exchange replication replication
$PYTHON_COMMANDS/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
# now send another 15
i=11
diff --git a/cpp/src/tests/ring_queue_test b/cpp/src/tests/ring_queue_test
index 553746eb49..271b46183e 100755
--- a/cpp/src/tests/ring_queue_test
+++ b/cpp/src/tests/ring_queue_test
@@ -28,7 +28,7 @@ MESSAGES=10000
SENDERS=1
RECEIVERS=1
CONCURRENT=0
-BROKER_URL="-a ${QPID_BROKER:-localhost}:${QPID_PORT:-5672}"
+BROKER_URL="-b ${QPID_BROKER:-localhost}:${QPID_PORT:-5672}"
setup() {
if [[ $DURABLE -gt 0 ]]; then
diff --git a/cpp/src/tests/run_acl_tests.ps1 b/cpp/src/tests/run_acl_tests.ps1
index 46e070477f..8279d87e54 100644
--- a/cpp/src/tests/run_acl_tests.ps1
+++ b/cpp/src/tests/run_acl_tests.ps1
@@ -20,15 +20,12 @@
# Run the acl tests.
$srcdir = Split-Path $myInvocation.InvocationName
-$PYTHON_DIR = "$srcdir\..\..\..\python"
+. .\test_env.ps1
if (!(Test-Path $PYTHON_DIR -pathType Container)) {
"Skipping acl tests as python libs not found"
exit 1
}
-$PYTHON_TEST_DIR = "$srcdir\..\..\..\tests\src\py"
-$QMF_LIB = "$srcdir\..\..\..\extras\qmf\src\py"
-$env:PYTHONPATH="$PYTHON_DIR;$srcdir;$PYTHON_TEST_DIR;$QMF_LIB"
$Global:BROKER_EXE = ""
Function start_broker($acl_options)
diff --git a/cpp/src/tests/run_federation_tests.ps1 b/cpp/src/tests/run_federation_tests.ps1
index 35353a870f..803b3eef6f 100644
--- a/cpp/src/tests/run_federation_tests.ps1
+++ b/cpp/src/tests/run_federation_tests.ps1
@@ -26,8 +26,7 @@ if (!(Test-Path $PYTHON_DIR -pathType Container)) {
exit 1
}
-$PYTHON_TEST_DIR = "$srcdir\..\..\..\tests\src\py"
-$QMF_LIB = "$srcdir\..\..\..\extras\qmf\src\py"
+. .\test_env.ps1
# Test runs from the tests directory but the broker executable is one level
# up, and most likely in a subdirectory from there based on what build type.
diff --git a/cpp/src/tests/run_header_test.ps1 b/cpp/src/tests/run_header_test.ps1
index 7d3e43a30f..344fac9cf9 100644
--- a/cpp/src/tests/run_header_test.ps1
+++ b/cpp/src/tests/run_header_test.ps1
@@ -28,6 +28,8 @@ if (!(Test-Path $PYTHON_DIR -pathType Container)) {
exit 0
}
+. .\test_env.ps1
+
if (Test-Path qpidd.port) {
set-item -path env:QPID_PORT -value (get-content -path qpidd.port -totalcount 1)
}
@@ -42,6 +44,5 @@ if (!(Test-Path $prog)) {
}
Invoke-Expression "$prog -p $env:QPID_PORT" | Write-Output
-$env:PYTHONPATH="$PYTHON_DIR;$env:PYTHONPATH"
Invoke-Expression "python $srcdir/header_test.py localhost $env:QPID_PORT" | Write-Output
exit $LASTEXITCODE
diff --git a/cpp/src/tests/run_msg_group_tests b/cpp/src/tests/run_msg_group_tests
index 5a6da546f3..4e82759866 100755
--- a/cpp/src/tests/run_msg_group_tests
+++ b/cpp/src/tests/run_msg_group_tests
@@ -44,19 +44,19 @@ run_test() {
declare -i i=0
declare -a tests
-tests=("qpid-config -a $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups"
+tests=("qpid-config -b $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 3"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 7 --randomize-group-size"
- "qpid-config -a $BROKER_URL add queue ${QUEUE_NAME}-two --group-header=${GROUP_KEY} --shared-groups"
+ "qpid-config -b $BROKER_URL add queue ${QUEUE_NAME}-two --group-header=${GROUP_KEY} --shared-groups"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 3 --randomize-group-size"
"msg_group_test -b $BROKER_URL -a ${QUEUE_NAME}-two --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 5"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 59 --group-size 5 --receivers 2 --senders 3 --capacity 1 --ack-frequency 3 --randomize-group-size"
- "qpid-config -a $BROKER_URL del queue ${QUEUE_NAME}-two --force"
+ "qpid-config -b $BROKER_URL del queue ${QUEUE_NAME}-two --force"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 59 --group-size 3 --receivers 2 --senders 3 --capacity 1 --ack-frequency 1 --randomize-group-size"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 211 --group-size 13 --receivers 2 --senders 3 --capacity 47 --ack-frequency 79 --interleave 53"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10000 --group-size 1 --receivers 0 --senders 1"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10000 --receivers 5 --senders 0"
- "qpid-config -a $BROKER_URL del queue $QUEUE_NAME --force")
+ "qpid-config -b $BROKER_URL del queue $QUEUE_NAME --force")
while [ -n "${tests[i]}" ]; do
run_test ${tests[i]}
diff --git a/cpp/src/tests/run_msg_group_tests_soak b/cpp/src/tests/run_msg_group_tests_soak
index 44995423cc..2ebbaf4efd 100755
--- a/cpp/src/tests/run_msg_group_tests_soak
+++ b/cpp/src/tests/run_msg_group_tests_soak
@@ -44,13 +44,13 @@ run_test() {
declare -i i=0
declare -a tests
-tests=("qpid-config -a $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups"
+tests=("qpid-config -b $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 47 --ack-frequency 97"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 79 --ack-frequency 79"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 97 --ack-frequency 47"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 40000 --receivers 0 --senders 5 --group-size 13 --randomize-group-size"
"msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 200000 --receivers 3 --senders 0 --capacity 23 --ack-frequency 7"
- "qpid-config -a $BROKER_URL del queue $QUEUE_NAME --force")
+ "qpid-config -b $BROKER_URL del queue $QUEUE_NAME --force")
while [ -n "${tests[i]}" ]; do
run_test ${tests[i]}
diff --git a/cpp/src/tests/run_store_tests.ps1 b/cpp/src/tests/run_store_tests.ps1
index b2f0b1ccd8..0683892393 100644
--- a/cpp/src/tests/run_store_tests.ps1
+++ b/cpp/src/tests/run_store_tests.ps1
@@ -30,14 +30,14 @@ if ($test_store -ne "MSSQL" -and $test_store -ne "MSSQL-CLFS") {
}
$srcdir = Split-Path $myInvocation.InvocationName
-$PYTHON_DIR = "$srcdir\..\..\..\python"
+
+. .\test_env.ps1
+
if (!(Test-Path $PYTHON_DIR -pathType Container)) {
"Skipping store tests as python libs not found"
exit 1
}
-$QMF_LIB = "$srcdir\..\..\..\extras\qmf\src\py"
-
# Test runs from the tests directory but the broker executable is one level
# up, and most likely in a subdirectory from there based on what build type.
# Look around for it before trying to start it.
@@ -97,7 +97,7 @@ set-item -path env:QPID_PORT -value (get-content -path qpidd-store.port -totalco
Remove-Item qpidd-store.port
$PYTHON_TEST_DIR = "$srcdir\..\..\..\tests\src\py\qpid_tests\broker_0_10"
-$env:PYTHONPATH="$PYTHON_DIR;$PYTHON_TEST_DIR;$env:PYTHONPATH;$QMF_LIB"
+$env:PYTHONPATH="$PYTHON_TEST_DIR;$srcdir;$env:PYTHONPATH"
python $PYTHON_DIR/qpid-python-test -m dtx -m persistence -b localhost:$env:QPID_PORT $fails $tests
$RETCODE=$LASTEXITCODE
if ($RETCODE -ne 0) {
@@ -111,7 +111,6 @@ Invoke-Expression "$prog --quit --port $env:QPID_PORT" | Write-Output
# Test 2... store.py starts/stops/restarts its own brokers
$tests = "*"
-$env:PYTHONPATH="$PYTHON_DIR;$QMF_LIB;$srcdir"
$env:QPIDD_EXEC="$prog"
$env:STORE_LIB="$store_dir\store$suffix.dll"
if ($test_store -eq "MSSQL") {
diff --git a/cpp/src/tests/run_test.ps1 b/cpp/src/tests/run_test.ps1
index ca990bc057..872e1dddb1 100644
--- a/cpp/src/tests/run_test.ps1
+++ b/cpp/src/tests/run_test.ps1
@@ -20,8 +20,7 @@
$srcdir = Split-Path $myInvocation.InvocationName
# Set up environment and run a test executable or script.
-$env:QPID_DATA_DIR = ""
-$env:BOOST_TEST_SHOW_PROGRESS = "yes"
+. .\test_env.ps1
# The test exe is probably not in the current binary dir - it's usually
# placed in a subdirectory based on the configuration built in Visual Studio.
@@ -30,7 +29,7 @@ $env:BOOST_TEST_SHOW_PROGRESS = "yes"
# one level up.
$prog = $args[0]
$is_script = $prog -match ".ps1$"
-if (!$is_script) {
+if (!$is_script -and !(Test-Path "$prog")) {
. $srcdir\find_prog.ps1 $prog
$args[0] = $prog
$env:QPID_LIB_DIR = "..\$sub"
diff --git a/cpp/src/tests/sasl_fed b/cpp/src/tests/sasl_fed
index 884c44177c..9dc2dd46e2 100755
--- a/cpp/src/tests/sasl_fed
+++ b/cpp/src/tests/sasl_fed
@@ -90,23 +90,23 @@ EXCHANGE_NAME=sasl_fedex
#--------------------------------------------------
#echo " add exchanges"
#--------------------------------------------------
-$QPID_CONFIG_EXEC -a localhost:$broker_1_port add exchange direct $EXCHANGE_NAME
-$QPID_CONFIG_EXEC -a localhost:$broker_2_port add exchange direct $EXCHANGE_NAME
+$QPID_CONFIG_EXEC -b localhost:$broker_1_port add exchange direct $EXCHANGE_NAME
+$QPID_CONFIG_EXEC -b localhost:$broker_2_port add exchange direct $EXCHANGE_NAME
#--------------------------------------------------
#echo " add queues"
#--------------------------------------------------
-$QPID_CONFIG_EXEC -a localhost:$broker_1_port add queue $QUEUE_NAME
-$QPID_CONFIG_EXEC -a localhost:$broker_2_port add queue $QUEUE_NAME
+$QPID_CONFIG_EXEC -b localhost:$broker_1_port add queue $QUEUE_NAME
+$QPID_CONFIG_EXEC -b localhost:$broker_2_port add queue $QUEUE_NAME
sleep 5
#--------------------------------------------------
#echo " create bindings"
#--------------------------------------------------
-$QPID_CONFIG_EXEC -a localhost:$broker_1_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
-$QPID_CONFIG_EXEC -a localhost:$broker_2_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
+$QPID_CONFIG_EXEC -b localhost:$broker_1_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
+$QPID_CONFIG_EXEC -b localhost:$broker_2_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
sleep 5
@@ -130,13 +130,13 @@ sleep 5
#--------------------------------------------------
#echo " Examine Broker $broker_1_port"
#--------------------------------------------------
-broker_1_message_count=`$PYTHON_COMMANDS/qpid-stat -q localhost:$broker_1_port | grep sasl_fed_queue | awk '{print $2}'`
+broker_1_message_count=`$PYTHON_COMMANDS/qpid-stat -q -b localhost:$broker_1_port | grep sasl_fed_queue | awk '{print $2}'`
#echo " "
#--------------------------------------------------
#echo " Examine Broker $broker_2_port"
#--------------------------------------------------
-broker_2_message_count=`$PYTHON_COMMANDS/qpid-stat -q localhost:$broker_2_port | grep sasl_fed_queue | awk '{print $2}'`
+broker_2_message_count=`$PYTHON_COMMANDS/qpid-stat -q -b localhost:$broker_2_port | grep sasl_fed_queue | awk '{print $2}'`
#echo " "
#--------------------------------------------------
diff --git a/cpp/src/tests/sasl_fed_ex b/cpp/src/tests/sasl_fed_ex
index 716a806874..cc5b310067 100755
--- a/cpp/src/tests/sasl_fed_ex
+++ b/cpp/src/tests/sasl_fed_ex
@@ -280,18 +280,18 @@ EXCHANGE_NAME=sasl_fedex
print "add exchanges"
-$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} add exchange direct $EXCHANGE_NAME
-$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} add exchange direct $EXCHANGE_NAME
+$QPID_CONFIG_EXEC -b localhost:${SRC_TCP_PORT} add exchange direct $EXCHANGE_NAME
+$QPID_CONFIG_EXEC -b localhost:${DST_TCP_PORT} add exchange direct $EXCHANGE_NAME
print "add queues"
-$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} add queue $QUEUE_NAME
-$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} add queue $QUEUE_NAME
+$QPID_CONFIG_EXEC -b localhost:${SRC_TCP_PORT} add queue $QUEUE_NAME
+$QPID_CONFIG_EXEC -b localhost:${DST_TCP_PORT} add queue $QUEUE_NAME
print "create bindings"
-$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
-$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
+$QPID_CONFIG_EXEC -b localhost:${SRC_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
+$QPID_CONFIG_EXEC -b localhost:${DST_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
#
diff --git a/cpp/src/tests/test_env.sh.in b/cpp/src/tests/test_env.sh.in
index 0cd658bd80..5c07bcdc2e 100644
--- a/cpp/src/tests/test_env.sh.in
+++ b/cpp/src/tests/test_env.sh.in
@@ -44,6 +44,7 @@ export PYTHONPATH=$srcdir:$PYTHON_DIR:$PYTHON_COMMANDS:$QPID_TESTS_PY:$QMF_LIB:$
export QPID_CONFIG_EXEC=$PYTHON_COMMANDS/qpid-config
export QPID_ROUTE_EXEC=$PYTHON_COMMANDS/qpid-route
export QPID_CLUSTER_EXEC=$PYTHON_COMMANDS/qpid-cluster
+export QPID_HA_EXEC=$PYTHON_COMMANDS/qpid-ha
# Executables
export QPIDD_EXEC=$top_builddir/src/qpidd
diff --git a/cpp/src/tests/testlib.py b/cpp/src/tests/testlib.py
index fe57a84a81..71ad59e5c1 100644
--- a/cpp/src/tests/testlib.py
+++ b/cpp/src/tests/testlib.py
@@ -348,8 +348,8 @@ class TestBaseCluster(TestBase):
def _qpidConfig(self, nodeNumber, clusterName, action):
"""Configure some aspect of a qpid broker using the qpid_config executable"""
port = self.getNodeTuple(nodeNumber, clusterName)[self.PORT]
- #print "%s -a localhost:%d %s" % (self._qpidConfigExec, port, action)
- ret = os.spawnl(os.P_WAIT, self._qpidConfigExec, self._qpidConfigExec, "-a", "localhost:%d" % port, *action.split())
+ #print "%s -b localhost:%d %s" % (self._qpidConfigExec, port, action)
+ ret = os.spawnl(os.P_WAIT, self._qpidConfigExec, self._qpidConfigExec, "-b", "localhost:%d" % port, *action.split())
if ret != 0:
raise Exception("_qpidConfig(): cluster=\"%s\" nodeNumber=%d port=%d action=\"%s\" returned %d" % \
(clusterName, nodeNumber, port, action, ret))
diff --git a/doc/book/src/LVQ.xml b/doc/book/src/LVQ.xml
index 4e818881ad..b57c6268be 100644
--- a/doc/book/src/LVQ.xml
+++ b/doc/book/src/LVQ.xml
@@ -117,7 +117,7 @@
qpid-config utility:
</para>
<programlisting>
- $ qpid-config add queue prices --argument qpid.last_value_queue_key=ticker
+ $ qpid-config add queue prices --lvq-key ticker
</programlisting>
</section>
</section>
@@ -131,13 +131,13 @@
from qpid.messaging import Connection, Message
def send(sender, key, message):
- message.properties["key"] = key
+ message.properties["ticker"] = key
sender.send(message)
conn = Connection("localhost")
conn.open()
sess = conn.session()
- tx = sess.sender("topic;{create:always, node:{type:queue,x-declare:{arguments:{'qpid.last_value_queue_key':key}}}}")
+ tx = sess.sender("prices;{create:always, node:{type:queue,x-declare:{arguments:{'qpid.last_value_queue_key':ticker}}}}")
msg = Message("Content")
send(tx, "key1", msg);
@@ -155,12 +155,11 @@
<title>LVQ Browsing Receiver</title>
<programlisting>
from qpid.messaging import Connection, Message
- from time import sleep
conn = Connection("localhost")
conn.open()
sess = conn.session()
- rx = sess.receiver("topic;{mode:browse}")
+ rx = sess.receiver("prices;{mode:browse}")
while True:
msg = rx.fetch()
@@ -176,7 +175,7 @@
There are two legacy modes (still implemented as of Qpid 0.14)
controlled by the qpid.last_value_queue and
qpid.last_value_queue_no_browse argument values. These modes are
- intended to be deprecated and should not be used.
+ deprecated and should not be used.
</para>
</section>
</section>
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
index 29f2a2f2fb..a91d8f359e 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
@@ -36,6 +36,7 @@ import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.LockConflictException;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
+import com.sleepycat.je.Transaction;
import com.sleepycat.je.TransactionConfig;
import org.apache.commons.configuration.Configuration;
import org.apache.log4j.Logger;
@@ -68,14 +69,18 @@ import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
import org.apache.qpid.server.store.TransactionLogRecoveryHandler.QueueEntryRecoveryHandler;
import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.store.berkeleydb.keys.MessageContentKey_5;
+import org.apache.qpid.server.store.berkeleydb.keys.Xid;
import org.apache.qpid.server.store.berkeleydb.records.BindingRecord;
import org.apache.qpid.server.store.berkeleydb.records.ExchangeRecord;
+import org.apache.qpid.server.store.berkeleydb.records.PreparedTransaction;
import org.apache.qpid.server.store.berkeleydb.records.QueueRecord;
import org.apache.qpid.server.store.berkeleydb.tuples.BindingTupleBindingFactory;
import org.apache.qpid.server.store.berkeleydb.tuples.MessageContentKeyTB_5;
import org.apache.qpid.server.store.berkeleydb.tuples.MessageMetaDataTupleBindingFactory;
+import org.apache.qpid.server.store.berkeleydb.tuples.PreparedTransactionTB;
import org.apache.qpid.server.store.berkeleydb.tuples.QueueEntryTB;
import org.apache.qpid.server.store.berkeleydb.tuples.QueueTupleBindingFactory;
+import org.apache.qpid.server.store.berkeleydb.tuples.XidTB;
import java.io.File;
import java.lang.ref.SoftReference;
@@ -120,6 +125,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
private String QUEUEDB_NAME = "queueDb";
private String BRIDGEDB_NAME = "bridges";
private String LINKDB_NAME = "links";
+ private String XIDDB_NAME = "xids";
private Database _messageMetaDataDb;
private Database _messageContentDb;
@@ -129,6 +135,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
private Database _queueDb;
private Database _bridgeDb;
private Database _linkDb;
+ private Database _xidDb;
/* =======
* Schema:
@@ -217,6 +224,8 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
LINKDB_NAME += "_v" + version;
BRIDGEDB_NAME += "_v" + version;
+
+ XIDDB_NAME += "_v" + version;
}
}
@@ -272,6 +281,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
}
recoverQueueEntries(recoveryHandler);
+
}
@@ -487,6 +497,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
_deliveryDb = openDatabase(DELIVERYDB_NAME, dbConfig);
_linkDb = openDatabase(LINKDB_NAME, dbConfig);
_bridgeDb = openDatabase(BRIDGEDB_NAME, dbConfig);
+ _xidDb = openDatabase(XIDDB_NAME, dbConfig);
}
@@ -564,6 +575,13 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
_linkDb.close();
}
+
+ if (_xidDb != null)
+ {
+ _log.info("Close xid database");
+ _xidDb.close();
+ }
+
closeEnvironment();
_state = State.CLOSED;
@@ -884,7 +902,52 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
}
}
- qerh.completeQueueEntryRecovery();
+
+
+ TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh = qerh.completeQueueEntryRecovery();
+
+ cursor = null;
+ try
+ {
+ cursor = _xidDb.openCursor(null, null);
+ DatabaseEntry key = new DatabaseEntry();
+ XidTB keyBinding = new XidTB();
+ PreparedTransactionTB valueBinding = new PreparedTransactionTB();
+ DatabaseEntry value = new DatabaseEntry();
+
+ while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
+ {
+ Xid xid = keyBinding.entryToObject(key);
+ PreparedTransaction preparedTransaction = valueBinding.entryToObject(value);
+ dtxrh.dtxRecord(xid.getFormat(),xid.getGlobalId(),xid.getBranchId(),
+ preparedTransaction.getEnqueues(),preparedTransaction.getDequeues());
+ }
+
+ try
+ {
+ cursor.close();
+ }
+ finally
+ {
+ cursor = null;
+ }
+
+ }
+ catch (DatabaseException e)
+ {
+ _log.error("Database Error: " + e.getMessage(), e);
+ throw e;
+ }
+ finally
+ {
+ if (cursor != null)
+ {
+ cursor.close();
+ }
+ }
+
+
+ dtxrh.completeDtxRecordRecovery();
}
/**
@@ -1481,6 +1544,69 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
}
}
+
+ private void recordXid(com.sleepycat.je.Transaction txn,
+ long format,
+ byte[] globalId,
+ byte[] branchId,
+ Transaction.Record[] enqueues,
+ Transaction.Record[] dequeues) throws AMQStoreException
+ {
+ DatabaseEntry key = new DatabaseEntry();
+ Xid xid = new Xid(format, globalId, branchId);
+ XidTB keyBinding = new XidTB();
+ keyBinding.objectToEntry(xid,key);
+
+ DatabaseEntry value = new DatabaseEntry();
+ PreparedTransaction preparedTransaction = new PreparedTransaction(enqueues, dequeues);
+ PreparedTransactionTB valueBinding = new PreparedTransactionTB();
+ valueBinding.objectToEntry(preparedTransaction, value);
+
+ try
+ {
+ _xidDb.put(txn, key, value);
+ }
+ catch (DatabaseException e)
+ {
+ _log.error("Failed to write xid: " + e.getMessage(), e);
+ throw new AMQStoreException("Error writing xid to database", e);
+ }
+ }
+
+ private void removeXid(com.sleepycat.je.Transaction txn, long format, byte[] globalId, byte[] branchId)
+ throws AMQStoreException
+ {
+ DatabaseEntry key = new DatabaseEntry();
+ Xid xid = new Xid(format, globalId, branchId);
+ XidTB keyBinding = new XidTB();
+
+ keyBinding.objectToEntry(xid, key);
+
+
+ try
+ {
+
+ OperationStatus status = _xidDb.delete(txn, key);
+ if (status == OperationStatus.NOTFOUND)
+ {
+ throw new AMQStoreException("Unable to find xid");
+ }
+ else if (status != OperationStatus.SUCCESS)
+ {
+ throw new AMQStoreException("Unable to remove xid");
+ }
+
+ }
+ catch (DatabaseException e)
+ {
+
+ _log.error("Failed to remove xid ", e);
+ _log.error(txn);
+
+ throw new AMQStoreException("Error accessing database while removing xid: " + e.getMessage(), e);
+ }
+ }
+
/**
* Commits all operations performed within a given transaction.
*
@@ -2385,6 +2511,18 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
{
BDBMessageStore.this.abortTran(_txn);
}
+
+ public void removeXid(long format, byte[] globalId, byte[] branchId) throws AMQStoreException
+ {
+ BDBMessageStore.this.removeXid(_txn, format, globalId, branchId);
+ }
+
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues,
+ Record[] dequeues) throws AMQStoreException
+ {
+ BDBMessageStore.this.recordXid(_txn, format, globalId, branchId, enqueues, dequeues);
+ }
}
+
}
diff --git a/cpp/src/qpid/sys/apr/APRPool.cpp b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/Xid.java
index e221bfc2f1..f74d67b355 100644
--- a/cpp/src/qpid/sys/apr/APRPool.cpp
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/Xid.java
@@ -7,9 +7,9 @@
* 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
@@ -19,23 +19,34 @@
*
*/
-#include "qpid/sys/apr/APRPool.h"
-#include "qpid/sys/apr/APRBase.h"
-#include <boost/pool/detail/singleton.hpp>
+package org.apache.qpid.server.store.berkeleydb.keys;
-using namespace qpid::sys;
+public class Xid
+{
-APRPool::APRPool(){
- APRBase::increment();
- CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL));
-}
+ private final long _format;
+ private final byte[] _globalId;
+ private final byte[] _branchId;
-APRPool::~APRPool(){
- apr_pool_destroy(pool);
- APRBase::decrement();
-}
+ public Xid(long format, byte[] globalId, byte[] branchId)
+ {
+ _format = format;
+ _globalId = globalId;
+ _branchId = branchId;
+ }
-apr_pool_t* APRPool::get() {
- return boost::details::pool::singleton_default<APRPool>::instance().pool;
-}
+ public long getFormat()
+ {
+ return _format;
+ }
+
+ public byte[] getGlobalId()
+ {
+ return _globalId;
+ }
+ public byte[] getBranchId()
+ {
+ return _branchId;
+ }
+}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/PreparedTransaction.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/PreparedTransaction.java
new file mode 100644
index 0000000000..bfd72b9a1f
--- /dev/null
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/PreparedTransaction.java
@@ -0,0 +1,46 @@
+/*
+ *
+ * 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.server.store.berkeleydb.records;
+
+import org.apache.qpid.server.store.MessageStore;
+
+public class PreparedTransaction
+{
+ private final MessageStore.Transaction.Record[] _enqueues;
+ private final MessageStore.Transaction.Record[] _dequeues;
+
+ public PreparedTransaction(MessageStore.Transaction.Record[] enqueues, MessageStore.Transaction.Record[] dequeues)
+ {
+ _enqueues = enqueues;
+ _dequeues = dequeues;
+ }
+
+ public MessageStore.Transaction.Record[] getEnqueues()
+ {
+ return _enqueues;
+ }
+
+ public MessageStore.Transaction.Record[] getDequeues()
+ {
+ return _dequeues;
+ }
+}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/PreparedTransactionTB.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/PreparedTransactionTB.java
new file mode 100644
index 0000000000..3eb4cb69b5
--- /dev/null
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/PreparedTransactionTB.java
@@ -0,0 +1,122 @@
+/*
+ *
+ * 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.server.store.berkeleydb.tuples;
+
+import com.sleepycat.bind.tuple.TupleBinding;
+import com.sleepycat.bind.tuple.TupleInput;
+import com.sleepycat.bind.tuple.TupleOutput;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.store.berkeleydb.records.PreparedTransaction;
+
+public class PreparedTransactionTB extends TupleBinding<PreparedTransaction>
+{
+ @Override
+ public PreparedTransaction entryToObject(TupleInput input)
+ {
+ MessageStore.Transaction.Record[] enqueues = readRecords(input);
+
+ MessageStore.Transaction.Record[] dequeues = readRecords(input);
+
+ return new PreparedTransaction(enqueues, dequeues);
+ }
+
+ private MessageStore.Transaction.Record[] readRecords(TupleInput input)
+ {
+ MessageStore.Transaction.Record[] records = new MessageStore.Transaction.Record[input.readInt()];
+ for(int i = 0; i < records.length; i++)
+ {
+ records[i] = new RecordImpl(input.readString(), input.readLong());
+ }
+ return records;
+ }
+
+ @Override
+ public void objectToEntry(PreparedTransaction preparedTransaction, TupleOutput output)
+ {
+ writeRecords(preparedTransaction.getEnqueues(), output);
+ writeRecords(preparedTransaction.getDequeues(), output);
+
+ }
+
+ private void writeRecords(MessageStore.Transaction.Record[] records, TupleOutput output)
+ {
+ if(records == null)
+ {
+ output.writeInt(0);
+ }
+ else
+ {
+ output.writeInt(records.length);
+ for(MessageStore.Transaction.Record record : records)
+ {
+ output.writeString(record.getQueue().getResourceName());
+ output.writeLong(record.getMessage().getMessageNumber());
+ }
+ }
+ }
+
+ private static class RecordImpl implements MessageStore.Transaction.Record, TransactionLogResource, EnqueableMessage
+ {
+
+ private final String _queueName;
+ private long _messageNumber;
+
+ public RecordImpl(String queueName, long messageNumber)
+ {
+ _queueName = queueName;
+ _messageNumber = messageNumber;
+ }
+
+ public TransactionLogResource getQueue()
+ {
+ return this;
+ }
+
+ public EnqueableMessage getMessage()
+ {
+ return this;
+ }
+
+ public long getMessageNumber()
+ {
+ return _messageNumber;
+ }
+
+ public boolean isPersistent()
+ {
+ return true;
+ }
+
+ public StoredMessage getStoredMessage()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getResourceName()
+ {
+ return _queueName;
+ }
+ }
+}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/XidTB.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/XidTB.java
new file mode 100644
index 0000000000..3a5d61b2b6
--- /dev/null
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/XidTB.java
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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.server.store.berkeleydb.tuples;
+
+import com.sleepycat.bind.tuple.TupleBinding;
+import com.sleepycat.bind.tuple.TupleInput;
+import com.sleepycat.bind.tuple.TupleOutput;
+import org.apache.qpid.server.store.berkeleydb.keys.Xid;
+
+public class XidTB extends TupleBinding<Xid>
+{
+ @Override
+ public Xid entryToObject(TupleInput input)
+ {
+ long format = input.readLong();
+ byte[] globalId = new byte[input.readInt()];
+ input.readFast(globalId);
+ byte[] branchId = new byte[input.readInt()];
+ input.readFast(branchId);
+ return new Xid(format,globalId,branchId);
+ }
+
+ @Override
+ public void objectToEntry(Xid xid, TupleOutput output)
+ {
+ output.writeLong(xid.getFormat());
+ output.writeInt(xid.getGlobalId() == null ? 0 : xid.getGlobalId().length);
+ if(xid.getGlobalId() != null)
+ {
+ output.write(xid.getGlobalId());
+ }
+ output.writeInt(xid.getBranchId() == null ? 0 : xid.getBranchId().length);
+ if(xid.getBranchId() != null)
+ {
+ output.write(xid.getBranchId());
+ }
+
+ }
+}
diff --git a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java b/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
index ace30b9b89..cf79924f3d 100644
--- a/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
+++ b/java/broker-plugins/extras/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
@@ -80,6 +80,11 @@ public class TestExchange implements Exchange
return false;
}
+ public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue)
+ {
+ return false;
+ }
+
public boolean isBound(String bindingKey)
{
return false;
diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
index 1a098d0446..2d6f7e0946 100644
--- a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
@@ -410,6 +410,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return queues;
}
+ public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue)
+ {
+ return false; //TODO
+ }
+
public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
{
return false; //To change body of implemented methods use File | Settings | File Templates.
diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
index e5e755bd23..16a3036ea7 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
@@ -1615,7 +1615,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
}
}
- @Override
public int compareTo(AMQSessionModel session)
{
return getId().toString().compareTo(session.getID().toString());
diff --git a/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/java/broker/src/main/java/org/apache/qpid/server/Broker.java
index 072f8dc132..18f69853e6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/Broker.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/Broker.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server;
+import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.QpidLog4JConfigurator;
@@ -59,8 +60,11 @@ import java.util.Set;
public class Broker
{
+ private static final Logger LOGGER = Logger.getLogger(Broker.class);
+
private static final int IPV4_ADDRESS_LENGTH = 4;
private static final char IPV4_LITERAL_SEPARATOR = '.';
+ private volatile Thread _shutdownHookThread;
protected static class InitException extends RuntimeException
{
@@ -74,7 +78,14 @@ public class Broker
public void shutdown()
{
- ApplicationRegistry.remove();
+ try
+ {
+ removeShutdownHook();
+ }
+ finally
+ {
+ ApplicationRegistry.remove();
+ }
}
public void startup() throws Exception
@@ -88,6 +99,7 @@ public class Broker
{
CurrentActor.set(new BrokerActor(new SystemOutMessageLogger()));
startupImpl(options);
+ addShutdownHook();
}
finally
{
@@ -441,4 +453,56 @@ public class Broker
blm.register();
}
+
+ private void addShutdownHook()
+ {
+ Thread shutdownHookThread = new Thread(new ShutdownService());
+ shutdownHookThread.setName("QpidBrokerShutdownHook");
+
+ Runtime.getRuntime().addShutdownHook(shutdownHookThread);
+ _shutdownHookThread = shutdownHookThread;
+
+ LOGGER.debug("Added shutdown hook");
+ }
+
+ private void removeShutdownHook()
+ {
+ Thread shutdownThread = _shutdownHookThread;
+
+ //if there is a shutdown thread and we aren't it, we should remove it
+ if(shutdownThread != null && !(Thread.currentThread() == shutdownThread))
+ {
+ LOGGER.debug("Removing shutdown hook");
+
+ _shutdownHookThread = null;
+
+ boolean removed = false;
+ try
+ {
+ removed = Runtime.getRuntime().removeShutdownHook(shutdownThread);
+ }
+ catch(IllegalStateException ise)
+ {
+ //ignore, means the JVM is already shutting down
+ }
+
+ if(LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Removed shutdown hook: " + removed);
+ }
+ }
+ else
+ {
+ LOGGER.debug("Skipping shutdown hook removal as there either isnt one, or we are it.");
+ }
+ }
+
+ private class ShutdownService implements Runnable
+ {
+ public void run()
+ {
+ LOGGER.debug("Shutdown hook running");
+ Broker.this.shutdown();
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
index 5fd261a081..558311fc46 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
@@ -42,9 +42,9 @@ import java.util.Map;
public class VirtualHostConfiguration extends ConfigurationPlugin
{
- private String _name;
- private Map<String, QueueConfiguration> _queues = new HashMap<String, QueueConfiguration>();
- private Map<String, ExchangeConfiguration> _exchanges = new HashMap<String, ExchangeConfiguration>();
+ private final String _name;
+ private final Map<String, QueueConfiguration> _queues = new HashMap<String, QueueConfiguration>();
+ private final Map<String, ExchangeConfiguration> _exchanges = new HashMap<String, ExchangeConfiguration>();
public VirtualHostConfiguration(String name, Configuration config) throws ConfigurationException
{
@@ -92,11 +92,6 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
return getLongValue("housekeeping.checkPeriod", ApplicationRegistry.getInstance().getConfiguration().getHousekeepingCheckPeriod());
}
- public String getAuthenticationDatabase()
- {
- return getStringValue("security.authentication.name");
- }
-
public List getCustomExchanges()
{
return getListValue("custom-exchanges.class-name");
@@ -253,16 +248,6 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
return queueConfig;
}
- public long getMemoryUsageMaximum()
- {
- return getLongValue("queues.maximumMemoryUsage");
- }
-
- public long getMemoryUsageMinimum()
- {
- return getLongValue("queues.minimumMemoryUsage");
- }
-
public int getMaximumMessageAge()
{
return getIntValue("queues.maximumMessageAge");
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
index c3ae15f09c..0bcfc3a3da 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
@@ -35,6 +35,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
import javax.management.JMException;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
public interface Exchange extends ExchangeReferrer, ExchangeConfig
{
@@ -111,6 +112,8 @@ public interface Exchange extends ExchangeReferrer, ExchangeConfig
boolean isBound(String bindingKey, AMQQueue queue);
+ public boolean isBound(String bindingKey, Map<String,Object> arguments, AMQQueue queue);
+
boolean isBound(String bindingKey);
void addCloseTask(Task task);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
index 0886ae2ae0..b6f5f973f4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
@@ -39,7 +39,7 @@ class HeadersBinding
{
private static final Logger _logger = Logger.getLogger(HeadersBinding.class);
- private final FieldTable _mappings;
+ private final Map<String,Object> _mappings;
private final Binding _binding;
private final Set<String> required = new HashSet<String>();
private final Map<String,Object> matches = new HashMap<String,Object>();
@@ -58,7 +58,7 @@ class HeadersBinding
_binding = binding;
if(_binding !=null)
{
- _mappings = FieldTable.convertToFieldTable(_binding.getArguments());
+ _mappings = _binding.getArguments();
initMappings();
}
else
@@ -69,37 +69,23 @@ class HeadersBinding
private void initMappings()
{
- _mappings.processOverElements(new FieldTable.FieldTableElementProcessor()
+ for(Map.Entry<String, Object> entry : _mappings.entrySet())
{
-
- public boolean processElement(String propertyName, AMQTypedValue value)
+ String propertyName = entry.getKey();
+ Object value = entry.getValue();
+ if (isSpecial(propertyName))
{
- if (isSpecial(propertyName))
- {
- processSpecial(propertyName, value.getValue());
- }
- else if (value.getValue() == null || value.getValue().equals(""))
- {
- required.add(propertyName);
- }
- else
- {
- matches.put(propertyName,value.getValue());
- }
-
- return true;
+ processSpecial(propertyName, value);
}
-
- public Object getResult()
+ else if (value == null || value.equals(""))
{
- return null;
+ required.add(propertyName);
}
- });
- }
-
- protected FieldTable getMappings()
- {
- return _mappings;
+ else
+ {
+ matches.put(propertyName,value);
+ }
+ }
}
public Binding getBinding()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
index de12da74b4..295a7191e7 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
@@ -146,6 +146,33 @@ public class HeadersExchange extends AbstractExchange
return new ArrayList<BaseQueue>(queues);
}
+
+ public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue)
+ {
+ CopyOnWriteArraySet<Binding> bindings;
+ if(bindingKey == null)
+ {
+ bindings = new CopyOnWriteArraySet<Binding>(getBindings());
+ }
+ else
+ {
+ bindings = _bindingsByKey.get(bindingKey);
+ }
+
+ if(bindings != null)
+ {
+ for(Binding binding : bindings)
+ {
+ if(queue == null || binding.getQueue().equals(queue))
+ {
+ return arguments == null ? binding.getArguments() == null : binding.getArguments().equals(arguments);
+ }
+ }
+ }
+
+ return false;
+ }
+
public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
{
//fixme isBound here should take the arguements in to consideration.
@@ -251,10 +278,11 @@ public class HeadersExchange extends AbstractExchange
{
bindings.remove(binding);
}
-
+
+ boolean removedBinding = _bindingHeaderMatchers.remove(new HeadersBinding(binding));
if(_logger.isDebugEnabled())
{
- _logger.debug("Removing Binding: " + _bindingHeaderMatchers.remove(new HeadersBinding(binding)));
+ _logger.debug("Removing Binding: " + removedBinding);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
index 6d7242a78d..e4c452a5d6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
@@ -20,13 +20,23 @@
*/
package org.apache.qpid.server.exchange;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.management.JMException;
import org.apache.log4j.Logger;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQInvalidArgumentException;
import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.filter.SelectorParsingException;
+import org.apache.qpid.filter.selector.ParseException;
import org.apache.qpid.filter.selector.TokenMgrError;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
@@ -36,23 +46,11 @@ import org.apache.qpid.server.exchange.topic.TopicMatcherResult;
import org.apache.qpid.server.exchange.topic.TopicNormalizer;
import org.apache.qpid.server.exchange.topic.TopicParser;
import org.apache.qpid.server.filter.JMSSelectorFilter;
-import org.apache.qpid.filter.selector.ParseException;
import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import javax.management.JMException;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.WeakHashMap;
-import java.util.concurrent.ConcurrentHashMap;
-
public class TopicExchange extends AbstractExchange
{
@@ -275,6 +273,28 @@ public class TopicExchange extends AbstractExchange
}
}
+ public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue)
+ {
+ Binding binding = new Binding(null, bindingKey, queue, this, arguments);
+ if (arguments == null)
+ {
+ return _bindings.containsKey(binding);
+ }
+ else
+ {
+ FieldTable o = _bindings.get(binding);
+ if (o != null)
+ {
+ return arguments.equals(FieldTable.convertToMap(o));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ }
+
public boolean isBound(AMQShortString routingKey, AMQQueue queue)
{
return isBound(routingKey, null, queue);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
index 81e2e5557a..6d55f31ebc 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
@@ -26,6 +26,7 @@ import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQUnknownExchangeType;
import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ExchangeDeclareBody;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.protocol.AMQConstant;
@@ -65,26 +66,39 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange
throw body.getChannelNotFoundException(channelId);
}
+ final AMQShortString exchangeName = body.getExchange();
if (_logger.isDebugEnabled())
{
- _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + body.getExchange());
+ _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + exchangeName);
}
synchronized(exchangeRegistry)
{
- Exchange exchange = exchangeRegistry.getExchange(body.getExchange());
+ Exchange exchange = exchangeRegistry.getExchange(exchangeName);
if (exchange == null)
{
if(body.getPassive() && ((body.getType() == null) || body.getType().length() ==0))
{
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + body.getExchange());
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName);
+ }
+ else if(exchangeName.startsWith("amq."))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Attempt to declare exchange: " + exchangeName +
+ " which begins with reserved prefix 'amq.'.");
+ }
+ else if(exchangeName.startsWith("qpid."))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Attempt to declare exchange: " + exchangeName +
+ " which begins with reserved prefix 'qpid.'.");
}
else
{
try
{
- exchange = exchangeFactory.createExchange(body.getExchange() == null ? null : body.getExchange().intern(),
+ exchange = exchangeFactory.createExchange(exchangeName == null ? null : exchangeName.intern(),
body.getType() == null ? null : body.getType().intern(),
body.getDurable(),
body.getPassive(), body.getTicket());
@@ -97,14 +111,15 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange
}
catch(AMQUnknownExchangeType e)
{
- throw body.getConnectionException(AMQConstant.COMMAND_INVALID, "Unknown exchange: " + body.getExchange(),e);
+ throw body.getConnectionException(AMQConstant.COMMAND_INVALID, "Unknown exchange: " + exchangeName,e);
}
}
}
else if (!exchange.getTypeShortString().equals(body.getType()) && !((body.getType() == null || body.getType().length() ==0) && body.getPassive()))
{
- throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + body.getExchange() + " of type " + exchange.getTypeShortString() + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null);
+ throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " +
+ exchangeName + " of type " + exchange.getTypeShortString() + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null);
}
}
if(!body.getNowait())
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties
index fadc2e2098..9ef58df940 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties
@@ -31,3 +31,9 @@ RECOVERY_START = TXN-1004 : Recovery Start[ : {0}]
RECOVERED = TXN-1005 : Recovered {0,number} messages for queue {1}
# 0 - queue name
RECOVERY_COMPLETE = TXN-1006 : Recovery Complete[ : {0}]
+# 0 - xid
+# 1 - queue name
+XA_INCOMPLETE_QUEUE = TXN-1007 : XA transaction recover for xid {0} incomplete as it references a queue {1} which was not durably retained
+# 0 - xid format
+# 1 - message id
+XA_INCOMPLETE_MESSAGE = TXN-1008 : XA transaction recover for xid {0} incomplete as it references a message {1} which was not durably retained
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
index a3da598bdf..e643338c3d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
@@ -34,7 +34,6 @@ import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.List;
@@ -141,10 +140,9 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
public List<QueueEntry> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition);
- void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName,
- ServerTransaction transaction);
+ void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName);
- void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction transaction);
+ void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName);
void removeMessagesFromQueue(long fromMessageId, long toMessageId);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
index 7c59097965..b0d4cb3486 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
@@ -36,8 +36,6 @@ import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.txn.LocalTransaction;
-import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.transport.MessageProperties;
import javax.management.JMException;
@@ -613,9 +611,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
}
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore());
- _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn);
- txn.commit();
+ _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName);
}
/**
@@ -648,11 +644,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
}
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore());
-
- _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn);
-
- txn.commit();
+ _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName);
}
/**
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
index fea5303e23..6c9e918324 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
@@ -417,11 +417,19 @@ public abstract class QueueEntryImpl implements QueueEntry
if (alternateExchange != null)
{
- final List<? extends BaseQueue> rerouteQueues = alternateExchange.route(new InboundMessageAdapter(this));
+ InboundMessageAdapter inboundMessageAdapter = new InboundMessageAdapter(this);
+ List<? extends BaseQueue> queues = alternateExchange.route(inboundMessageAdapter);
final ServerMessage message = getMessage();
- if (rerouteQueues != null && rerouteQueues.size() != 0)
+ if ((queues == null || queues.size() == 0) && alternateExchange.getAlternateExchange() != null)
{
+ queues = alternateExchange.getAlternateExchange().route(inboundMessageAdapter);
+ }
+
+
+ if (queues != null && queues.size() != 0)
+ {
+ final List<? extends BaseQueue> rerouteQueues = queues;
ServerTransaction txn = new LocalTransaction(getQueue().getVirtualHost().getMessageStore());
txn.enqueue(rerouteQueues, message, new ServerTransaction.Action()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
index 891a492b7f..30c2846732 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
@@ -1198,19 +1198,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public void moveMessagesToAnotherQueue(final long fromMessageId,
final long toMessageId,
- String queueName,
- ServerTransaction txn) throws IllegalArgumentException
+ String destinationQueueName) throws IllegalArgumentException
{
- final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (toQueue == null)
- {
- throw new IllegalArgumentException("Queue '" + queueName + "' is not registered with the virtualhost.");
- }
- else if (toQueue == this)
- {
- throw new IllegalArgumentException("The destination queue cant be the same as the source queue");
- }
+ final AMQQueue toQueue = getValidatedDestinationQueue(destinationQueueName);
List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
{
@@ -1230,65 +1221,68 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
});
-
- // Move the messages in on the message store.
- for (final QueueEntry entry : entries)
+ final ServerTransaction txn = new LocalTransaction(getVirtualHost().getMessageStore());
+ boolean shouldRollback = true;
+ try
{
- final ServerMessage message = entry.getMessage();
- txn.enqueue(toQueue, message,
- new ServerTransaction.Action()
- {
-
- public void postCommit()
+ // Move the messages in on the message store.
+ for (final QueueEntry entry : entries)
+ {
+ final ServerMessage message = entry.getMessage();
+ txn.enqueue(toQueue, message,
+ new ServerTransaction.Action()
{
- try
+
+ public void postCommit()
{
- toQueue.enqueue(message);
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
}
- catch (AMQException e)
+
+ public void onRollback()
{
- throw new RuntimeException(e);
+ entry.release();
}
- }
-
- public void onRollback()
+ });
+ txn.dequeue(this, message,
+ new ServerTransaction.Action()
{
- entry.release();
- }
- });
- txn.dequeue(this, message,
- new ServerTransaction.Action()
- {
- public void postCommit()
- {
- entry.discard();
- }
-
- public void onRollback()
- {
+ public void postCommit()
+ {
+ entry.discard();
+ }
- }
- });
+ public void onRollback()
+ {
+ }
+ });
+ }
+ txn.commit();
+ shouldRollback = false;
+ }
+ finally
+ {
+ if (shouldRollback)
+ {
+ txn.rollback();
+ }
}
}
public void copyMessagesToAnotherQueue(final long fromMessageId,
final long toMessageId,
- String queueName,
- final ServerTransaction txn) throws IllegalArgumentException
+ String destinationQueueName) throws IllegalArgumentException
{
- final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (toQueue == null)
- {
- throw new IllegalArgumentException("Queue '" + queueName + "' is not registered with the virtualhost.");
- }
- else if (toQueue == this)
- {
- throw new IllegalArgumentException("The destination queue cant be the same as the source queue");
- }
+ final AMQQueue toQueue = getValidatedDestinationQueue(destinationQueueName);
List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
{
@@ -1306,36 +1300,63 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
});
-
- // Move the messages in on the message store.
- for (QueueEntry entry : entries)
+ final ServerTransaction txn = new LocalTransaction(_virtualHost.getMessageStore());
+ boolean shouldRollback = true;
+ try
{
- final ServerMessage message = entry.getMessage();
-
- txn.enqueue(toQueue, message, new ServerTransaction.Action()
+ // Copy the messages in on the message store.
+ for (QueueEntry entry : entries)
{
- public void postCommit()
+ final ServerMessage message = entry.getMessage();
+
+ txn.enqueue(toQueue, message, new ServerTransaction.Action()
{
- try
+ public void postCommit()
{
- toQueue.enqueue(message);
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
}
- catch (AMQException e)
+
+ public void onRollback()
{
- throw new RuntimeException(e);
}
- }
+ });
- public void onRollback()
- {
-
- }
- });
+ }
+ txn.commit();
+ shouldRollback = false;
+ }
+ finally
+ {
+ if (shouldRollback)
+ {
+ txn.rollback();
+ }
}
}
+ private AMQQueue getValidatedDestinationQueue(String queueName)
+ {
+ final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
+ if (toQueue == null)
+ {
+ throw new IllegalArgumentException("Queue '" + queueName + "' is not registered with the virtualhost.");
+ }
+ else if (toQueue == this)
+ {
+ throw new IllegalArgumentException("The destination queue can't be the same as the source queue");
+ }
+ return toQueue;
+ }
+
public void removeMessagesFromQueue(long fromMessageId, long toMessageId)
{
@@ -1515,10 +1536,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
for(final QueueEntry entry : entries)
{
adapter.setEntry(entry);
- final List<? extends BaseQueue> rerouteQueues = _alternateExchange.route(adapter);
+ List<? extends BaseQueue> queues = _alternateExchange.route(adapter);
+ if((queues == null || queues.size() == 0) && _alternateExchange.getAlternateExchange() != null)
+ {
+ queues = _alternateExchange.getAlternateExchange().route(adapter);
+ }
+
final ServerMessage message = entry.getMessage();
- if(rerouteQueues != null && rerouteQueues.size() != 0)
+ if(queues != null && queues.size() != 0)
{
+ final List<? extends BaseQueue> rerouteQueues = queues;
txn.enqueue(rerouteQueues, entry.getMessage(),
new ServerTransaction.Action()
{
@@ -1895,7 +1922,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if(context != null)
{
QueueEntry releasedNode = context.getReleasedEntry();
- return releasedNode == null || releasedNode.compareTo(entry) < 0;
+ return releasedNode != null && releasedNode.compareTo(entry) < 0;
}
else
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
index 224d694932..9951f7d3c8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
@@ -186,19 +186,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
_qmfService = qmfService;
}
- static
- {
- Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownService()));
- }
-
- private static class ShutdownService implements Runnable
- {
- public void run()
- {
- remove();
- }
- }
-
public static void initialise(IApplicationRegistry instance) throws Exception
{
if(instance == null)
@@ -273,7 +260,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
_logger.info("Shutting down ApplicationRegistry(" + instance + ")");
}
instance.close();
- instance.getBroker().getSystem().removeBroker(instance.getBroker());
}
}
catch (Exception e)
@@ -536,35 +522,49 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
}
}
-
public void close()
{
if (_logger.isInfoEnabled())
{
_logger.info("Shutting down ApplicationRegistry:" + this);
}
-
- //Stop Statistics Reporting
- if (_reportingTimer != null)
+
+ //Set the Actor for Broker Shutdown
+ CurrentActor.set(new BrokerActor(getRootMessageLogger()));
+ try
{
- _reportingTimer.cancel();
- }
+ //Stop Statistics Reporting
+ if (_reportingTimer != null)
+ {
+ _reportingTimer.cancel();
+ }
+
+ //Stop incoming connections
+ unbind();
- //Stop incoming connections
- unbind();
+ //Shutdown virtualhosts
+ close(_virtualHostRegistry);
- //Shutdown virtualhosts
- close(_virtualHostRegistry);
+ close(_authenticationManager);
- close(_authenticationManager);
+ close(_qmfService);
- close(_qmfService);
+ close(_pluginManager);
- close(_pluginManager);
+ close(_managedObjectRegistry);
- close(_managedObjectRegistry);
+ BrokerConfig broker = getBroker();
+ if(broker != null)
+ {
+ broker.getSystem().removeBroker(broker);
+ }
- CurrentActor.get().message(BrokerMessages.STOPPED());
+ CurrentActor.get().message(BrokerMessages.STOPPED());
+ }
+ finally
+ {
+ CurrentActor.remove();
+ }
}
private void unbind()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
index e9ba2764e5..b28e3d6c89 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
@@ -25,8 +25,6 @@ import org.osgi.framework.BundleContext;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.logging.actors.BrokerActor;
-import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.management.JMXManagedObjectRegistry;
import org.apache.qpid.server.management.NoopManagedObjectRegistry;
@@ -45,22 +43,6 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
}
@Override
- public void close()
- {
- //Set the Actor for Broker Shutdown
- CurrentActor.set(new BrokerActor(getRootMessageLogger()));
- try
- {
- super.close();
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
-
- @Override
protected void initialiseManagedObjectRegistry() throws AMQException
{
if (getConfiguration().getManagementEnabled())
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
index 2877e25645..2cc9a5423e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
@@ -92,7 +92,9 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
private static final String LINKS_TABLE_NAME = "QPID_LINKS";
private static final String BRIDGES_TABLE_NAME = "QPID_BRIDGES";
-
+ private static final String XID_TABLE_NAME = "QPID_XIDS";
+ private static final String XID_ACTIONS_TABLE_NAME = "QPID_XID_ACTIONS";
+
private static final int DB_VERSION = 3;
@@ -190,6 +192,31 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
+ "arguments )"
+ " values (?, ?, ?, ?, ?, ?)";
+ private static final String CREATE_XIDS_TABLE =
+ "CREATE TABLE "+XID_TABLE_NAME+" ( format bigint not null,"
+ + " global_id varchar(64) for bit data, branch_id varchar(64) for bit data, PRIMARY KEY ( format, " +
+ "global_id, branch_id ))";
+ private static final String INSERT_INTO_XIDS =
+ "INSERT INTO "+XID_TABLE_NAME+" ( format, global_id, branch_id ) values (?, ?, ?)";
+ private static final String DELETE_FROM_XIDS = "DELETE FROM " + XID_TABLE_NAME
+ + " WHERE format = ? and global_id = ? and branch_id = ?";
+ private static final String SELECT_ALL_FROM_XIDS = "SELECT format, global_id, branch_id FROM " + XID_TABLE_NAME;
+
+
+ private static final String CREATE_XID_ACTIONS_TABLE =
+ "CREATE TABLE "+XID_ACTIONS_TABLE_NAME+" ( format bigint not null,"
+ + " global_id varchar(64) for bit data not null, branch_id varchar(64) for bit data not null, " +
+ "action_type char not null, queue_name varchar(255) not null, message_id bigint not null" +
+ ", PRIMARY KEY ( " +
+ "format, global_id, branch_id, action_type, queue_name, message_id))";
+ private static final String INSERT_INTO_XID_ACTIONS =
+ "INSERT INTO "+XID_ACTIONS_TABLE_NAME+" ( format, global_id, branch_id, action_type, " +
+ "queue_name, message_id ) values (?,?,?,?,?,?) ";
+ private static final String DELETE_FROM_XID_ACTIONS = "DELETE FROM " + XID_ACTIONS_TABLE_NAME
+ + " WHERE format = ? and global_id = ? and branch_id = ?";
+ private static final String SELECT_ALL_FROM_XID_ACTIONS =
+ "SELECT action_type, queue_name, message_id FROM " + XID_ACTIONS_TABLE_NAME +
+ " WHERE format = ? and global_id = ? and branch_id = ?";
private static final String DERBY_SINGLE_DB_SHUTDOWN_CODE = "08006";
@@ -295,7 +322,8 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
_configured = true;
}
- recoverQueueEntries(recoveryHandler);
+ TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh = recoverQueueEntries(recoveryHandler);
+ recoverXids(dtxrh);
}
@@ -350,7 +378,8 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
createMessageContentTable(conn);
createLinkTable(conn);
createBridgeTable(conn);
-
+ createXidTable(conn);
+ createXidActionTable(conn);
conn.close();
}
@@ -519,8 +548,38 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
+ private void createXidTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(XID_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute(CREATE_XIDS_TABLE);
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ }
+ private void createXidActionTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(XID_ACTIONS_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute(CREATE_XID_ACTIONS_TABLE);
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ }
private boolean tableExists(final String tableName, final Connection conn) throws SQLException
{
@@ -1726,6 +1785,126 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
+
+ private void removeXid(ConnectionWrapper connWrapper, long format, byte[] globalId, byte[] branchId)
+ throws AMQStoreException
+ {
+ Connection conn = connWrapper.getConnection();
+
+
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_XIDS);
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2,globalId);
+ stmt.setBytes(3,branchId);
+ int results = stmt.executeUpdate();
+
+
+
+ if(results != 1)
+ {
+ throw new AMQStoreException("Unable to find message with xid");
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ stmt = conn.prepareStatement(DELETE_FROM_XID_ACTIONS);
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2,globalId);
+ stmt.setBytes(3,branchId);
+ int results = stmt.executeUpdate();
+
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ }
+ catch (SQLException e)
+ {
+ _logger.error("Failed to dequeue: " + e.getMessage(), e);
+ throw new AMQStoreException("Error deleting enqueued message with xid", e);
+ }
+
+ }
+
+
+ private void recordXid(ConnectionWrapper connWrapper, long format, byte[] globalId, byte[] branchId,
+ Transaction.Record[] enqueues, Transaction.Record[] dequeues) throws AMQStoreException
+ {
+ Connection conn = connWrapper.getConnection();
+
+
+ try
+ {
+
+ PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_XIDS);
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2, globalId);
+ stmt.setBytes(3, branchId);
+ stmt.executeUpdate();
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ stmt = conn.prepareStatement(INSERT_INTO_XID_ACTIONS);
+
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2, globalId);
+ stmt.setBytes(3, branchId);
+
+ if(enqueues != null)
+ {
+ stmt.setString(4, "E");
+ for(Transaction.Record record : enqueues)
+ {
+ stmt.setString(5, record.getQueue().getResourceName());
+ stmt.setLong(6, record.getMessage().getMessageNumber());
+ stmt.executeUpdate();
+ }
+ }
+
+ if(dequeues != null)
+ {
+ stmt.setString(4, "D");
+ for(Transaction.Record record : dequeues)
+ {
+ stmt.setString(5, record.getQueue().getResourceName());
+ stmt.setLong(6, record.getMessage().getMessageNumber());
+ stmt.executeUpdate();
+ }
+ }
+
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ }
+ catch (SQLException e)
+ {
+ _logger.error("Failed to enqueue: " + e.getMessage(), e);
+ throw new AMQStoreException("Error writing xid ", e);
+ }
+
+ }
+
private static final class ConnectionWrapper
{
private final Connection _connection;
@@ -1919,7 +2098,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
- private void recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) throws SQLException
+ private TransactionLogRecoveryHandler.DtxRecordRecoveryHandler recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) throws SQLException
{
Connection conn = newAutoCommitConnection();
try
@@ -1950,7 +2129,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
stmt.close();
}
- queueEntryHandler.completeQueueEntryRecovery();
+ return queueEntryHandler.completeQueueEntryRecovery();
}
finally
{
@@ -1958,6 +2137,165 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
+ private static final class Xid
+ {
+
+ private final long _format;
+ private final byte[] _globalId;
+ private final byte[] _branchId;
+
+ public Xid(long format, byte[] globalId, byte[] branchId)
+ {
+ _format = format;
+ _globalId = globalId;
+ _branchId = branchId;
+ }
+
+ public long getFormat()
+ {
+ return _format;
+ }
+
+ public byte[] getGlobalId()
+ {
+ return _globalId;
+ }
+
+ public byte[] getBranchId()
+ {
+ return _branchId;
+ }
+ }
+
+ private static class RecordImpl implements MessageStore.Transaction.Record, TransactionLogResource, EnqueableMessage
+ {
+
+ private final String _queueName;
+ private long _messageNumber;
+
+ public RecordImpl(String queueName, long messageNumber)
+ {
+ _queueName = queueName;
+ _messageNumber = messageNumber;
+ }
+
+ public TransactionLogResource getQueue()
+ {
+ return this;
+ }
+
+ public EnqueableMessage getMessage()
+ {
+ return this;
+ }
+
+ public long getMessageNumber()
+ {
+ return _messageNumber;
+ }
+
+ public boolean isPersistent()
+ {
+ return true;
+ }
+
+ public StoredMessage getStoredMessage()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getResourceName()
+ {
+ return _queueName;
+ }
+ }
+
+ private void recoverXids(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh) throws SQLException
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ List<Xid> xids = new ArrayList<Xid>();
+
+ Statement stmt = conn.createStatement();
+ try
+ {
+ ResultSet rs = stmt.executeQuery(SELECT_ALL_FROM_XIDS);
+ try
+ {
+ while(rs.next())
+ {
+
+ long format = rs.getLong(1);
+ byte[] globalId = rs.getBytes(2);
+ byte[] branchId = rs.getBytes(3);
+ xids.add(new Xid(format, globalId, branchId));
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+
+
+ for(Xid xid : xids)
+ {
+ List<RecordImpl> enqueues = new ArrayList<RecordImpl>();
+ List<RecordImpl> dequeues = new ArrayList<RecordImpl>();
+
+ PreparedStatement pstmt = conn.prepareStatement(SELECT_ALL_FROM_XID_ACTIONS);
+
+ pstmt.setLong(1, xid.getFormat());
+ pstmt.setBytes(2, xid.getGlobalId());
+ pstmt.setBytes(3, xid.getBranchId());
+ try
+ {
+ ResultSet rs = pstmt.executeQuery();
+ try
+ {
+ while(rs.next())
+ {
+
+ String actionType = rs.getString(1);
+ String queueName = rs.getString(2);
+ long messageId = rs.getLong(3);
+
+ RecordImpl record = new RecordImpl(queueName, messageId);
+ List<RecordImpl> records = "E".equals(actionType) ? enqueues : dequeues;
+ records.add(record);
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ pstmt.close();
+ }
+
+ dtxrh.dtxRecord(xid.getFormat(), xid.getGlobalId(), xid.getBranchId(),
+ enqueues.toArray(new RecordImpl[enqueues.size()]),
+ dequeues.toArray(new RecordImpl[dequeues.size()]));
+ }
+
+
+ dtxrh.completeDtxRecordRecovery();
+ }
+ finally
+ {
+ conn.close();
+ }
+
+ }
+
StorableMessageMetaData getMetaData(long messageId) throws SQLException
{
@@ -2175,8 +2513,21 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
{
DerbyMessageStore.this.abortTran(_connWrapper);
}
+
+ public void removeXid(long format, byte[] globalId, byte[] branchId) throws AMQStoreException
+ {
+ DerbyMessageStore.this.removeXid(_connWrapper, format, globalId, branchId);
+ }
+
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ throws AMQStoreException
+ {
+ DerbyMessageStore.this.recordXid(_connWrapper, format, globalId, branchId, enqueues, dequeues);
+ }
}
+
+
private class StoredDerbyMessage implements StoredMessage
{
@@ -2360,4 +2711,4 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
-}
+} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
index 546a81a050..b01e5aa954 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
@@ -78,6 +78,14 @@ public class MemoryMessageStore implements MessageStore, DurableConfigurationSto
{
}
+ public void removeXid(long format, byte[] globalId, byte[] branchId)
+ {
+ }
+
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ {
+ }
+
};
public void configureConfigStore(String name, ConfigurationRecoveryHandler handler, Configuration configuration, LogSubject logSubject) throws Exception
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
index 2fecd5d4be..00bb0449d6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
@@ -21,7 +21,6 @@
package org.apache.qpid.server.store;
import org.apache.commons.configuration.Configuration;
-
import org.apache.qpid.AMQStoreException;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.message.EnqueableMessage;
@@ -126,7 +125,16 @@ public interface MessageStore
void abortTran() throws AMQStoreException;
+ public static interface Record
+ {
+ TransactionLogResource getQueue();
+ EnqueableMessage getMessage();
+ }
+
+ void removeXid(long format, byte[] globalId, byte[] branchId) throws AMQStoreException;
+ void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ throws AMQStoreException;
}
public void configureTransactionLog(String name,
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java
index 802596ed1e..48ca72718b 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java
@@ -28,6 +28,13 @@ public interface TransactionLogRecoveryHandler
{
void queueEntry(String queuename, long messageId);
- void completeQueueEntryRecovery();
+ DtxRecordRecoveryHandler completeQueueEntryRecovery();
+ }
+
+ public static interface DtxRecordRecoveryHandler
+ {
+ void dtxRecord(long format, byte[] globalId, byte[] branchId, MessageStore.Transaction.Record[] enqueues, MessageStore.Transaction.Record[] dequeues);
+
+ void completeDtxRecordRecovery();
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
index 9a7d69b10d..a75467ac42 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
@@ -409,6 +409,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
{
deliveryProps.setTimestamp(origDeliveryProps.getTimestamp());
}
+ if(origDeliveryProps.hasTtl())
+ {
+ deliveryProps.setTtl(origDeliveryProps.getTtl());
+ }
}
@@ -684,7 +688,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
{
entry.setRedelivered();
entry.routeToAlternate();
-
+ if(entry.isAcquiredBy(this))
+ {
+ entry.discard();
+ }
}
void release(final QueueEntry entry, final boolean setRedelivered)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
index a957ef84bf..28d8cb2ec7 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
@@ -231,23 +231,26 @@ public class ServerConnectionDelegate extends ServerDelegate
@Override public void sessionDetach(Connection conn, SessionDetach dtc)
{
- // To ensure a clean detach, we unregister any remaining subscriptions. Unregister ensures
- // that any in-progress delivery (SubFlushRunner/QueueRunner) is completed before the unregister
+ // To ensure a clean detach, we stop any remaining subscriptions. Stop ensures
+ // that any in-progress delivery (SubFlushRunner/QueueRunner) is completed before the stop
// completes.
- unregisterAllSubscriptions(conn, dtc);
+ stopAllSubscriptions(conn, dtc);
+ Session ssn = conn.getSession(dtc.getChannel());
+ ((ServerSession)ssn).setClose(true);
super.sessionDetach(conn, dtc);
}
- private void unregisterAllSubscriptions(Connection conn, SessionDetach dtc)
+ private void stopAllSubscriptions(Connection conn, SessionDetach dtc)
{
final ServerSession ssn = (ServerSession) conn.getSession(dtc.getChannel());
final Collection<Subscription_0_10> subs = ssn.getSubscriptions();
for (Subscription_0_10 subscription_0_10 : subs)
{
- ssn.unregister(subscription_0_10);
+ subscription_0_10.stop();
}
}
+
@Override
public void sessionAttach(final Connection conn, final SessionAttach atc)
{
@@ -305,4 +308,4 @@ public class ServerConnectionDelegate extends ServerDelegate
{
return _clientProperties == null ? null : (String) _clientProperties.get(ConnectionStartProperties.VERSION_0_10);
}
-} \ No newline at end of file
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
index e4268ed2dc..48e372f87e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
@@ -21,6 +21,8 @@
package org.apache.qpid.server.transport;
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT;
+import org.apache.qpid.server.txn.RollbackOnlyDtxException;
+import org.apache.qpid.server.txn.TimeoutDtxException;
import static org.apache.qpid.util.Serial.gt;
import java.security.Principal;
@@ -44,6 +46,7 @@ import java.util.concurrent.atomic.AtomicLong;
import javax.security.auth.Subject;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.server.configuration.ConfigStore;
@@ -67,24 +70,19 @@ import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.subscription.Subscription_0_10;
+import org.apache.qpid.server.txn.AlreadyKnownDtxException;
import org.apache.qpid.server.txn.AsyncAutoCommitTransaction;
+import org.apache.qpid.server.txn.DistributedTransaction;
+import org.apache.qpid.server.txn.DtxNotSelectedException;
+import org.apache.qpid.server.txn.IncorrectDtxStateException;
+import org.apache.qpid.server.txn.JoinAndResumeDtxException;
import org.apache.qpid.server.txn.LocalTransaction;
+import org.apache.qpid.server.txn.NotAssociatedDtxException;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.SuspendAndFailDtxException;
+import org.apache.qpid.server.txn.UnknownDtxBranchException;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.transport.Binary;
-import org.apache.qpid.transport.Connection;
-import org.apache.qpid.transport.MessageCreditUnit;
-import org.apache.qpid.transport.MessageFlow;
-import org.apache.qpid.transport.MessageFlowMode;
-import org.apache.qpid.transport.MessageSetFlowMode;
-import org.apache.qpid.transport.MessageStop;
-import org.apache.qpid.transport.MessageTransfer;
-import org.apache.qpid.transport.Method;
-import org.apache.qpid.transport.Range;
-import org.apache.qpid.transport.RangeSet;
-import org.apache.qpid.transport.RangeSetFactory;
-import org.apache.qpid.transport.Session;
-import org.apache.qpid.transport.SessionDelegate;
+import org.apache.qpid.transport.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -109,7 +107,6 @@ public class ServerSession extends Session
private ChannelLogSubject _logSubject;
private final AtomicInteger _outstandingCredit = new AtomicInteger(UNLIMITED_CREDIT);
-
public static interface MessageDispositionChangeListener
{
public void onAccept();
@@ -359,7 +356,15 @@ public class ServerSession extends Session
public void onClose()
{
- _transaction.rollback();
+ if(_transaction instanceof LocalTransaction)
+ {
+ _transaction.rollback();
+ }
+ else if(_transaction instanceof DistributedTransaction)
+ {
+ getVirtualHost().getDtxRegistry().endAssociations(this);
+ }
+
for(MessageDispositionChangeListener listener : _messageDispositionListenerMap.values())
{
listener.onRelease(true);
@@ -455,6 +460,95 @@ public class ServerSession extends Session
_txnStarts.incrementAndGet();
}
+ public void selectDtx()
+ {
+ _transaction = new DistributedTransaction(this, getMessageStore(), getVirtualHost());
+
+ }
+
+
+ public void startDtx(Xid xid, boolean join, boolean resume)
+ throws JoinAndResumeDtxException,
+ UnknownDtxBranchException,
+ AlreadyKnownDtxException,
+ DtxNotSelectedException
+ {
+ DistributedTransaction distributedTransaction = assertDtxTransaction();
+ distributedTransaction.start(xid, join, resume);
+ }
+
+
+ public void endDtx(Xid xid, boolean fail, boolean suspend)
+ throws NotAssociatedDtxException,
+ UnknownDtxBranchException,
+ DtxNotSelectedException,
+ SuspendAndFailDtxException, TimeoutDtxException
+ {
+ DistributedTransaction distributedTransaction = assertDtxTransaction();
+ distributedTransaction.end(xid, fail, suspend);
+ }
+
+
+ public long getTimeoutDtx(Xid xid)
+ throws UnknownDtxBranchException
+ {
+ return getVirtualHost().getDtxRegistry().getTimeout(xid);
+ }
+
+
+ public void setTimeoutDtx(Xid xid, long timeout)
+ throws UnknownDtxBranchException
+ {
+ getVirtualHost().getDtxRegistry().setTimeout(xid, timeout);
+ }
+
+
+ public void prepareDtx(Xid xid)
+ throws UnknownDtxBranchException,
+ IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException
+ {
+ getVirtualHost().getDtxRegistry().prepare(xid);
+ }
+
+ public void commitDtx(Xid xid, boolean onePhase)
+ throws UnknownDtxBranchException,
+ IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException
+ {
+ getVirtualHost().getDtxRegistry().commit(xid, onePhase);
+ }
+
+
+ public void rollbackDtx(Xid xid)
+ throws UnknownDtxBranchException,
+ IncorrectDtxStateException, AMQStoreException, TimeoutDtxException
+ {
+ getVirtualHost().getDtxRegistry().rollback(xid);
+ }
+
+
+ public void forgetDtx(Xid xid) throws UnknownDtxBranchException, IncorrectDtxStateException
+ {
+ getVirtualHost().getDtxRegistry().forget(xid);
+ }
+
+ public List<Xid> recoverDtx()
+ {
+ return getVirtualHost().getDtxRegistry().recover();
+ }
+
+ private DistributedTransaction assertDtxTransaction() throws DtxNotSelectedException
+ {
+ if(_transaction instanceof DistributedTransaction)
+ {
+ return (DistributedTransaction) _transaction;
+ }
+ else
+ {
+ throw new DtxNotSelectedException();
+ }
+ }
+
+
public void commit()
{
_transaction.commit();
@@ -704,7 +798,7 @@ public class ServerSession extends Session
{
if(_blockingQueues.remove(queue) && _blockingQueues.isEmpty())
{
- if(_blocking.compareAndSet(true,false))
+ if(_blocking.compareAndSet(true,false) && !isClosing())
{
_actor.message(_logSubject, ChannelMessages.FLOW_REMOVED());
@@ -759,6 +853,16 @@ public class ServerSession extends Session
}
}
+ void stopSubscriptions()
+ {
+ final Collection<Subscription_0_10> subscriptions = getSubscriptions();
+ for (Subscription_0_10 subscription_0_10 : subscriptions)
+ {
+ subscription_0_10.stop();
+ }
+ }
+
+
public void receivedComplete()
{
final Collection<Subscription_0_10> subscriptions = getSubscriptions();
@@ -900,7 +1004,11 @@ public class ServerSession extends Session
}
}
- @Override
+ protected void setClose(boolean close)
+ {
+ super.setClose(close);
+ }
+
public int compareTo(AMQSessionModel session)
{
return getId().toString().compareTo(session.getID().toString());
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
index 8e4fb3635b..d18086808f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.transport;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
import org.apache.qpid.AMQUnknownExchangeType;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
@@ -50,7 +51,16 @@ import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.subscription.Subscription_0_10;
+import org.apache.qpid.server.txn.AlreadyKnownDtxException;
+import org.apache.qpid.server.txn.DtxNotSelectedException;
+import org.apache.qpid.server.txn.IncorrectDtxStateException;
+import org.apache.qpid.server.txn.JoinAndResumeDtxException;
+import org.apache.qpid.server.txn.NotAssociatedDtxException;
+import org.apache.qpid.server.txn.RollbackOnlyDtxException;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.SuspendAndFailDtxException;
+import org.apache.qpid.server.txn.TimeoutDtxException;
+import org.apache.qpid.server.txn.UnknownDtxBranchException;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.*;
@@ -199,6 +209,10 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
}
+ else if(queue.isExclusive() && queue.getExclusiveOwningSession() != null && queue.getExclusiveOwningSession() != session)
+ {
+ exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
+ }
else
{
if(queue.isExclusive())
@@ -221,7 +235,6 @@ public class ServerSessionDelegate extends SessionDelegate
}
});
}
-
}
FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L);
@@ -426,6 +439,235 @@ public class ServerSessionDelegate extends SessionDelegate
((ServerSession)session).rollback();
}
+ @Override
+ public void dtxSelect(Session session, DtxSelect method)
+ {
+ // TODO - check current tx mode
+ ((ServerSession)session).selectDtx();
+ }
+
+ @Override
+ public void dtxStart(Session session, DtxStart method)
+ {
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ ((ServerSession)session).startDtx(method.getXid(), method.getJoin(), method.getResume());
+ session.executionResult(method.getId(), result);
+ }
+ catch(JoinAndResumeDtxException e)
+ {
+ exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage());
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Unknown xid " + method.getXid());
+ }
+ catch(AlreadyKnownDtxException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Xid already started an neither join nor " +
+ "resume set" + method.getXid());
+ }
+ catch(DtxNotSelectedException e)
+ {
+ exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage());
+ }
+
+ }
+
+ @Override
+ public void dtxEnd(Session session, DtxEnd method)
+ {
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ try
+ {
+ ((ServerSession)session).endDtx(method.getXid(), method.getFail(), method.getSuspend());
+ }
+ catch (TimeoutDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBTIMEOUT);
+ }
+ session.executionResult(method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(NotAssociatedDtxException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(DtxNotSelectedException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(SuspendAndFailDtxException e)
+ {
+ exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage());
+ }
+
+ }
+
+ @Override
+ public void dtxCommit(Session session, DtxCommit method)
+ {
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ try
+ {
+ ((ServerSession)session).commitDtx(method.getXid(), method.getOnePhase());
+ }
+ catch (RollbackOnlyDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBROLLBACK);
+ }
+ catch (TimeoutDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBTIMEOUT);
+ }
+ session.executionResult(method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ catch(IncorrectDtxStateException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(AMQStoreException e)
+ {
+ exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage());
+ }
+ }
+
+ @Override
+ public void dtxForget(Session session, DtxForget method)
+ {
+ try
+ {
+ ((ServerSession)session).forgetDtx(method.getXid());
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ catch(IncorrectDtxStateException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+
+ }
+
+ @Override
+ public void dtxGetTimeout(Session session, DtxGetTimeout method)
+ {
+ GetTimeoutResult result = new GetTimeoutResult();
+ try
+ {
+ result.setTimeout(((ServerSession) session).getTimeoutDtx(method.getXid()));
+ session.executionResult(method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ }
+
+ @Override
+ public void dtxPrepare(Session session, DtxPrepare method)
+ {
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ try
+ {
+ ((ServerSession)session).prepareDtx(method.getXid());
+ }
+ catch (RollbackOnlyDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBROLLBACK);
+ }
+ catch (TimeoutDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBTIMEOUT);
+ }
+ session.executionResult((int) method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ catch(IncorrectDtxStateException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(AMQStoreException e)
+ {
+ exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage());
+ }
+ }
+
+ @Override
+ public void dtxRecover(Session session, DtxRecover method)
+ {
+ RecoverResult result = new RecoverResult();
+ List inDoubt = ((ServerSession)session).recoverDtx();
+ result.setInDoubt(inDoubt);
+ session.executionResult(method.getId(), result);
+ }
+
+ @Override
+ public void dtxRollback(Session session, DtxRollback method)
+ {
+
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ try
+ {
+ ((ServerSession)session).rollbackDtx(method.getXid());
+ }
+ catch (TimeoutDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBTIMEOUT);
+ }
+ session.executionResult(method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ catch(IncorrectDtxStateException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(AMQStoreException e)
+ {
+ exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage());
+ }
+ }
+
+ @Override
+ public void dtxSetTimeout(Session session, DtxSetTimeout method)
+ {
+ try
+ {
+ ((ServerSession)session).setTimeoutDtx(method.getXid(), method.getTimeout());
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ }
@Override
public void executionSync(final Session ssn, final ExecutionSync sync)
@@ -474,48 +716,96 @@ public class ServerSessionDelegate extends SessionDelegate
{
if (exchange == null)
{
- ExchangeRegistry exchangeRegistry = getExchangeRegistry(session);
- ExchangeFactory exchangeFactory = virtualHost.getExchangeFactory();
+ if(exchangeName.startsWith("amq."))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED,
+ "Attempt to declare exchange: " + exchangeName +
+ " which begins with reserved prefix 'amq.'.");
+ }
+ else if(exchangeName.startsWith("qpid."))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED,
+ "Attempt to declare exchange: " + exchangeName +
+ " which begins with reserved prefix 'qpid.'.");
+ }
+ else
+ {
+ ExchangeRegistry exchangeRegistry = getExchangeRegistry(session);
+ ExchangeFactory exchangeFactory = virtualHost.getExchangeFactory();
- try
- {
+ try
+ {
+
+ exchange = exchangeFactory.createExchange(method.getExchange(),
+ method.getType(),
+ method.getDurable(),
+ method.getAutoDelete());
+
+ String alternateExchangeName = method.getAlternateExchange();
+ boolean validAlternate;
+ if(alternateExchangeName != null && alternateExchangeName.length() != 0)
+ {
+ Exchange alternate = getExchange(session, alternateExchangeName);
+ if(alternate == null)
+ {
+ validAlternate = false;
+ }
+ else
+ {
+ exchange.setAlternateExchange(alternate);
+ validAlternate = true;
+ }
+ }
+ else
+ {
+ validAlternate = true;
+ }
- exchange = exchangeFactory.createExchange(method.getExchange(),
- method.getType(),
- method.getDurable(),
- method.getAutoDelete());
+ if(validAlternate)
+ {
+ if (exchange.isDurable())
+ {
+ DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+ store.createExchange(exchange);
+ }
- String alternateExchangeName = method.getAlternateExchange();
- if(alternateExchangeName != null && alternateExchangeName.length() != 0)
+ exchangeRegistry.registerExchange(exchange);
+ }
+ else
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND,
+ "Unknown alternate exchange " + alternateExchangeName);
+ }
+ }
+ catch(AMQUnknownExchangeType e)
{
- Exchange alternate = getExchange(session, alternateExchangeName);
- exchange.setAlternateExchange(alternate);
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "Unknown Exchange Type: " + method.getType());
}
-
- if (exchange.isDurable())
+ catch (AMQException e)
{
- DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
- store.createExchange(exchange);
+ exception(session, method, e, "Cannot declare exchange '" + exchangeName);
}
-
- exchangeRegistry.registerExchange(exchange);
- }
- catch(AMQUnknownExchangeType e)
- {
- exception(session, method, ExecutionErrorCode.NOT_FOUND, "Unknown Exchange Type: " + method.getType());
- }
- catch (AMQException e)
- {
- exception(session, method, e, "Cannot declare exchange '" + exchangeName);
}
}
else
{
if(!exchange.getTypeShortString().toString().equals(method.getType()))
{
- exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to redeclare exchange: " + exchangeName + " of type " + exchange.getTypeShortString() + " to " + method.getType() +".");
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED,
+ "Attempt to redeclare exchange: " + exchangeName
+ + " of type " + exchange.getTypeShortString()
+ + " to " + method.getType() +".");
+ }
+ else if(method.hasAlternateExchange()
+ && (exchange.getAlternateExchange() == null ||
+ !method.getAlternateExchange().equals(exchange.getAlternateExchange().getName())))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED,
+ "Attempt to change alternate exchange of: " + exchangeName
+ + " from " + exchange.getAlternateExchange()
+ + " to " + method.getAlternateExchange() +".");
}
}
@@ -732,10 +1022,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
else
{
- AMQShortString routingKey = new AMQShortString(method.getBindingKey());
- FieldTable fieldTable = FieldTable.convertToFieldTable(method.getArguments());
-
- if (!exchange.isBound(routingKey, fieldTable, queue))
+ if (!exchange.isBound(method.getBindingKey(), method.getArguments(), queue))
{
try
{
@@ -847,12 +1134,6 @@ public class ServerSessionDelegate extends SessionDelegate
if(method.hasBindingKey())
{
- if(method.hasArguments())
- {
- FieldTable args = FieldTable.convertToFieldTable(method.getArguments());
-
- result.setArgsNotMatched(!exchange.isBound(new AMQShortString(method.getBindingKey()), args, queue));
- }
if(queueMatched)
{
result.setKeyNotMatched(!exchange.isBound(method.getBindingKey(), queue));
@@ -861,23 +1142,28 @@ public class ServerSessionDelegate extends SessionDelegate
{
result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
}
+
+ if(method.hasArguments())
+ {
+ result.setArgsNotMatched(!exchange.isBound(result.getKeyNotMatched() ? null : method.getBindingKey(), method.getArguments(), queueMatched ? queue : null));
+ }
+
}
else if (method.hasArguments())
{
- // TODO
-
+ result.setArgsNotMatched(!exchange.isBound(null, method.getArguments(), queueMatched ? queue : null));
}
- result.setQueueNotMatched(!exchange.isBound(queue));
-
}
else if(exchange != null && method.hasBindingKey())
{
+ result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
+
if(method.hasArguments())
{
- // TODO
+ result.setArgsNotMatched(!exchange.isBound(result.getKeyNotMatched() ? null : method.getBindingKey(), method.getArguments(), queue));
}
- result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
+
}
@@ -886,11 +1172,15 @@ public class ServerSessionDelegate extends SessionDelegate
{
if(method.hasArguments())
{
- // TODO
+ result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments(), null));
}
result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
}
+ else if(exchange != null && method.hasArguments())
+ {
+ result.setArgsNotMatched(!exchange.isBound(null, method.getArguments(), null));
+ }
session.executionResult((int) method.getId(), result);
@@ -1134,6 +1424,10 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
}
+ else if(queue.isExclusive() && queue.getExclusiveOwningSession() != null && queue.getExclusiveOwningSession() != session)
+ {
+ exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
+ }
else if (method.getIfEmpty() && !queue.isEmpty())
{
exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Queue " + queueName + " not empty");
@@ -1280,8 +1574,9 @@ public class ServerSessionDelegate extends SessionDelegate
ServerSession serverSession = (ServerSession)session;
- serverSession.unregisterSubscriptions();
+ serverSession.stopSubscriptions();
serverSession.onClose();
+ serverSession.unregisterSubscriptions();
}
@Override
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AlreadyKnownDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AlreadyKnownDtxException.java
new file mode 100644
index 0000000000..faa4ec592f
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AlreadyKnownDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class AlreadyKnownDtxException extends DtxException
+{
+ public AlreadyKnownDtxException(Xid id)
+ {
+ super("Xid " + id + " cannot be started as it is already known");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java
new file mode 100644
index 0000000000..36f5f7b58f
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java
@@ -0,0 +1,246 @@
+/*
+ *
+ * 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.server.txn;
+
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.queue.BaseQueue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.Xid;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class DistributedTransaction implements ServerTransaction
+{
+
+ private final AutoCommitTransaction _autoCommitTransaction;
+
+ private volatile MessageStore.Transaction _transaction;
+
+ private long _txnStartTime = 0L;
+
+ private DtxBranch _branch;
+ private AMQSessionModel _session;
+ private VirtualHost _vhost;
+
+
+ public DistributedTransaction(AMQSessionModel session, MessageStore store, VirtualHost vhost)
+ {
+ _session = session;
+ _vhost = vhost;
+ _autoCommitTransaction = new AutoCommitTransaction(vhost.getMessageStore());
+ }
+
+ public long getTransactionStartTime()
+ {
+ return _txnStartTime;
+ }
+
+ public void addPostTransactionAction(Action postTransactionAction)
+ {
+ if(_branch != null)
+ {
+ _branch.addPostTransactionAcion(postTransactionAction);
+ }
+ else
+ {
+ _autoCommitTransaction.addPostTransactionAction(postTransactionAction);
+ }
+ }
+
+ public void dequeue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
+ {
+ if(_branch != null)
+ {
+ _branch.dequeue(queue, message);
+ _branch.addPostTransactionAcion(postTransactionAction);
+ }
+ else
+ {
+ _autoCommitTransaction.dequeue(queue, message, postTransactionAction);
+ }
+ }
+
+ public void dequeue(Collection<QueueEntry> messages, Action postTransactionAction)
+ {
+ if(_branch != null)
+ {
+ for(QueueEntry entry : messages)
+ {
+ _branch.dequeue(entry.getQueue(), entry.getMessage());
+ }
+ _branch.addPostTransactionAcion(postTransactionAction);
+ }
+ else
+ {
+ _autoCommitTransaction.dequeue(messages, postTransactionAction);
+ }
+ }
+
+ public void enqueue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
+ {
+ if(_branch != null)
+ {
+ _branch.enqueue(queue, message);
+ _branch.addPostTransactionAcion(postTransactionAction);
+ enqueue(Collections.singletonList(queue), message, postTransactionAction, System.currentTimeMillis());
+ }
+ else
+ {
+ _autoCommitTransaction.enqueue(queue, message, postTransactionAction);
+ }
+ }
+
+ public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message,
+ Action postTransactionAction, long currentTime)
+ {
+ if(_branch != null)
+ {
+ for(BaseQueue queue : queues)
+ {
+ _branch.enqueue(queue, message);
+ }
+ _branch.addPostTransactionAcion(postTransactionAction);
+ }
+ else
+ {
+ _autoCommitTransaction.enqueue(queues, message, postTransactionAction, currentTime);
+ }
+ }
+
+ public void commit()
+ {
+ throw new IllegalStateException("Cannot call tx.commit() on a distributed transaction");
+ }
+
+ public void commit(Runnable immediatePostTransactionAction)
+ {
+ throw new IllegalStateException("Cannot call tx.commit() on a distributed transaction");
+ }
+
+ public void rollback()
+ {
+ throw new IllegalStateException("Cannot call tx.rollback() on a distributed transaction");
+ }
+
+ public boolean isTransactional()
+ {
+ return _branch != null;
+ }
+
+ public void start(Xid id, boolean join, boolean resume)
+ throws UnknownDtxBranchException, AlreadyKnownDtxException, JoinAndResumeDtxException
+ {
+ if(join && resume)
+ {
+ throw new JoinAndResumeDtxException(id);
+ }
+
+ DtxBranch branch = _vhost.getDtxRegistry().getBranch(id);
+
+ if(branch == null)
+ {
+ if(join || resume)
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ branch = new DtxBranch(id,_vhost.getMessageStore(), _vhost);
+ if(_vhost.getDtxRegistry().registerBranch(branch))
+ {
+ _branch = branch;
+ branch.associateSession(_session);
+ }
+ else
+ {
+ throw new AlreadyKnownDtxException(id);
+ }
+ }
+ else
+ {
+ if(join)
+ {
+ branch.associateSession(_session);
+ }
+ else if(resume)
+ {
+ branch.resumeSession(_session);
+ }
+ else
+ {
+ throw new AlreadyKnownDtxException(id);
+ }
+ _branch = branch;
+ }
+ }
+
+ public void end(Xid id, boolean fail, boolean suspend)
+ throws UnknownDtxBranchException, NotAssociatedDtxException, SuspendAndFailDtxException, TimeoutDtxException
+ {
+ DtxBranch branch = _vhost.getDtxRegistry().getBranch(id);
+
+ if(suspend && fail)
+ {
+ branch.disassociateSession(_session);
+ _branch = null;
+ throw new SuspendAndFailDtxException(id);
+ }
+
+
+ if(branch == null)
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ else
+ {
+ if(!branch.isAssociated(_session))
+ {
+ throw new NotAssociatedDtxException(id);
+ }
+ if(branch.expired() || branch.getState() == DtxBranch.State.TIMEDOUT)
+ {
+ branch.disassociateSession(_session);
+ throw new TimeoutDtxException(id);
+ }
+
+ if(suspend)
+ {
+ branch.suspendSession(_session);
+ }
+ else
+ {
+ if(fail)
+ {
+ branch.setState(DtxBranch.State.ROLLBACK_ONLY);
+ }
+ branch.disassociateSession(_session);
+ }
+
+ _branch = null;
+
+ }
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
new file mode 100644
index 0000000000..99bb639261
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
@@ -0,0 +1,348 @@
+/*
+ *
+ * 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.server.txn;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ScheduledFuture;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.queue.BaseQueue;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.Xid;
+
+public class DtxBranch
+{
+ private static final Logger _logger = Logger.getLogger(DtxBranch.class);
+
+ private final Xid _xid;
+ private final List<ServerTransaction.Action> _postTransactionActions = new ArrayList<ServerTransaction.Action>();
+ private State _state = State.ACTIVE;
+ private long _timeout;
+ private Map<AMQSessionModel, State> _associatedSessions = new HashMap<AMQSessionModel, State>();
+ private final List<Record> _enqueueRecords = new ArrayList<Record>();
+ private final List<Record> _dequeueRecords = new ArrayList<Record>();
+
+ private MessageStore.Transaction _transaction;
+ private long _expiration;
+ private VirtualHost _vhost;
+ private ScheduledFuture<?> _timeoutFuture;
+ private MessageStore _store;
+
+
+ public enum State
+ {
+ ACTIVE,
+ PREPARED,
+ TIMEDOUT,
+ SUSPENDED,
+ FORGOTTEN,
+ HEUR_COM,
+ HEUR_RB,
+ ROLLBACK_ONLY
+ }
+
+
+ public DtxBranch(Xid xid, MessageStore store, VirtualHost vhost)
+ {
+ _xid = xid;
+ _store = store;
+ _vhost = vhost;
+ }
+
+ public Xid getXid()
+ {
+ return _xid;
+ }
+
+ public State getState()
+ {
+ return _state;
+ }
+
+ public void setState(State state)
+ {
+ _state = state;
+ }
+
+ public long getTimeout()
+ {
+ return _timeout;
+ }
+
+ public void setTimeout(long timeout)
+ {
+ if(_timeoutFuture != null)
+ {
+ _timeoutFuture.cancel(false);
+ }
+ _timeout = timeout;
+ _expiration = timeout == 0 ? 0 : System.currentTimeMillis() + timeout;
+
+ if(_timeout == 0)
+ {
+ _timeoutFuture = null;
+ }
+ else
+ {
+ _timeoutFuture = _vhost.scheduleTask(_timeout, new Runnable()
+ {
+ public void run()
+ {
+ setState(State.TIMEDOUT);
+ try
+ {
+ rollback();
+ }
+ catch (AMQStoreException e)
+ {
+ _logger.error("Unexpected error when attempting to rollback XA transaction ("+
+ _xid + ") due to timeout", e);
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ }
+
+ public boolean expired()
+ {
+ return _timeout != 0 && _expiration < System.currentTimeMillis();
+ }
+
+ public synchronized boolean isAssociated(AMQSessionModel session)
+ {
+ return _associatedSessions.containsKey(session);
+ }
+
+ public synchronized boolean hasAssociatedSessions()
+ {
+ return !_associatedSessions.isEmpty();
+ }
+
+
+ public synchronized boolean hasAssociatedActiveSessions()
+ {
+ if(hasAssociatedSessions())
+ {
+ for(State state : _associatedSessions.values())
+ {
+ if(state != State.SUSPENDED)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public synchronized void clearAssociations()
+ {
+ _associatedSessions.clear();
+ }
+
+ synchronized boolean associateSession(AMQSessionModel associatedSession)
+ {
+ return _associatedSessions.put(associatedSession, State.ACTIVE) != null;
+ }
+
+ synchronized boolean disassociateSession(AMQSessionModel associatedSession)
+ {
+ return _associatedSessions.remove(associatedSession) != null;
+ }
+
+ public synchronized boolean resumeSession(AMQSessionModel session)
+ {
+ if(_associatedSessions.containsKey(session) && _associatedSessions.get(session) == State.SUSPENDED)
+ {
+ _associatedSessions.put(session, State.ACTIVE);
+ return true;
+ }
+ return false;
+ }
+
+ public synchronized boolean suspendSession(AMQSessionModel session)
+ {
+ if(_associatedSessions.containsKey(session) && _associatedSessions.get(session) == State.ACTIVE)
+ {
+ _associatedSessions.put(session, State.SUSPENDED);
+ return true;
+ }
+ return false;
+ }
+
+ public void prepare() throws AMQStoreException
+ {
+
+ MessageStore.Transaction txn = _store.newTransaction();
+ txn.recordXid(_xid.getFormat(),
+ _xid.getGlobalId(),
+ _xid.getBranchId(),
+ _enqueueRecords.toArray(new Record[_enqueueRecords.size()]),
+ _dequeueRecords.toArray(new Record[_dequeueRecords.size()]));
+ txn.commitTran();
+
+ prePrepareTransaction();
+ }
+
+ public synchronized void rollback() throws AMQStoreException
+ {
+ if(_timeoutFuture != null)
+ {
+ _timeoutFuture.cancel(false);
+ _timeoutFuture = null;
+ }
+
+
+ if(_transaction != null)
+ {
+ // prepare has previously been called
+
+ MessageStore.Transaction txn = _store.newTransaction();
+ txn.removeXid(_xid.getFormat(), _xid.getGlobalId(), _xid.getBranchId());
+ txn.commitTran();
+
+ _transaction.abortTran();
+ }
+
+ for(ServerTransaction.Action action : _postTransactionActions)
+ {
+ action.onRollback();
+ }
+ _postTransactionActions.clear();
+ }
+
+ public void commit() throws AMQStoreException
+ {
+ if(_timeoutFuture != null)
+ {
+ _timeoutFuture.cancel(false);
+ _timeoutFuture = null;
+ }
+
+ if(_transaction == null)
+ {
+ prePrepareTransaction();
+ }
+ else
+ {
+ _transaction.removeXid(_xid.getFormat(), _xid.getGlobalId(), _xid.getBranchId());
+ }
+ _transaction.commitTran();
+
+ for(ServerTransaction.Action action : _postTransactionActions)
+ {
+ action.postCommit();
+ }
+ _postTransactionActions.clear();
+ }
+
+ public void prePrepareTransaction() throws AMQStoreException
+ {
+ _transaction = _store.newTransaction();
+
+ for(Record enqueue : _enqueueRecords)
+ {
+ if(enqueue.isDurable())
+ {
+ _transaction.enqueueMessage(enqueue.getQueue(), enqueue.getMessage());
+ }
+ }
+
+
+ for(Record enqueue : _dequeueRecords)
+ {
+ if(enqueue.isDurable())
+ {
+ _transaction.dequeueMessage(enqueue.getQueue(), enqueue.getMessage());
+ }
+ }
+ }
+
+
+ public void addPostTransactionAcion(ServerTransaction.Action postTransactionAction)
+ {
+ _postTransactionActions.add(postTransactionAction);
+ }
+
+
+ public void dequeue(BaseQueue queue, EnqueableMessage message)
+ {
+ _dequeueRecords.add(new Record(queue, message));
+ }
+
+
+ public void enqueue(BaseQueue queue, EnqueableMessage message)
+ {
+ _enqueueRecords.add(new Record(queue, message));
+ }
+
+ private static final class Record implements MessageStore.Transaction.Record
+ {
+ private final BaseQueue _queue;
+ private final EnqueableMessage _message;
+
+ public Record(BaseQueue queue, EnqueableMessage message)
+ {
+ _queue = queue;
+ _message = message;
+ }
+
+ public BaseQueue getQueue()
+ {
+ return _queue;
+ }
+
+ public EnqueableMessage getMessage()
+ {
+ return _message;
+ }
+
+ public boolean isDurable()
+ {
+ return _message.isPersistent() && _queue.isDurable();
+ }
+ }
+
+
+ public void close()
+ {
+ if(_transaction != null)
+ {
+ try
+ {
+ _state = null;
+ _transaction.abortTran();
+ }
+ catch(AMQStoreException e)
+ {
+ _logger.error("Error while closing XA branch", e);
+ }
+ }
+ }
+}
diff --git a/cpp/src/qpid/sys/apr/APRPool.h b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxException.java
index da7661fcfa..d18d0cb68b 100644
--- a/cpp/src/qpid/sys/apr/APRPool.h
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxException.java
@@ -1,6 +1,3 @@
-#ifndef _APRPool_
-#define _APRPool_
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -10,9 +7,9 @@
* 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
@@ -21,30 +18,27 @@
* under the License.
*
*/
-#include <boost/noncopyable.hpp>
-#include <apr_pools.h>
-
-namespace qpid {
-namespace sys {
-/**
- * Singleton APR memory pool.
- */
-class APRPool : private boost::noncopyable {
- public:
- APRPool();
- ~APRPool();
-
- /** Get singleton instance */
- static apr_pool_t* get();
-
- private:
- apr_pool_t* pool;
-};
-
-}}
-
-
-
-
-#endif /*!_APRPool_*/
+package org.apache.qpid.server.txn;
+
+public class DtxException extends Exception
+{
+ public DtxException()
+ {
+ }
+
+ public DtxException(String message)
+ {
+ super(message);
+ }
+
+ public DtxException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public DtxException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/cpp/src/qpid/sys/apr/Time.cpp b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxNotSelectedException.java
index 34e740b144..c1289b1fdd 100644
--- a/cpp/src/qpid/sys/apr/Time.cpp
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxNotSelectedException.java
@@ -7,9 +7,9 @@
* 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
@@ -19,18 +19,12 @@
*
*/
-#include "qpid/sys/Time.h"
-
-#include <apr_time.h>
+package org.apache.qpid.server.txn;
-namespace qpid {
-namespace sys {
-
-AbsTime AbsTime::now() {
- AbsTime time_now;
- time_now.time_ns = apr_time_now() * TIME_USEC;
- return time_now;
+public class DtxNotSelectedException extends DtxException
+{
+ public DtxNotSelectedException()
+ {
+ super("Distribution transactions have not been selected on this session");
+ }
}
-
-}}
-
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java
new file mode 100644
index 0000000000..5c54c1164f
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java
@@ -0,0 +1,333 @@
+/*
+ *
+ * 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.server.txn;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.transport.Xid;
+
+public class DtxRegistry
+{
+ private final Map<ComparableXid, DtxBranch> _branches = new HashMap<ComparableXid, DtxBranch>();
+
+
+ private static final class ComparableXid
+ {
+ private final Xid _xid;
+
+ private ComparableXid(Xid xid)
+ {
+ _xid = xid;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if(this == o)
+ {
+ return true;
+ }
+ if(o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ ComparableXid that = (ComparableXid) o;
+
+ return compareBytes(_xid.getBranchId(), that._xid.getBranchId())
+ && compareBytes(_xid.getGlobalId(), that._xid.getGlobalId());
+ }
+
+ private static boolean compareBytes(byte[] a, byte[] b)
+ {
+ if(a.length != b.length)
+ {
+ return false;
+ }
+ for(int i = 0; i < a.length; i++)
+ {
+ if(a[i] != b[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ @Override
+ public int hashCode()
+ {
+ int result = 0;
+ for(int i = 0; i < _xid.getGlobalId().length; i++)
+ {
+ result = 31 * result + (int) _xid.getGlobalId()[i];
+ }
+ for(int i = 0; i < _xid.getBranchId().length; i++)
+ {
+ result = 31 * result + (int) _xid.getBranchId()[i];
+ }
+
+ return result;
+ }
+ }
+
+ public synchronized DtxBranch getBranch(Xid xid)
+ {
+ return _branches.get(new ComparableXid(xid));
+ }
+
+ public synchronized boolean registerBranch(DtxBranch branch)
+ {
+ ComparableXid xid = new ComparableXid(branch.getXid());
+ if(!_branches.containsKey(xid))
+ {
+ _branches.put(xid, branch);
+ return true;
+ }
+ return false;
+ }
+
+ synchronized boolean unregisterBranch(DtxBranch branch)
+ {
+ return (_branches.remove(new ComparableXid(branch.getXid())) != null);
+ }
+
+ public void commit(Xid id, boolean onePhase)
+ throws IncorrectDtxStateException, UnknownDtxBranchException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ synchronized (branch)
+ {
+ if(!branch.hasAssociatedActiveSessions())
+ {
+ branch.clearAssociations();
+
+ if(branch.expired() || branch.getState() == DtxBranch.State.TIMEDOUT)
+ {
+ unregisterBranch(branch);
+ throw new TimeoutDtxException(id);
+ }
+ else if(branch.getState() == DtxBranch.State.ROLLBACK_ONLY)
+ {
+ throw new RollbackOnlyDtxException(id);
+ }
+ else if(onePhase && branch.getState() == DtxBranch.State.PREPARED)
+ {
+ throw new IncorrectDtxStateException("Cannot call one-phase commit on a prepared branch", id);
+ }
+ else if(!onePhase && branch.getState() != DtxBranch.State.PREPARED)
+ {
+ throw new IncorrectDtxStateException("Cannot call two-phase commit on a non-prepared branch",
+ id);
+ }
+ branch.commit();
+ branch.setState(DtxBranch.State.FORGOTTEN);
+ unregisterBranch(branch);
+ }
+ else
+ {
+ throw new IncorrectDtxStateException("Branch was still associated with a session", id);
+ }
+ }
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public synchronized void prepare(Xid id)
+ throws UnknownDtxBranchException,
+ IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ synchronized (branch)
+ {
+ if(!branch.hasAssociatedActiveSessions())
+ {
+ branch.clearAssociations();
+
+ if(branch.expired() || branch.getState() == DtxBranch.State.TIMEDOUT)
+ {
+ unregisterBranch(branch);
+ throw new TimeoutDtxException(id);
+ }
+ else if(branch.getState() != DtxBranch.State.ACTIVE
+ && branch.getState() != DtxBranch.State.ROLLBACK_ONLY)
+ {
+ throw new IncorrectDtxStateException("Cannot prepare a transaction in state "
+ + branch.getState(), id);
+ }
+ else
+ {
+ branch.prepare();
+ branch.setState(DtxBranch.State.PREPARED);
+ }
+ }
+ else
+ {
+ throw new IncorrectDtxStateException("Branch still has associated sessions", id);
+ }
+ }
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public void rollback(Xid id)
+ throws IncorrectDtxStateException,
+ UnknownDtxBranchException,
+ AMQStoreException, TimeoutDtxException
+ {
+
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ synchronized (branch)
+ {
+ if(branch.expired() || branch.getState() == DtxBranch.State.TIMEDOUT)
+ {
+ unregisterBranch(branch);
+ throw new TimeoutDtxException(id);
+ }
+ if(!branch.hasAssociatedActiveSessions())
+ {
+ branch.clearAssociations();
+ branch.rollback();
+ branch.setState(DtxBranch.State.FORGOTTEN);
+ unregisterBranch(branch);
+ }
+ else
+ {
+ throw new IncorrectDtxStateException("Branch was still associated with a session", id);
+ }
+ }
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+
+ public void forget(Xid id) throws UnknownDtxBranchException, IncorrectDtxStateException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ synchronized (branch)
+ {
+ if(!branch.hasAssociatedSessions())
+ {
+ if(branch.getState() != DtxBranch.State.HEUR_COM && branch.getState() != DtxBranch.State.HEUR_RB)
+ {
+ throw new IncorrectDtxStateException("Branch should not be forgotten - "
+ + "it is not heuristically complete", id);
+ }
+ branch.setState(DtxBranch.State.FORGOTTEN);
+ unregisterBranch(branch);
+ }
+ else
+ {
+ throw new IncorrectDtxStateException("Branch was still associated with a session", id);
+ }
+ }
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public long getTimeout(Xid id) throws UnknownDtxBranchException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ return branch.getTimeout();
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public void setTimeout(Xid id, long timeout) throws UnknownDtxBranchException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ branch.setTimeout(timeout);
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public synchronized List<Xid> recover()
+ {
+ List<Xid> inDoubt = new ArrayList<Xid>();
+ for(DtxBranch branch : _branches.values())
+ {
+ if(branch.getState() == DtxBranch.State.PREPARED)
+ {
+ inDoubt.add(branch.getXid());
+ }
+ }
+ return inDoubt;
+ }
+
+ public synchronized void endAssociations(AMQSessionModel session)
+ {
+ for(DtxBranch branch : _branches.values())
+ {
+ if(branch.isAssociated(session))
+ {
+ branch.setState(DtxBranch.State.ROLLBACK_ONLY);
+ branch.disassociateSession(session);
+ }
+ }
+ }
+
+
+ public synchronized void close()
+ {
+ for(DtxBranch branch : _branches.values())
+ {
+ branch.close();
+ }
+ _branches.clear();
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/IncorrectDtxStateException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/IncorrectDtxStateException.java
new file mode 100644
index 0000000000..45f094e4b9
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/IncorrectDtxStateException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class IncorrectDtxStateException extends DtxException
+{
+ public IncorrectDtxStateException(String message, Xid id)
+ {
+ super(message + " (xid: " + id + ")");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/JoinAndResumeDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/JoinAndResumeDtxException.java
new file mode 100644
index 0000000000..a25e5a4ed6
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/JoinAndResumeDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class JoinAndResumeDtxException extends DtxException
+{
+ public JoinAndResumeDtxException(Xid id)
+ {
+ super("Cannot start a branch with both join and resume set " + id);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/NotAssociatedDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/NotAssociatedDtxException.java
new file mode 100644
index 0000000000..de070546a7
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/NotAssociatedDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class NotAssociatedDtxException extends DtxException
+{
+ public NotAssociatedDtxException(Xid id)
+ {
+ super("Xid " + id + " not associated with the current session");
+ }
+}
diff --git a/cpp/src/qpid/sys/apr/Thread.cpp b/java/broker/src/main/java/org/apache/qpid/server/txn/RollbackOnlyDtxException.java
index b52d0e6ace..6cf12d8631 100644
--- a/cpp/src/qpid/sys/apr/Thread.cpp
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/RollbackOnlyDtxException.java
@@ -7,9 +7,9 @@
* 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
@@ -19,16 +19,14 @@
*
*/
-#include "qpid/sys/apr/Thread.h"
-#include "qpid/sys/Runnable.h"
-
-using namespace qpid::sys;
-using qpid::sys::Runnable;
-
-void* APR_THREAD_FUNC Thread::runRunnable(apr_thread_t* thread, void *data) {
- reinterpret_cast<Runnable*>(data)->run();
- CHECK_APR_SUCCESS(apr_thread_exit(thread, APR_SUCCESS));
- return NULL;
-}
+package org.apache.qpid.server.txn;
+import org.apache.qpid.transport.Xid;
+public class RollbackOnlyDtxException extends DtxException
+{
+ public RollbackOnlyDtxException(Xid id)
+ {
+ super("Transaction " + id + " may only be rolled back");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/SuspendAndFailDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/SuspendAndFailDtxException.java
new file mode 100644
index 0000000000..228844fd63
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/SuspendAndFailDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class SuspendAndFailDtxException extends DtxException
+{
+public SuspendAndFailDtxException(Xid id)
+{
+ super("Cannot end a branch with both suspend and fail set " + id);
+}
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/TimeoutDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/TimeoutDtxException.java
new file mode 100644
index 0000000000..50f7708d8a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/TimeoutDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class TimeoutDtxException extends DtxException
+{
+ public TimeoutDtxException(Xid id)
+ {
+ super("Transaction " + id + " has timed-out and may only be rolled back");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/UnknownDtxBranchException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/UnknownDtxBranchException.java
new file mode 100644
index 0000000000..c23e518365
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/UnknownDtxBranchException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class UnknownDtxBranchException extends DtxException
+{
+ public UnknownDtxBranchException(Xid id)
+ {
+ super("Unknown xid " + id);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
index afded3416e..5e4a4f2db6 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
@@ -20,6 +20,9 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ScheduledFuture;
import org.apache.qpid.common.Closeable;
import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.configuration.ConfigStore;
@@ -33,13 +36,10 @@ import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.stats.StatisticsGatherer;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
-
-import java.util.Map;
-import java.util.UUID;
+import org.apache.qpid.server.txn.DtxRegistry;
public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHostConfig, Closeable, StatisticsGatherer
{
@@ -59,8 +59,6 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo
DurableConfigurationStore getDurableConfigurationStore();
- AuthenticationManager getAuthenticationManager();
-
SecurityManager getSecurityManager();
void close();
@@ -96,5 +94,9 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo
ConfigStore getConfigStore();
+ DtxRegistry getDtxRegistry();
+
void removeBrokerConnection(BrokerLink brokerLink);
+
+ ScheduledFuture<?> scheduleTask(long delay, Runnable timeoutTask);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
index 266d23af97..0e965472d5 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
@@ -20,9 +20,18 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.UUID;
import org.apache.log4j.Logger;
-
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.binding.BindingFactory;
@@ -32,29 +41,26 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.TransactionLogMessages;
import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject;
import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.AbstractServerMessageImpl;
import org.apache.qpid.server.message.EnqueableMessage;
import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.MessageStoreRecoveryHandler;
import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.txn.DtxBranch;
+import org.apache.qpid.server.txn.DtxRegistry;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.transport.Xid;
+import org.apache.qpid.transport.util.Functions;
import org.apache.qpid.util.ByteBufferInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.UUID;
-
public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHandler,
ConfigurationRecoveryHandler.QueueRecoveryHandler,
ConfigurationRecoveryHandler.ExchangeRecoveryHandler,
@@ -63,7 +69,8 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
MessageStoreRecoveryHandler,
MessageStoreRecoveryHandler.StoredMessageRecoveryHandler,
TransactionLogRecoveryHandler,
- TransactionLogRecoveryHandler.QueueEntryRecoveryHandler
+ TransactionLogRecoveryHandler.QueueEntryRecoveryHandler,
+ TransactionLogRecoveryHandler.DtxRecordRecoveryHandler
{
private static final Logger _logger = Logger.getLogger(VirtualHostConfigRecoveryHandler.class);
@@ -76,7 +83,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
private MessageStore _store;
private final Map<String, Integer> _queueRecoveries = new TreeMap<String, Integer>();
- private Map<Long, ServerMessage> _recoveredMessages = new HashMap<Long, ServerMessage>();
+ private Map<Long, AbstractServerMessageImpl> _recoveredMessages = new HashMap<Long, AbstractServerMessageImpl>();
private Map<Long, StoredMessage> _unusedMessages = new HashMap<Long, StoredMessage>();
@@ -158,7 +165,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
public void message(StoredMessage message)
{
- ServerMessage serverMessage;
+ AbstractServerMessageImpl serverMessage;
switch(message.getMetaData().getType())
{
case META_DATA_0_8:
@@ -193,6 +200,164 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
{
}
+ public void dtxRecord(long format, byte[] globalId, byte[] branchId,
+ MessageStore.Transaction.Record[] enqueues,
+ MessageStore.Transaction.Record[] dequeues)
+ {
+ Xid id = new Xid(format, globalId, branchId);
+ DtxRegistry dtxRegistry = _virtualHost.getDtxRegistry();
+ DtxBranch branch = dtxRegistry.getBranch(id);
+ if(branch == null)
+ {
+ branch = new DtxBranch(id, _store, _virtualHost);
+ dtxRegistry.registerBranch(branch);
+ }
+ for(MessageStore.Transaction.Record record : enqueues)
+ {
+ final AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(record.getQueue().getResourceName());
+ if(queue != null)
+ {
+ final long messageId = record.getMessage().getMessageNumber();
+ final AbstractServerMessageImpl message = _recoveredMessages.get(messageId);
+ _unusedMessages.remove(messageId);
+
+ if(message != null)
+ {
+ message.incrementReference();
+
+ branch.enqueue(queue,message);
+
+ branch.addPostTransactionAcion(new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ try
+ {
+
+ queue.enqueue(message, true, null);
+ message.decrementReference();
+ }
+ catch (AMQException e)
+ {
+ _logger.error("Unable to enqueue message " + message.getMessageNumber() + " into " +
+ "queue " + queue.getName() + " (from XA transaction)", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void onRollback()
+ {
+ message.decrementReference();
+ }
+ });
+ }
+ else
+ {
+ StringBuilder xidString = xidAsString(id);
+ String messageNumberString = String.valueOf(message.getMessageNumber());
+ CurrentActor.get().message(_logSubject,
+ TransactionLogMessages.XA_INCOMPLETE_MESSAGE(xidString.toString(),
+ messageNumberString));
+
+ }
+
+ }
+ else
+ {
+ StringBuilder xidString = xidAsString(id);
+ CurrentActor.get().message(_logSubject,
+ TransactionLogMessages.XA_INCOMPLETE_QUEUE(xidString.toString(),
+ record.getQueue().getResourceName()));
+
+ }
+ }
+ for(MessageStore.Transaction.Record record : dequeues)
+ {
+ final AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(record.getQueue().getResourceName());
+ if(queue != null)
+ {
+ final long messageId = record.getMessage().getMessageNumber();
+ final AbstractServerMessageImpl message = _recoveredMessages.get(messageId);
+ _unusedMessages.remove(messageId);
+
+ if(message != null)
+ {
+ final QueueEntry entry = queue.getMessageOnTheQueue(messageId);
+
+ entry.acquire();
+
+ branch.dequeue(queue, message);
+
+ branch.addPostTransactionAcion(new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ entry.discard();
+ }
+
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+ }
+ else
+ {
+ StringBuilder xidString = xidAsString(id);
+ String messageNumberString = String.valueOf(message.getMessageNumber());
+ CurrentActor.get().message(_logSubject,
+ TransactionLogMessages.XA_INCOMPLETE_MESSAGE(xidString.toString(),
+ messageNumberString));
+
+ }
+
+ }
+ else
+ {
+ StringBuilder xidString = xidAsString(id);
+ CurrentActor.get().message(_logSubject,
+ TransactionLogMessages.XA_INCOMPLETE_QUEUE(xidString.toString(),
+ queue.getName()));
+ }
+
+ }
+
+ try
+ {
+ branch.setState(DtxBranch.State.PREPARED);
+ branch.prePrepareTransaction();
+ }
+ catch (AMQStoreException e)
+ {
+ _logger.error("Unexpected database exception when attempting to prepare a recovered XA transaction " +
+ xidAsString(id), e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static StringBuilder xidAsString(Xid id)
+ {
+ return new StringBuilder("(")
+ .append(id.getFormat())
+ .append(',')
+ .append(Functions.str(id.getGlobalId()))
+ .append(',')
+ .append(Functions.str(id.getBranchId()))
+ .append(')');
+ }
+
+ public void completeDtxRecordRecovery()
+ {
+ for(StoredMessage m : _unusedMessages.values())
+ {
+ _logger.warn("Message id " + m.getMessageNumber() + " in store, but not in any queue - removing....");
+ m.remove();
+ }
+ CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_COMPLETE(null, false));
+ }
+
private static final class ProcessAction
{
private final AMQQueue _queue;
@@ -349,15 +514,9 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
}
- public void completeQueueEntryRecovery()
+ public DtxRecordRecoveryHandler completeQueueEntryRecovery()
{
- for(StoredMessage m : _unusedMessages.values())
- {
- _logger.warn("Message id " + m.getMessageNumber() + " in store, but not in any queue - removing....");
- m.remove();
- }
-
for(Map.Entry<String,Integer> entry : _queueRecoveries.entrySet())
{
CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERED(entry.getValue(), entry.getKey()));
@@ -365,7 +524,9 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_COMPLETE(entry.getKey(), true));
}
- CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_COMPLETE(null, false));
+
+
+ return this;
}
private static class DummyMessage implements EnqueableMessage
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
index 51b60f7980..785d4610eb 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.util.concurrent.ScheduledFuture;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
@@ -61,11 +62,11 @@ import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.txn.DtxRegistry;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPlugin;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory;
@@ -95,12 +96,12 @@ public class VirtualHostImpl implements VirtualHost
private MessageStore _messageStore;
+ private DtxRegistry _dtxRegistry;
+
private VirtualHostMBean _virtualHostMBean;
private AMQBrokerManagerMBean _brokerMBean;
- private final AuthenticationManager _authenticationManager;
-
private SecurityManager _securityManager;
private final ScheduledThreadPoolExecutor _houseKeepingTasks;
@@ -118,6 +119,7 @@ public class VirtualHostImpl implements VirtualHost
private final ConcurrentHashMap<BrokerLink,BrokerLink> _links = new ConcurrentHashMap<BrokerLink, BrokerLink>();
private static final int HOUSEKEEPING_SHUTDOWN_TIMEOUT = 5;
+
public IConnectionRegistry getConnectionRegistry()
{
return _connectionRegistry;
@@ -188,6 +190,7 @@ public class VirtualHostImpl implements VirtualHost
_broker = _appRegistry.getBroker();
_configuration = hostConfig;
_name = _configuration.getName();
+ _dtxRegistry = new DtxRegistry();
_id = _appRegistry.getConfigStore().createId();
@@ -238,7 +241,6 @@ public class VirtualHostImpl implements VirtualHost
initialiseMessageStore(hostConfig);
}
- _authenticationManager = ApplicationRegistry.getInstance().getAuthenticationManager();
_brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
_brokerMBean.register();
@@ -351,6 +353,11 @@ public class VirtualHostImpl implements VirtualHost
TimeUnit.MILLISECONDS);
}
+ public ScheduledFuture<?> scheduleTask(long delay, Runnable task)
+ {
+ return _houseKeepingTasks.schedule(task, delay, TimeUnit.MILLISECONDS);
+ }
+
public long getHouseKeepingTaskCount()
{
return _houseKeepingTasks.getTaskCount();
@@ -574,11 +581,6 @@ public class VirtualHostImpl implements VirtualHost
return _durableConfigurationStore;
}
- public AuthenticationManager getAuthenticationManager()
- {
- return _authenticationManager;
- }
-
public SecurityManager getSecurityManager()
{
return _securityManager;
@@ -617,6 +619,11 @@ public class VirtualHostImpl implements VirtualHost
}
}
+ if(_dtxRegistry != null)
+ {
+ _dtxRegistry.close();
+ }
+
//Close MessageStore
if (_messageStore != null)
{
@@ -784,6 +791,11 @@ public class VirtualHostImpl implements VirtualHost
return getApplicationRegistry().getConfigStore();
}
+ public DtxRegistry getDtxRegistry()
+ {
+ return _dtxRegistry;
+ }
+
/**
* Temporary Startup RT class to record the creation of persistent queues / exchanges.
*
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
index 34dc5b4428..afaa417415 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
@@ -34,7 +34,6 @@ import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.List;
@@ -357,12 +356,12 @@ public class MockAMQQueue implements AMQQueue
return null;
}
- public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction storeContext)
+ public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName)
{
}
- public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction storeContext)
+ public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName)
{
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
index c345384e28..9f022dcdde 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
@@ -45,7 +45,6 @@ import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.subscription.MockSubscription;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.txn.AutoCommitTransaction;
-import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -839,7 +838,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
/**
* Tests that dequeued message is not copied as part of invocation of
- * {@link SimpleAMQQueue#copyMessagesToAnotherQueue(long, long, String, ServerTransaction)}
+ * {@link SimpleAMQQueue#copyMessagesToAnotherQueue(long, long, String)}
*/
public void testCopyMessagesWithDequeuedEntry()
{
@@ -856,14 +855,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
// create another queue
SimpleAMQQueue queue = createQueue(anotherQueueName);
- // create transaction
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore());
-
// copy messages into another queue
- _queue.copyMessagesToAnotherQueue(0, messageNumber, anotherQueueName, txn);
-
- // commit transaction
- txn.commit();
+ _queue.copyMessagesToAnotherQueue(0, messageNumber, anotherQueueName);
// get messages on another queue
List<QueueEntry> entries = queue.getMessagesOnTheQueue();
@@ -889,7 +882,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
/**
* Tests that dequeued message is not moved as part of invocation of
- * {@link SimpleAMQQueue#moveMessagesToAnotherQueue(long, long, String, ServerTransaction)}
+ * {@link SimpleAMQQueue#moveMessagesToAnotherQueue(long, long, String)}
*/
public void testMovedMessagesWithDequeuedEntry()
{
@@ -906,14 +899,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
// create another queue
SimpleAMQQueue queue = createQueue(anotherQueueName);
- // create transaction
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore());
-
// move messages into another queue
- _queue.moveMessagesToAnotherQueue(0, messageNumber, anotherQueueName, txn);
-
- // commit transaction
- txn.commit();
+ _queue.moveMessagesToAnotherQueue(0, messageNumber, anotherQueueName);
// get messages on another queue
List<QueueEntry> entries = queue.getMessagesOnTheQueue();
diff --git a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java b/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java
index 6a8a6dc2d0..9ff8f0a531 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java
@@ -80,11 +80,10 @@ public class ApplicationRegistryShutdownTest extends InternalBrokerBaseCase
}
}
- // Not using isEmpty as that is not in Java 5
- assertTrue("No new SASL mechanisms added by initialisation.", additions.size() != 0 );
+ assertFalse("No new SASL mechanisms added by initialisation.", additions.isEmpty());
//Close the registry which will perform the close the AuthenticationManager
- getRegistry().close();
+ stopBroker();
//Validate that the SASL plugFins have been removed.
Provider[] providersAfterClose = Security.getProviders();
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java b/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java
index 88b9acffe0..09d865cb05 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java
@@ -146,6 +146,14 @@ public class SkeletonMessageStore implements MessageStore
{
}
+
+ public void removeXid(long format, byte[] globalId, byte[] branchId)
+ {
+ }
+
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ {
+ }
};
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java b/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
index e409734a17..104e06d29a 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
@@ -100,6 +100,14 @@ public class TestableMemoryMessageStore extends MemoryMessageStore
public void abortTran() throws AMQStoreException
{
}
+
+ public void removeXid(long format, byte[] globalId, byte[] branchId)
+ {
+ }
+
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ {
+ }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
index fa0bb5be8b..801549e561 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
@@ -112,6 +112,14 @@ class MockStoreTransaction implements Transaction
_state = TransactionState.ABORTED;
}
+ public void removeXid(long format, byte[] globalId, byte[] branchId)
+ {
+ }
+
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ {
+ }
+
public static MessageStore createTestTransactionLog(final MockStoreTransaction storeTransaction)
{
return new MessageStore()
diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
index 5fe664acdd..af742532e2 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.util.concurrent.ScheduledFuture;
import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.configuration.BrokerConfig;
import org.apache.qpid.server.configuration.ConfigStore;
@@ -39,6 +40,7 @@ import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.txn.DtxRegistry;
import java.util.Map;
import java.util.UUID;
@@ -94,6 +96,11 @@ public class MockVirtualHost implements VirtualHost
return null;
}
+ public DtxRegistry getDtxRegistry()
+ {
+ return null;
+ }
+
public VirtualHostConfiguration getConfiguration()
{
return null;
@@ -170,6 +177,11 @@ public class MockVirtualHost implements VirtualHost
}
+ public ScheduledFuture<?> scheduleTask(long delay, Runnable timeoutTask)
+ {
+ return null;
+ }
+
public void scheduleHouseKeepingTask(long period, HouseKeepingTask task)
{
diff --git a/java/build.deps b/java/build.deps
index dd3853cb73..1531bdfb4b 100644
--- a/java/build.deps
+++ b/java/build.deps
@@ -48,10 +48,9 @@ jetty-util=lib/jetty-util-6.1.14.jar
jetty-servlet-tester=lib/jetty-servlet-tester-6.1.14.jar
servlet-api=lib/servlet-api.jar
-osgi-core=lib/org.osgi.core-1.0.0.jar
-felix-framework=lib/org.apache.felix.framework-2.0.5.jar
+felix-main=lib/org.apache.felix.main-2.0.5.jar
-felix.libs=${osgi-core} ${felix-framework}
+felix.libs=${felix-main}
commons-configuration.libs = ${commons-beanutils-core} ${commons-digester} \
${commons-codec} ${commons-lang} ${commons-collections} ${commons-configuration}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQQueueBrowser.java b/java/client/src/main/java/org/apache/qpid/client/AMQQueueBrowser.java
index 2313bce474..bd83e8b37b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQQueueBrowser.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQQueueBrowser.java
@@ -20,6 +20,12 @@
*/
package org.apache.qpid.client;
+import javax.jms.InvalidDestinationException;
+import javax.jms.InvalidSelectorException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQInternalException;
+import org.apache.qpid.client.filter.JMSSelectorFilter;
+import org.apache.qpid.protocol.AMQConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,12 +54,50 @@ public class AMQQueueBrowser implements QueueBrowser
_session = session;
_queue = queue;
_messageSelector = ((messageSelector == null) || (messageSelector.trim().length() == 0)) ? null : messageSelector;
- // Create Consumer to verify message selector.
- BasicMessageConsumer consumer =
- (BasicMessageConsumer) _session.createBrowserConsumer(_queue, _messageSelector, false);
- // Close this consumer as we are not looking to consume only to establish that, at least for now,
- // the QB can be created
- consumer.close();
+
+
+ validateQueue((AMQDestination) queue);
+
+ if(_messageSelector != null)
+ {
+ validateSelector(_messageSelector);
+ }
+ }
+
+ private void validateSelector(String messageSelector) throws InvalidSelectorException
+ {
+ try
+ {
+ new JMSSelectorFilter(messageSelector);
+ }
+ catch (AMQInternalException e)
+ {
+ throw new InvalidSelectorException(e.getMessage());
+ }
+ }
+
+ private void validateQueue(AMQDestination queue) throws JMSException
+ {
+ try
+ {
+ // Essentially just test the connection/session is still active
+ _session.sync();
+ // TODO - should really validate queue exists, but we often rely on creating the consumer to create the queue :(
+ // _session.declareQueuePassive( queue );
+ }
+ catch (AMQException e)
+ {
+ if(e.getErrorCode() == AMQConstant.NOT_FOUND)
+ {
+ throw new InvalidDestinationException(e.getMessage());
+ }
+ else
+ {
+ final JMSException jmsException = new JMSException(e.getMessage(), String.valueOf(e.getErrorCode().getCode()));
+ jmsException.setLinkedException(e);
+ throw jmsException;
+ }
+ }
}
public Queue getQueue() throws JMSException
@@ -118,12 +162,12 @@ public class AMQQueueBrowser implements QueueBrowser
_consumer = consumer;
prefetchMessage();
}
- _logger.info("QB:created with first element:" + _nextMessage);
+ _logger.debug("QB:created with first element:" + _nextMessage);
}
public boolean hasMoreElements()
{
- _logger.info("QB:hasMoreElements:" + (_nextMessage != null));
+ _logger.debug("QB:hasMoreElements:" + (_nextMessage != null));
return (_nextMessage != null);
}
@@ -136,9 +180,9 @@ public class AMQQueueBrowser implements QueueBrowser
}
try
{
- _logger.info("QB:nextElement about to receive");
+ _logger.debug("QB:nextElement about to receive");
prefetchMessage();
- _logger.info("QB:nextElement received:" + _nextMessage);
+ _logger.debug("QB:nextElement received:" + _nextMessage);
}
catch (JMSException e)
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
index e7e937b689..766237006a 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
@@ -120,18 +120,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public static final long DEFAULT_FLOW_CONTROL_WAIT_FAILURE = 120000L;
/**
- * The default value for immediate flag used by producers created by this session is false. That is, a consumer does
- * not need to be attached to a queue.
- */
- private final boolean _defaultImmediateValue = Boolean.parseBoolean(System.getProperty("qpid.default_immediate", "false"));
-
- /**
- * The default value for mandatory flag used by producers created by this session is true. That is, server will not
- * silently drop messages where no queue is connected to the exchange for the message.
- */
- private final boolean _defaultMandatoryValue = Boolean.parseBoolean(System.getProperty("qpid.default_mandatory", "true"));
-
- /**
* The period to wait while flow controlled before sending a log message confirming that the session is still
* waiting on flow control being revoked
*/
@@ -1198,12 +1186,12 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public P createProducer(Destination destination) throws JMSException
{
- return createProducerImpl(destination, _defaultMandatoryValue, _defaultImmediateValue);
+ return createProducerImpl(destination, null, null);
}
public P createProducer(Destination destination, boolean immediate) throws JMSException
{
- return createProducerImpl(destination, _defaultMandatoryValue, immediate);
+ return createProducerImpl(destination, null, immediate);
}
public P createProducer(Destination destination, boolean mandatory, boolean immediate)
@@ -1692,7 +1680,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
AMQProtocolHandler protocolHandler = getProtocolHandler();
declareExchange(amqd, protocolHandler, false);
- AMQShortString queueName = declareQueue(amqd, protocolHandler, false);
+ AMQShortString queueName = declareQueue(amqd, false);
bindQueue(queueName, amqd.getRoutingKey(), new FieldTable(), amqd.getExchangeName(), amqd);
}
@@ -2613,7 +2601,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public abstract void sendConsume(C consumer, AMQShortString queueName,
AMQProtocolHandler protocolHandler, boolean nowait, int tag) throws AMQException, FailoverException;
- private P createProducerImpl(final Destination destination, final boolean mandatory, final boolean immediate)
+ private P createProducerImpl(final Destination destination, final Boolean mandatory, final Boolean immediate)
throws JMSException
{
return new FailoverRetrySupport<P, JMSException>(
@@ -2642,8 +2630,8 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
}, _connection).execute();
}
- public abstract P createMessageProducer(final Destination destination, final boolean mandatory,
- final boolean immediate, final long producerId) throws JMSException;
+ public abstract P createMessageProducer(final Destination destination, final Boolean mandatory,
+ final Boolean immediate, final long producerId) throws JMSException;
private void declareExchange(AMQDestination amqd, AMQProtocolHandler protocolHandler, boolean nowait) throws AMQException
{
@@ -2726,6 +2714,12 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public abstract void sendExchangeDeclare(final AMQShortString name, final AMQShortString type, final AMQProtocolHandler protocolHandler,
final boolean nowait) throws AMQException, FailoverException;
+
+ void declareQueuePassive(AMQDestination queue) throws AMQException
+ {
+ declareQueue(queue,false,false,true);
+ }
+
/**
* Declares a queue for a JMS destination.
*
@@ -2735,27 +2729,35 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
*
* <p/>Note that this operation automatically retries in the event of fail-over.
*
- * @param amqd The destination to declare as a queue.
- * @param protocolHandler The protocol handler to communicate through.
*
+ * @param amqd The destination to declare as a queue.
* @return The name of the decalred queue. This is useful where the broker is generating a queue name on behalf of
* the client.
*
+ *
+ *
* @throws AMQException If the queue cannot be declared for any reason.
* @todo Verify the destiation is valid or throw an exception.
* @todo Be aware of possible changes to parameter order as versions change.
*/
- protected AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler,
+ protected AMQShortString declareQueue(final AMQDestination amqd,
final boolean noLocal) throws AMQException
{
- return declareQueue(amqd, protocolHandler, noLocal, false);
+ return declareQueue(amqd, noLocal, false);
}
- protected AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler,
+ protected AMQShortString declareQueue(final AMQDestination amqd,
final boolean noLocal, final boolean nowait)
+ throws AMQException
+ {
+ return declareQueue(amqd, noLocal, nowait, false);
+ }
+
+ protected AMQShortString declareQueue(final AMQDestination amqd,
+ final boolean noLocal, final boolean nowait, final boolean passive)
throws AMQException
{
- /*return new FailoverRetrySupport<AMQShortString, AMQException>(*/
+ final AMQProtocolHandler protocolHandler = getProtocolHandler();
return new FailoverNoopSupport<AMQShortString, AMQException>(
new FailoverProtectedOperation<AMQShortString, AMQException>()
{
@@ -2767,7 +2769,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
amqd.setQueueName(protocolHandler.generateQueueName());
}
- sendQueueDeclare(amqd, protocolHandler, nowait);
+ sendQueueDeclare(amqd, protocolHandler, nowait, passive);
return amqd.getAMQQueueName();
}
@@ -2775,7 +2777,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
}
public abstract void sendQueueDeclare(final AMQDestination amqd, final AMQProtocolHandler protocolHandler,
- final boolean nowait) throws AMQException, FailoverException;
+ final boolean nowait, boolean passive) throws AMQException, FailoverException;
/**
* Undeclares the specified queue.
@@ -2916,7 +2918,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
if (_delareQueues || amqd.isNameRequired())
{
- declareQueue(amqd, protocolHandler, consumer.isNoLocal(), nowait);
+ declareQueue(amqd, consumer.isNoLocal(), nowait);
}
bindQueue(amqd.getAMQQueueName(), amqd.getRoutingKey(), consumer.getArguments(), amqd.getExchangeName(), amqd, nowait);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
index 816ad1f222..3902c726f3 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
@@ -17,9 +17,20 @@
*/
package org.apache.qpid.client;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import javax.jms.Destination;
+import javax.jms.JMSException;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQDestination.AddressOption;
import org.apache.qpid.client.AMQDestination.Binding;
@@ -27,7 +38,6 @@ import org.apache.qpid.client.AMQDestination.DestSyntax;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.failover.FailoverNoopSupport;
import org.apache.qpid.client.failover.FailoverProtectedOperation;
-import org.apache.qpid.client.filter.MessageFilter;
import org.apache.qpid.client.message.AMQMessageDelegateFactory;
import org.apache.qpid.client.message.FieldTableSupport;
import org.apache.qpid.client.message.MessageFactoryRegistry;
@@ -42,28 +52,14 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.transport.*;
-import org.apache.qpid.util.Serial;
-import org.apache.qpid.util.Strings;
-
import static org.apache.qpid.transport.Option.BATCH;
import static org.apache.qpid.transport.Option.NONE;
import static org.apache.qpid.transport.Option.SYNC;
import static org.apache.qpid.transport.Option.UNRELIABLE;
-
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentLinkedQueue;
+import org.apache.qpid.util.Serial;
+import org.apache.qpid.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* This is a 0.10 Session
@@ -654,8 +650,8 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
/**
* Create an 0_10 message producer
*/
- public BasicMessageProducer_0_10 createMessageProducer(final Destination destination, final boolean mandatory,
- final boolean immediate, final long producerId) throws JMSException
+ public BasicMessageProducer_0_10 createMessageProducer(final Destination destination, final Boolean mandatory,
+ final Boolean immediate, final long producerId) throws JMSException
{
try
{
@@ -725,7 +721,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
* Declare a queue with the given queueName
*/
public void sendQueueDeclare(final AMQDestination amqd, final AMQProtocolHandler protocolHandler,
- final boolean nowait)
+ final boolean nowait, boolean passive)
throws AMQException, FailoverException
{
// do nothing this is only used by 0_8
@@ -735,7 +731,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
* Declare a queue with the given queueName
*/
public AMQShortString send0_10QueueDeclare(final AMQDestination amqd, final AMQProtocolHandler protocolHandler,
- final boolean noLocal, final boolean nowait)
+ final boolean noLocal, final boolean nowait, boolean passive)
throws AMQException
{
AMQShortString queueName;
@@ -761,7 +757,8 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
getQpidSession().queueDeclare(queueName.toString(), "" , arguments,
amqd.isAutoDelete() ? Option.AUTO_DELETE : Option.NONE,
amqd.isDurable() ? Option.DURABLE : Option.NONE,
- amqd.isExclusive() ? Option.EXCLUSIVE : Option.NONE);
+ amqd.isExclusive() ? Option.EXCLUSIVE : Option.NONE,
+ passive ? Option.PASSIVE : Option.NONE);
}
else
{
@@ -931,11 +928,12 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
return getCurrentException();
}
- protected AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler,
- final boolean noLocal, final boolean nowait)
+ protected AMQShortString declareQueue(final AMQDestination amqd,
+ final boolean noLocal, final boolean nowait, final boolean passive)
throws AMQException
{
- /*return new FailoverRetrySupport<AMQShortString, AMQException>(*/
+ final AMQProtocolHandler protocolHandler = getProtocolHandler();
+
return new FailoverNoopSupport<AMQShortString, AMQException>(
new FailoverProtectedOperation<AMQShortString, AMQException>()
{
@@ -952,7 +950,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
amqd.setQueueName(new AMQShortString( binddingKey + "@"
+ amqd.getExchangeName().toString() + "_" + UUID.randomUUID()));
}
- return send0_10QueueDeclare(amqd, protocolHandler, noLocal, nowait);
+ return send0_10QueueDeclare(amqd, protocolHandler, noLocal, nowait, passive);
}
}, getAMQConnection()).execute();
}
@@ -1209,7 +1207,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
else if(createNode)
{
setLegacyFiledsForQueueType(dest);
- send0_10QueueDeclare(dest,null,noLocal,noWait);
+ send0_10QueueDeclare(dest,null,noLocal,noWait, false);
sendQueueBind(dest.getAMQQueueName(), dest.getRoutingKey(),
null,dest.getExchangeName(),dest, false);
break;
@@ -1315,7 +1313,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
}
node.setExclusive(true);
node.setAutoDelete(!node.isDurable());
- send0_10QueueDeclare(dest,null,noLocal,true);
+ send0_10QueueDeclare(dest,null,noLocal,true, false);
getQpidSession().exchangeBind(dest.getQueueName(),
dest.getAddressName(),
dest.getSubject(),
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
index 29f1925cbc..8ab23a240e 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
@@ -38,7 +38,6 @@ import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.client.state.AMQState;
import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.listener.SpecificMethodFrameListener;
-import org.apache.qpid.client.filter.MessageFilter;
import org.apache.qpid.framing.*;
import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9;
import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91;
@@ -401,9 +400,17 @@ public class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, BasicMe
}
public void sendQueueDeclare(final AMQDestination amqd, final AMQProtocolHandler protocolHandler,
- final boolean nowait) throws AMQException, FailoverException
- {
- QueueDeclareBody body = getMethodRegistry().createQueueDeclareBody(getTicket(),amqd.getAMQQueueName(),false,amqd.isDurable(),amqd.isExclusive(),amqd.isAutoDelete(),false,null);
+ final boolean nowait, boolean passive) throws AMQException, FailoverException
+ {
+ QueueDeclareBody body =
+ getMethodRegistry().createQueueDeclareBody(getTicket(),
+ amqd.getAMQQueueName(),
+ passive,
+ amqd.isDurable(),
+ amqd.isExclusive(),
+ amqd.isAutoDelete(),
+ false,
+ null);
AMQFrame queueDeclare = body.generateFrame(getChannelId());
@@ -441,8 +448,8 @@ public class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, BasicMe
}
- public BasicMessageProducer_0_8 createMessageProducer(final Destination destination, final boolean mandatory,
- final boolean immediate, long producerId) throws JMSException
+ public BasicMessageProducer_0_8 createMessageProducer(final Destination destination, final Boolean mandatory,
+ final Boolean immediate, long producerId) throws JMSException
{
try
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
index 75f198e1fa..56739f17f9 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
@@ -20,18 +20,8 @@
*/
package org.apache.qpid.client;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.message.AbstractJMSMessage;
-import org.apache.qpid.client.message.MessageConverter;
-import org.apache.qpid.client.protocol.AMQProtocolHandler;
-import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.transport.TransportException;
-import org.apache.qpid.util.UUIDGen;
-import org.apache.qpid.util.UUIDs;
-
+import java.io.UnsupportedEncodingException;
+import java.util.UUID;
import javax.jms.BytesMessage;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
@@ -42,74 +32,19 @@ import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
-import java.io.UnsupportedEncodingException;
-import java.util.UUID;
+import javax.jms.Topic;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.message.AbstractJMSMessage;
+import org.apache.qpid.client.message.MessageConverter;
+import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.util.UUIDGen;
+import org.apache.qpid.util.UUIDs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public abstract class BasicMessageProducer extends Closeable implements org.apache.qpid.jms.MessageProducer
{
- /**
- * If true, messages will not get a timestamp.
- */
- protected boolean isDisableTimestamps()
- {
- return _disableTimestamps;
- }
-
- protected void setDisableTimestamps(boolean disableTimestamps)
- {
- _disableTimestamps = disableTimestamps;
- }
-
- protected void setDestination(AMQDestination destination)
- {
- _destination = destination;
- }
-
- protected AMQProtocolHandler getProtocolHandler()
- {
- return _protocolHandler;
- }
-
- protected void setProtocolHandler(AMQProtocolHandler protocolHandler)
- {
- _protocolHandler = protocolHandler;
- }
-
- protected int getChannelId()
- {
- return _channelId;
- }
-
- protected void setChannelId(int channelId)
- {
- _channelId = channelId;
- }
-
- protected void setSession(AMQSession session)
- {
- _session = session;
- }
-
- protected String getUserID()
- {
- return _userID;
- }
-
- protected void setUserID(String userID)
- {
- _userID = userID;
- }
-
- protected PublishMode getPublishMode()
- {
- return publishMode;
- }
-
- protected void setPublishMode(PublishMode publishMode)
- {
- this.publishMode = publishMode;
- }
-
enum PublishMode { ASYNC_PUBLISH_ALL, SYNC_PUBLISH_PERSISTENT, SYNC_PUBLISH_ALL };
private final Logger _logger = LoggerFactory.getLogger(getClass());
@@ -166,7 +101,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
private final boolean _immediate;
- private final boolean _mandatory;
+ private final Boolean _mandatory;
private boolean _disableMessageId;
@@ -174,12 +109,34 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
private String _userID; // ref user id used in the connection.
- private static final ContentBody[] NO_CONTENT_BODIES = new ContentBody[0];
+
+ /**
+ * The default value for immediate flag used this producer is false. That is, a consumer does
+ * not need to be attached to a queue.
+ */
+ private final boolean _defaultImmediateValue = Boolean.parseBoolean(System.getProperty("qpid.default_immediate", "false"));
+
+ /**
+ * The default value for mandatory flag used by this producer is true. That is, server will not
+ * silently drop messages where no queue is connected to the exchange for the message.
+ */
+ private final boolean _defaultMandatoryValue = Boolean.parseBoolean(System.getProperty("qpid.default_mandatory", "true"));
+
+ /**
+ * The default value for mandatory flag used by this producer when publishing to a Topic is false. That is, server
+ * will silently drop messages where no queue is connected to the exchange for the message.
+ */
+ private final boolean _defaultMandatoryTopicValue =
+ Boolean.parseBoolean(System.getProperty("qpid.default_mandatory_topic",
+ System.getProperties().containsKey("qpid.default_mandatory")
+ ? System.getProperty("qpid.default_mandatory")
+ : "false"));
private PublishMode publishMode = PublishMode.ASYNC_PUBLISH_ALL;
protected BasicMessageProducer(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId,
- AMQSession session, AMQProtocolHandler protocolHandler, long producerId, boolean immediate, boolean mandatory) throws AMQException
+ AMQSession session, AMQProtocolHandler protocolHandler, long producerId,
+ Boolean immediate, Boolean mandatory) throws AMQException
{
_connection = connection;
_destination = destination;
@@ -193,8 +150,14 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
declareDestination(destination);
}
- _immediate = immediate;
- _mandatory = mandatory;
+ _immediate = immediate == null ? _defaultImmediateValue : immediate;
+ _mandatory = mandatory == null
+ ? destination == null ? null
+ : destination instanceof Topic
+ ? _defaultMandatoryTopicValue
+ : _defaultMandatoryValue
+ : mandatory;
+
_userID = connection.getUsername();
setPublishMode();
}
@@ -381,7 +344,12 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
synchronized (_connection.getFailoverMutex())
{
validateDestination(destination);
- sendImpl((AMQDestination) destination, message, _deliveryMode, _messagePriority, _timeToLive, _mandatory,
+ sendImpl((AMQDestination) destination, message, _deliveryMode, _messagePriority, _timeToLive,
+ _mandatory == null
+ ? destination instanceof Topic
+ ? _defaultMandatoryTopicValue
+ : _defaultMandatoryValue
+ : _mandatory,
_immediate);
}
}
@@ -394,7 +362,13 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
synchronized (_connection.getFailoverMutex())
{
validateDestination(destination);
- sendImpl((AMQDestination) destination, message, deliveryMode, priority, timeToLive, _mandatory, _immediate);
+ sendImpl((AMQDestination) destination, message, deliveryMode, priority, timeToLive,
+ _mandatory == null
+ ? destination instanceof Topic
+ ? _defaultMandatoryTopicValue
+ : _defaultMandatoryValue
+ : _mandatory,
+ _immediate);
}
}
@@ -646,6 +620,69 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
}
}
+ /**
+ * If true, messages will not get a timestamp.
+ */
+ protected boolean isDisableTimestamps()
+ {
+ return _disableTimestamps;
+ }
+
+ protected void setDisableTimestamps(boolean disableTimestamps)
+ {
+ _disableTimestamps = disableTimestamps;
+ }
+
+ protected void setDestination(AMQDestination destination)
+ {
+ _destination = destination;
+ }
+
+ protected AMQProtocolHandler getProtocolHandler()
+ {
+ return _protocolHandler;
+ }
+
+ protected void setProtocolHandler(AMQProtocolHandler protocolHandler)
+ {
+ _protocolHandler = protocolHandler;
+ }
+
+ protected int getChannelId()
+ {
+ return _channelId;
+ }
+
+ protected void setChannelId(int channelId)
+ {
+ _channelId = channelId;
+ }
+
+ protected void setSession(AMQSession session)
+ {
+ _session = session;
+ }
+
+ protected String getUserID()
+ {
+ return _userID;
+ }
+
+ protected void setUserID(String userID)
+ {
+ _userID = userID;
+ }
+
+ protected PublishMode getPublishMode()
+ {
+ return publishMode;
+ }
+
+ protected void setPublishMode(PublishMode publishMode)
+ {
+ this.publishMode = publishMode;
+ }
+
Logger getLogger()
{
return _logger;
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java
index 024219cfd6..db5baed586 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java
@@ -61,7 +61,7 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
BasicMessageProducer_0_10(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId,
AMQSession session, AMQProtocolHandler protocolHandler, long producerId,
- boolean immediate, boolean mandatory) throws AMQException
+ Boolean immediate, Boolean mandatory) throws AMQException
{
super(connection, destination, transacted, channelId, session, protocolHandler, producerId, immediate, mandatory);
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java
index 3b5e361f97..7fd8feef54 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java
@@ -44,7 +44,7 @@ public class BasicMessageProducer_0_8 extends BasicMessageProducer
{
BasicMessageProducer_0_8(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId,
- AMQSession session, AMQProtocolHandler protocolHandler, long producerId, boolean immediate, boolean mandatory) throws AMQException
+ AMQSession session, AMQProtocolHandler protocolHandler, long producerId, Boolean immediate, Boolean mandatory) throws AMQException
{
super(connection, destination,transacted,channelId,session, protocolHandler, producerId, immediate, mandatory);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java b/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java
index 128aa18d30..0bf0b012ff 100644
--- a/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java
+++ b/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java
@@ -308,13 +308,16 @@ public class XAResourceImpl implements XAResource
_xaSession.createSession();
convertExecutionErrorToXAErr( e.getException().getErrorCode());
}
- Xid[] result = new Xid[res.getInDoubt().size()];
- int i = 0;
- for (Object obj : res.getInDoubt())
- {
- org.apache.qpid.transport.Xid xid = (org.apache.qpid.transport.Xid) obj;
- result[i] = new XidImpl(xid.getBranchId(), (int) xid.getFormat(), xid.getGlobalId());
- i++;
+ Xid[] result = new Xid[res.getInDoubt() != null ? res.getInDoubt().size() : 0];
+ if(result.length != 0)
+ {
+ int i = 0;
+ for (Object obj : res.getInDoubt())
+ {
+ org.apache.qpid.transport.Xid xid = (org.apache.qpid.transport.Xid) obj;
+ result[i] = new XidImpl(xid.getBranchId(), (int) xid.getFormat(), xid.getGlobalId());
+ i++;
+ }
}
return result;
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java
index 84d91ee57e..f199961b6f 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java
@@ -145,7 +145,7 @@ public class TestAMQSession extends AMQSession_0_8
}
public void sendQueueDeclare(AMQDestination amqd, AMQProtocolHandler protocolHandler,
- boolean nowait) throws AMQException, FailoverException
+ boolean nowait, boolean passive) throws AMQException, FailoverException
{
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
index a0ed90244d..f6fa89a91c 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
@@ -75,17 +75,6 @@ public class ContentHeaderBody implements AMQBody
return TYPE;
}
- protected void populateFromBuffer(DataInputStream buffer, long size)
- throws AMQFrameDecodingException, AMQProtocolVersionException, IOException
- {
- classId = buffer.readUnsignedShort();
- weight = buffer.readUnsignedShort();
- bodySize = buffer.readLong();
- int propertyFlags = buffer.readUnsignedShort();
- ContentHeaderPropertiesFactory factory = ContentHeaderPropertiesFactory.getInstance();
- properties = factory.createContentHeaderProperties(classId, propertyFlags, buffer, (int)size - 14);
- }
-
/**
* Helper method that is used currently by the persistence layer (by BDB at the moment).
* @param buffer
diff --git a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
index 6d05c2fd3a..1ecd8a13b7 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
@@ -264,7 +264,6 @@ public class EncodingUtils
public static void writeLongStringBytes(DataOutput buffer, String s) throws IOException
{
- assert (s == null) || (s.length() <= 0xFFFE);
if (s != null)
{
int len = s.length();
@@ -286,7 +285,6 @@ public class EncodingUtils
public static void writeLongStringBytes(DataOutput buffer, char[] s) throws IOException
{
- assert (s == null) || (s.length <= 0xFFFE);
if (s != null)
{
int len = s.length;
@@ -307,7 +305,6 @@ public class EncodingUtils
public static void writeLongStringBytes(DataOutput buffer, byte[] bytes) throws IOException
{
- assert (bytes == null) || (bytes.length <= 0xFFFE);
if (bytes != null)
{
writeUnsignedInteger(buffer, bytes.length);
diff --git a/java/common/src/main/java/org/apache/qpid/properties/ConnectionStartProperties.java b/java/common/src/main/java/org/apache/qpid/properties/ConnectionStartProperties.java
index 0215c87618..15c144b0eb 100644
--- a/java/common/src/main/java/org/apache/qpid/properties/ConnectionStartProperties.java
+++ b/java/common/src/main/java/org/apache/qpid/properties/ConnectionStartProperties.java
@@ -74,14 +74,19 @@ public class ConnectionStartProperties
public static String getPlatformInfo()
{
- StringBuffer fullSystemInfo = new StringBuffer();
- fullSystemInfo.append(System.getProperty("java.runtime.name"));
- fullSystemInfo.append(", " + System.getProperty("java.runtime.version"));
- fullSystemInfo.append(", " + System.getProperty("java.vendor"));
- fullSystemInfo.append(", " + System.getProperty("os.arch"));
- fullSystemInfo.append(", " + System.getProperty("os.name"));
- fullSystemInfo.append(", " + System.getProperty("os.version"));
- fullSystemInfo.append(", " + System.getProperty("sun.os.patch.level"));
+ StringBuilder fullSystemInfo = new StringBuilder(System.getProperty("java.runtime.name"));
+ fullSystemInfo.append(", ");
+ fullSystemInfo.append(System.getProperty("java.runtime.version"));
+ fullSystemInfo.append(", ");
+ fullSystemInfo.append(System.getProperty("java.vendor"));
+ fullSystemInfo.append(", ");
+ fullSystemInfo.append(System.getProperty("os.arch"));
+ fullSystemInfo.append(", ");
+ fullSystemInfo.append(System.getProperty("os.name"));
+ fullSystemInfo.append(", ");
+ fullSystemInfo.append(System.getProperty("os.version"));
+ fullSystemInfo.append(", ");
+ fullSystemInfo.append(System.getProperty("sun.os.patch.level"));
return fullSystemInfo.toString();
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/Session.java b/java/common/src/main/java/org/apache/qpid/transport/Session.java
index d450746eaa..0cdffeee80 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/Session.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Session.java
@@ -161,7 +161,7 @@ public class Session extends SessionInvoker
this.expiry = expiry;
}
- void setClose(boolean close)
+ protected void setClose(boolean close)
{
this.closing = close;
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
index a38c83d4cb..2b93697bfc 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
@@ -25,6 +25,7 @@ import org.apache.qpid.transport.RangeSet;
import org.apache.qpid.transport.Struct;
import org.apache.qpid.transport.Type;
+import org.apache.qpid.transport.Xid;
import static org.apache.qpid.transport.util.Functions.lsb;
import java.io.UnsupportedEncodingException;
@@ -61,6 +62,7 @@ abstract class AbstractEncoder implements Encoder
ENCODINGS.put(Character.class, Type.CHAR);
ENCODINGS.put(byte[].class, Type.VBIN32);
ENCODINGS.put(UUID.class, Type.UUID);
+ ENCODINGS.put(Xid.class, Type.STRUCT32);
}
private final Map<String,byte[]> str8cache = new LinkedHashMap<String,byte[]>()
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
index b80d5dfd30..a80b988cea 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
@@ -189,7 +189,7 @@ public class Assembler implements Receiver<NetworkEvent>, NetworkDelegate
command = Method.create(commandType);
command.setSync((0x0001 & hdr) != 0);
command.read(dec);
- if (command.hasPayload())
+ if (command.hasPayload() && !frame.isLastSegment())
{
setIncompleteCommand(channel, command);
}
diff --git a/java/genpom b/java/genpom
index 39eccd4c3e..07a5b82a1f 100755
--- a/java/genpom
+++ b/java/genpom
@@ -73,13 +73,15 @@ if opts.name is None:
if opts.artifact is None:
opts.artifact = opts.name
-def lookup(dep, attr):
- nd = dep["dep"][attr]
+def lookup(doc, attr):
+ nd = doc[attr]
if nd is None:
- if nd is None:
- return None
+ return None
return nd.text()
+def lookupElement(doc, attr):
+ return doc[attr]
+
def search(path, file):
for d in path:
f = os.path.join(d, file)
@@ -120,6 +122,7 @@ for jar in jars:
continue
else:
die("unable to locate xml for %s" % jar)
+ dep = dep["dep"]
group = lookup(dep, "groupId")
artifactId = lookup(dep, "artifactId")
version = lookup(dep, "version")
@@ -128,11 +131,28 @@ for jar in jars:
<groupId>%s</groupId>
<artifactId>%s</artifactId>
<version>%s</version>
- <scope>%s</scope>
- </dependency>
-""" % (group, artifactId, version,
+ <scope>%s</scope>""" % (group, artifactId, version,
scopes.get(artifactId, "compile")))
+ exclusions = lookupElement(dep, "exclusions")
+ if exclusions is not None:
+ deps.append("""
+ <exclusions>""")
+ for exclusion in list(exclusions.query["exclusion"]):
+ group = lookup(exclusion, "groupId")
+ artifactId = lookup(exclusion, "artifactId")
+ deps.append("""
+ <exclusion>
+ <groupId>%s</groupId>
+ <artifactId>%s</artifactId>
+ </exclusion>""" % (group, artifactId))
+ deps.append("""
+ </exclusions>""")
+
+ deps.append("""
+ </dependency>
+""")
+
TEMPLATE = """<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diff --git a/java/lib/org.apache.felix.framework-2.0.5.jar b/java/lib/org.apache.felix.main-2.0.5.jar
index 71e5a84231..71e5a84231 100644
--- a/java/lib/org.apache.felix.framework-2.0.5.jar
+++ b/java/lib/org.apache.felix.main-2.0.5.jar
Binary files differ
diff --git a/java/lib/poms/commons-digester-1.8.1.xml b/java/lib/poms/commons-digester-1.8.1.xml
index 1edee7b5f0..56b38bf778 100644
--- a/java/lib/poms/commons-digester-1.8.1.xml
+++ b/java/lib/poms/commons-digester-1.8.1.xml
@@ -19,4 +19,10 @@
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
<version>1.8.1</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ </exclusion>
+ </exclusions>
</dep>
diff --git a/java/lib/poms/org.apache.felix.framework-2.0.5.xml b/java/lib/poms/org.apache.felix.main-2.0.5.xml
index cef17fe589..91718725dc 100644
--- a/java/lib/poms/org.apache.felix.framework-2.0.5.xml
+++ b/java/lib/poms/org.apache.felix.main-2.0.5.xml
@@ -17,6 +17,24 @@
-->
<dep>
<groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.framework</artifactId>
+ <artifactId>org.apache.felix.main</artifactId>
<version>2.0.5</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.framework</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.shell</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.shell.tui</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.bundlerepository</artifactId>
+ </exclusion>
+ </exclusions>
</dep>
diff --git a/java/lib/poms/org.osgi.core-1.0.0.xml b/java/lib/poms/org.osgi.core-1.0.0.xml
deleted file mode 100644
index 833cc91729..0000000000
--- a/java/lib/poms/org.osgi.core-1.0.0.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.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.
--->
-<dep>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.osgi.core</artifactId>
- <version>1.0.0</version>
-</dep>
diff --git a/java/lib/poms/xalan-2.7.0.xml b/java/lib/poms/xalan-2.7.0.xml
index 73ea2df7e2..3fd89aacd8 100644
--- a/java/lib/poms/xalan-2.7.0.xml
+++ b/java/lib/poms/xalan-2.7.0.xml
@@ -19,4 +19,12 @@
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.7.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ </exclusions>
</dep>
+
+
diff --git a/java/module.xml b/java/module.xml
index a3b8606525..3c2be75d8f 100644
--- a/java/module.xml
+++ b/java/module.xml
@@ -220,7 +220,7 @@
<jython path="${mllib.dir}">
<args>
<arg line='"${project.root}/genpom"'/>
- <arg line='-s "${project.root}/lib/poms"'/>
+ <arg line='-s "${project.root}/lib/poms${path.separator}lib/poms"'/>
<arg line='-o "${build.scratch}/qpid-${module.name}.pom"'/>
<arg line="-u ${project.url}"/>
<arg line="-g ${project.groupid}"/>
diff --git a/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java b/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java
index f337908134..c8ffe8571d 100644
--- a/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java
@@ -43,7 +43,7 @@ public class XAResourceTest extends QpidBrokerTestCase
public void testIsSameRMSingleCF() throws Exception
{
XAConnectionFactory factory = getConnectionFactory(FACTORY_NAME);
- XAConnection conn = factory.createXAConnection();
+ XAConnection conn = factory.createXAConnection("guest","guest");
XASession session = conn.createXASession();
XAResource xaResource1 = session.getXAResource();
XAResource xaResource2 = session.getXAResource();
@@ -68,9 +68,9 @@ public class XAResourceTest extends QpidBrokerTestCase
XAConnectionFactory factory2 = new AMQConnectionFactory(url);
XAConnectionFactory factory3 = getConnectionFactory(ALT_FACTORY_NAME);
- XAConnection conn = factory.createXAConnection();
- XAConnection conn2 = factory2.createXAConnection();
- XAConnection conn3 = factory3.createXAConnection();
+ XAConnection conn = factory.createXAConnection("guest","guest");
+ XAConnection conn2 = factory2.createXAConnection("guest","guest");
+ XAConnection conn3 = factory3.createXAConnection("guest","guest");
XASession session = conn.createXASession();
XASession session2 = conn2.createXASession();
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java
index 0604955290..22e175b6b3 100644
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java
@@ -20,6 +20,8 @@ package org.apache.qpid.management.jmx;
import org.apache.commons.lang.time.FastDateFormat;
+import org.apache.log4j.Logger;
+import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.management.common.mbeans.ManagedQueue;
import org.apache.qpid.server.queue.AMQQueueMBean;
import org.apache.qpid.test.utils.JMXTestUtils;
@@ -27,15 +29,25 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase;
import javax.jms.Connection;
import javax.jms.Destination;
+import javax.jms.JMSException;
import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
import javax.jms.Session;
-import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
+
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Tests the JMX API for the Managed Queue.
@@ -43,17 +55,41 @@ import java.util.Map;
*/
public class ManagedQueueMBeanTest extends QpidBrokerTestCase
{
- /**
- * JMX helper.
- */
+ protected static final Logger LOGGER = Logger.getLogger(ManagedQueueMBeanTest.class);
+
private JMXTestUtils _jmxUtils;
+ private Connection _connection;
+ private Session _session;
+
+ private String _sourceQueueName;
+ private String _destinationQueueName;
+ private Destination _sourceQueue;
+ private Destination _destinationQueue;
+ private ManagedQueue _managedSourceQueue;
+ private ManagedQueue _managedDestinationQueue;
public void setUp() throws Exception
{
_jmxUtils = new JMXTestUtils(this);
_jmxUtils.setUp();
+
super.setUp();
+ _sourceQueueName = getTestQueueName() + "_src";
+ _destinationQueueName = getTestQueueName() + "_dest";
+
+ _connection = getConnection();
+ _connection.start();
+
+ _session = _connection.createSession(true, Session.SESSION_TRANSACTED);
+ _sourceQueue = _session.createQueue(_sourceQueueName);
+ _destinationQueue = _session.createQueue(_destinationQueueName);
+ createQueueOnBroker(_sourceQueue);
+ createQueueOnBroker(_destinationQueue);
+
_jmxUtils.open();
+
+ _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName);
+ _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName);
}
public void tearDown() throws Exception
@@ -70,28 +106,17 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase
*/
public void testViewSingleMessage() throws Exception
{
- final String queueName = getTestQueueName();
-
- // Create queue and send numMessages messages to it.
- final Connection con = getConnection();
- final Session session = con.createSession(true, Session.SESSION_TRANSACTED);
- final Destination dest = session.createQueue(queueName);
- session.createConsumer(dest).close(); // Create a consumer only to cause queue creation
-
- final List<Message> sentMessages = sendMessage(session, dest, 1);
+ final List<Message> sentMessages = sendMessage(_session, _sourceQueue, 1);
final Message sentMessage = sentMessages.get(0);
- // Obtain the management interface.
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertNotNull("ManagedQueue expected to be available", managedQueue);
- assertEquals("Unexpected queue depth", 1, managedQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue());
// Check the contents of the message
- final TabularData tab = managedQueue.viewMessages(1l, 1l);
+ final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l);
assertEquals("Unexpected number of rows in table", 1, tab.size());
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) tab.values().iterator();
+ final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) tab.values().iterator();
- final CompositeDataSupport row1 = rowItr.next();
+ final CompositeData row1 = rowItr.next();
assertNotNull("Message should have AMQ message id", row1.get(ManagedQueue.MSG_AMQ_ID));
assertEquals("Unexpected queue position", 1l, row1.get(ManagedQueue.MSG_QUEUE_POS));
assertEquals("Unexpected redelivered flag", Boolean.FALSE, row1.get(ManagedQueue.MSG_REDELIVERED));
@@ -109,6 +134,175 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase
}
/**
+ * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface.
+ */
+ public void testMoveMessagesBetweenQueues() throws Exception
+ {
+ final int numberOfMessagesToSend = 10;
+
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+ // Move first three messages to destination
+ long fromMessageId = amqMessagesIds.get(0);
+ long toMessageId = amqMessagesIds.get(2);
+ _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+ assertEquals("Unexpected queue depth on destination queue after first move", 3, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after first move", 7, _managedSourceQueue.getMessageCount().intValue());
+
+ // Now move a further two messages to destination
+ fromMessageId = amqMessagesIds.get(7);
+ toMessageId = amqMessagesIds.get(8);
+ _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+ assertEquals("Unexpected queue depth on destination queue after second move", 5, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after second move", 5, _managedSourceQueue.getMessageCount().intValue());
+
+ assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
+ }
+
+ /**
+ * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface.
+ */
+ public void testCopyMessagesBetweenQueues() throws Exception
+ {
+ final int numberOfMessagesToSend = 10;
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+ // Copy first three messages to destination
+ long fromMessageId = amqMessagesIds.get(0);
+ long toMessageId = amqMessagesIds.get(2);
+ _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+ assertEquals("Unexpected queue depth on destination queue after first copy", 3, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after first copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ // Now copy a further two messages to destination
+ fromMessageId = amqMessagesIds.get(7);
+ toMessageId = amqMessagesIds.get(8);
+ _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
+ assertEquals("Unexpected queue depth on destination queue after second copy", 5, _managedDestinationQueue.getMessageCount().intValue());
+ assertEquals("Unexpected queue depth on source queue after second copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
+ }
+
+ public void testMoveMessagesBetweenQueuesWithActiveConsumerOnSourceQueue() throws Exception
+ {
+ setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
+ Connection asyncConnection = getConnection();
+ asyncConnection.start();
+
+ final int numberOfMessagesToSend = 50;
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+ long fromMessageId = amqMessagesIds.get(0);
+ long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
+
+ CountDownLatch consumerReadToHalfwayLatch = new CountDownLatch(numberOfMessagesToSend / 2);
+ AtomicInteger totalConsumed = new AtomicInteger(0);
+ startAsyncConsumerOn(_sourceQueue, asyncConnection, consumerReadToHalfwayLatch, totalConsumed);
+
+ boolean halfwayPointReached = consumerReadToHalfwayLatch.await(5000, TimeUnit.MILLISECONDS);
+ assertTrue("Did not read half of messages within time allowed", halfwayPointReached);
+
+ _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+ asyncConnection.stop();
+
+ // The exact number of messages moved will be non deterministic, but the number of messages moved
+ // plus the number consumed should be equal to the number we originally sent.
+
+ int numberOfMessagesReadByConsumer = totalConsumed.intValue();
+ int numberOfMessagesOnDestinationQueue = _managedDestinationQueue.getMessageCount().intValue();
+ LOGGER.debug("Async consumer read : " + numberOfMessagesReadByConsumer
+ + " Number of messages moved to destination : " + numberOfMessagesOnDestinationQueue);
+ assertEquals(numberOfMessagesToSend, numberOfMessagesReadByConsumer + numberOfMessagesOnDestinationQueue);
+
+ int numberOfMessagesRemainingOnSourceQueue = _managedSourceQueue.getMessageCount().intValue();
+ assertEquals(0, numberOfMessagesRemainingOnSourceQueue);
+ }
+
+ public void testMoveMessagesBetweenQueuesWithActiveConsumerOnDestinationQueue() throws Exception
+ {
+ setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
+ Connection asyncConnection = getConnection();
+ asyncConnection.start();
+
+ final int numberOfMessagesToSend = 50;
+ sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+ assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+ List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+ long fromMessageId = amqMessagesIds.get(0);
+ long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
+
+ AtomicInteger totalConsumed = new AtomicInteger(0);
+ CountDownLatch allMessagesConsumedLatch = new CountDownLatch(numberOfMessagesToSend);
+ startAsyncConsumerOn(_destinationQueue, asyncConnection, allMessagesConsumedLatch, totalConsumed);
+
+ _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+ allMessagesConsumedLatch.await(5000, TimeUnit.MILLISECONDS);
+ assertEquals("Did not consume all messages from destination queue", numberOfMessagesToSend, totalConsumed.intValue());
+ }
+
+ private void startAsyncConsumerOn(Destination queue, Connection asyncConnection,
+ final CountDownLatch requiredNumberOfMessagesRead, final AtomicInteger totalConsumed) throws Exception
+ {
+ Session session = asyncConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageConsumer consumer = session.createConsumer(queue);
+ consumer.setMessageListener(new MessageListener()
+ {
+
+ @Override
+ public void onMessage(Message arg0)
+ {
+ totalConsumed.incrementAndGet();
+ requiredNumberOfMessagesRead.countDown();
+ }
+ });
+ }
+
+ private void assertMessageIndicesOn(Destination queue, int... expectedIndexes) throws Exception
+ {
+ MessageConsumer consumer = _session.createConsumer(queue);
+
+ for (int i : expectedIndexes)
+ {
+ Message message = consumer.receive(1000);
+ assertNotNull("Expected message with index " + i, message);
+ assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX));
+ }
+
+ assertNull("Unexpected message encountered", consumer.receive(1000));
+ }
+
+ private List<Long> getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception
+ {
+ final SortedSet<Long> messageIds = new TreeSet<Long>();
+
+ final TabularData tab = managedQueue.viewMessages(startIndex, endIndex);
+ final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) tab.values().iterator();
+ while(rowItr.hasNext())
+ {
+ final CompositeData row = rowItr.next();
+ long amqMessageId = (Long)row.get(ManagedQueue.MSG_AMQ_ID);
+ messageIds.add(amqMessageId);
+ }
+
+ return new ArrayList<Long>(messageIds);
+ }
+
+ /**
*
* Utility method to convert array of Strings in the form x = y into a
* map with key/value x =&gt; y.
@@ -126,4 +320,9 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase
}
return headerMap;
}
+
+ private void createQueueOnBroker(Destination destination) throws JMSException
+ {
+ _session.createConsumer(destination).close(); // Create a consumer only to cause queue creation
+ }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
index 2a1895d6c8..3d116f1b1b 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
@@ -241,7 +241,7 @@ public class ReturnUnroutableMandatoryMessageTest extends QpidBrokerTestCase imp
con2.start();
MessageProducer nonMandatoryProducer = producerSession.createProducer(valid_topic, false, false);
- MessageProducer mandatoryProducer = producerSession.createProducer(invalid_topic);
+ MessageProducer mandatoryProducer = producerSession.createProducer(invalid_topic, false, true);
// First test - should be routed
_logger.info("Sending non-mandatory message");
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
index ddcb96b4db..236202f323 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.logging;
+import javax.jms.QueueBrowser;
import junit.framework.AssertionFailedError;
import org.apache.qpid.client.AMQConnection;
@@ -166,8 +167,10 @@ public class SubscriptionLoggingTest extends AbstractTestLogging
*/
public void testSubscriptionCreateQueueBrowser() throws JMSException, IOException
{
- _session.createBrowser(_queue);
+ _connection.start();
+ QueueBrowser browser = _session.createBrowser(_queue);
+ browser.getEnumeration();
//Validate
//Ensure that we wait for the SUB log message
waitAndFindMatches("SUB-1001");
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
index 54abb76b6d..8ffc09930e 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
@@ -313,6 +313,17 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore
_underlying.abortTran();
doPostDelay("abortTran");
}
+
+ public void removeXid(long format, byte[] globalId, byte[] branchId) throws AMQStoreException
+ {
+ _underlying.removeXid(format, globalId, branchId);
+ }
+
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ throws AMQStoreException
+ {
+ _underlying.recordXid(format, globalId, branchId, enqueues, dequeues);
+ }
}
public void updateQueue(AMQQueue queue) throws AMQStoreException
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
deleted file mode 100644
index d95ad51e05..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
+++ /dev/null
@@ -1,101 +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.test.client;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-import javax.jms.Connection;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.QueueBrowser;
-import javax.jms.Session;
-import java.util.Enumeration;
-
-public class CancelTest extends QpidBrokerTestCase
-{
- private static final Logger _logger = Logger.getLogger(CancelTest.class);
-
- private Connection _clientConnection;
- private Session _clientSession;
- private Queue _queue;
-
- public void setUp() throws Exception
- {
-
- super.setUp();
-
- _queue = (Queue) getInitialContext().lookup("queue");
-
- //Create Client
- _clientConnection = getConnection();
-
- _clientConnection.start();
-
- _clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- //Ensure _queue is created
- _clientSession.createConsumer(_queue).close();
- }
-
- /**
- * Simply
- * This test originally did not assert anything but was just checking
- * that a message could be browsed and consumed without throwing an exception.
- * It now checks that at least a message is browsed and that a message is received.
- */
- public void test() throws Exception
- {
- Connection producerConnection = getConnection();
-
- producerConnection.start();
-
- Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- MessageProducer producer = producerSession.createProducer(_queue);
- producer.send(producerSession.createTextMessage());
- producerConnection.close();
-
-
- QueueBrowser browser = _clientSession.createBrowser(_queue);
- Enumeration e = browser.getEnumeration();
-
- assertTrue(e.hasMoreElements());
-
- int i = 0;
- while (e.hasMoreElements())
- {
- e.nextElement();
- if(++i > 1)
- {
- fail("Two many elemnts to browse!");
- }
- }
-
- browser.close();
-
- MessageConsumer consumer = _clientSession.createConsumer(_queue);
- assertNotNull( consumer.receive(2000l) );
- consumer.close();
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/ImmediateAndMandatoryPublishingTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/ImmediateAndMandatoryPublishingTest.java
index 484146b690..b746a5b09e 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/ImmediateAndMandatoryPublishingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/ImmediateAndMandatoryPublishingTest.java
@@ -18,11 +18,9 @@
*/
package org.apache.qpid.test.client;
-import org.apache.qpid.client.AMQNoConsumersException;
-import org.apache.qpid.client.AMQNoRouteException;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
@@ -32,9 +30,10 @@ import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.Topic;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.TimeUnit;
+import org.apache.qpid.client.AMQNoConsumersException;
+import org.apache.qpid.client.AMQNoRouteException;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
public class ImmediateAndMandatoryPublishingTest extends QpidBrokerTestCase implements ExceptionListener
{
@@ -202,7 +201,88 @@ public class ImmediateAndMandatoryPublishingTest extends QpidBrokerTestCase impl
return message;
}
- @Override
+ public void testMandatoryAndImmediateDefaults() throws JMSException, InterruptedException
+ {
+ Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // publish to non-existent queue - should get mandatory failure
+ MessageProducer producer = session.createProducer(session.createQueue(getTestQueueName()));
+ Message message = session.createMessage();
+ producer.send(message);
+
+ JMSException exception = _exceptions.poll(10, TimeUnit.SECONDS);
+ assertNotNull("JMSException is expected", exception);
+ AMQNoRouteException noRouteException = (AMQNoRouteException) exception.getLinkedException();
+ assertNotNull("AMQNoRouteException should be linked to JMSEXception", noRouteException);
+ Message bounceMessage = (Message) noRouteException.getUndeliveredMessage();
+ assertNotNull("Bounced Message is expected", bounceMessage);
+ assertEquals("Unexpected message is bounced", message.getJMSMessageID(), bounceMessage.getJMSMessageID());
+
+ producer = session.createProducer(null);
+ message = session.createMessage();
+ producer.send(session.createQueue(getTestQueueName()), message);
+
+ exception = _exceptions.poll(10, TimeUnit.SECONDS);
+ assertNotNull("JMSException is expected", exception);
+ noRouteException = (AMQNoRouteException) exception.getLinkedException();
+ assertNotNull("AMQNoRouteException should be linked to JMSEXception", noRouteException);
+ bounceMessage = (Message) noRouteException.getUndeliveredMessage();
+ assertNotNull("Bounced Message is expected", bounceMessage);
+ assertEquals("Unexpected message is bounced", message.getJMSMessageID(), bounceMessage.getJMSMessageID());
+
+
+ // publish to non-existent topic - should get no failure
+ producer = session.createProducer(session.createTopic(getTestQueueName()));
+ message = session.createMessage();
+ producer.send(message);
+
+ exception = _exceptions.poll(1, TimeUnit.SECONDS);
+ assertNull("Unexpected JMSException", exception);
+
+ producer = session.createProducer(null);
+ message = session.createMessage();
+ producer.send(session.createTopic(getTestQueueName()), message);
+
+ exception = _exceptions.poll(1, TimeUnit.SECONDS);
+ assertNull("Unexpected JMSException", exception);
+
+ session.close();
+ }
+
+ public void testMandatoryAndImmediateSystemProperties() throws JMSException, InterruptedException
+ {
+ setTestClientSystemProperty("qpid.default_mandatory","true");
+ Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // publish to non-existent topic - should get mandatory failure
+
+ MessageProducer producer = session.createProducer(session.createTopic(getTestQueueName()));
+ Message message = session.createMessage();
+ producer.send(message);
+
+ JMSException exception = _exceptions.poll(10, TimeUnit.SECONDS);
+ assertNotNull("JMSException is expected", exception);
+ AMQNoRouteException noRouteException = (AMQNoRouteException) exception.getLinkedException();
+ assertNotNull("AMQNoRouteException should be linked to JMSEXception", noRouteException);
+ Message bounceMessage = (Message) noRouteException.getUndeliveredMessage();
+ assertNotNull("Bounced Message is expected", bounceMessage);
+ assertEquals("Unexpected message is bounced", message.getJMSMessageID(), bounceMessage.getJMSMessageID());
+
+ // now set topic specific system property to false - should no longer get mandatory failure on new producer
+ setTestClientSystemProperty("qpid.default_mandatory_topic","false");
+ producer = session.createProducer(null);
+ message = session.createMessage();
+ producer.send(session.createTopic(getTestQueueName()), message);
+
+ exception = _exceptions.poll(1, TimeUnit.SECONDS);
+ if(exception != null)
+ {
+ exception.printStackTrace();
+ }
+ assertNull("Unexpected JMSException", exception);
+
+ }
+
public void onException(JMSException exception)
{
_exceptions.add(exception);
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
index 7a4a45a2c8..f3433adb3f 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
@@ -20,11 +20,7 @@
*/
package org.apache.qpid.test.client;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
+import java.util.Enumeration;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
@@ -35,7 +31,10 @@ import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.NamingException;
-import java.util.Enumeration;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
public class QueueBrowserAutoAckTest extends QpidBrokerTestCase
{
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java
index 707c4b6a47..841d0ea4ba 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java
@@ -56,7 +56,6 @@ public class AcknowledgeTest extends QpidBrokerTestCase
_queue = getTestQueue();
- _logger.info("AT: setup");
//Create Producer put some messages on the queue
_connection = getConnection();
}
@@ -70,13 +69,10 @@ public class AcknowledgeTest extends QpidBrokerTestCase
// These should all end up being prefetched by session
sendMessage(_consumerSession, _queue, 1);
- if(!transacted)
- {
- ((AMQSession)_consumerSession).sync();
- }
+ syncIfNotTransacted(transacted);
assertEquals("Wrong number of messages on queue", 1,
- ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue));
+ ((AMQSession<?,?>) _consumerSession).getQueueDepth((AMQDestination) _queue));
}
/**
@@ -114,6 +110,7 @@ public class AcknowledgeTest extends QpidBrokerTestCase
{
//Send the next message
_producer.send(createNextMessage(_consumerSession, count));
+ syncIfNotTransacted(transacted);
}
doAcknowlegement(msg);
@@ -128,7 +125,7 @@ public class AcknowledgeTest extends QpidBrokerTestCase
}
assertEquals("Wrong number of messages on queue", 0,
- ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue));
+ ((AMQSession<?,?>) _consumerSession).getQueueDepth((AMQDestination) _queue));
}
/**
@@ -181,4 +178,11 @@ public class AcknowledgeTest extends QpidBrokerTestCase
testAcking(false, AMQSession.PRE_ACKNOWLEDGE);
}
+ private void syncIfNotTransacted(boolean transacted) throws Exception
+ {
+ if(!transacted)
+ {
+ ((AMQSession<?,?>)_consumerSession).sync();
+ }
+ }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java
index 8afc3f6997..a121b39a56 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java
@@ -36,6 +36,7 @@ import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
+import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageNotReadableException;
import javax.jms.MessageNotWriteableException;
@@ -278,4 +279,46 @@ public class BytesMessageTest extends QpidBrokerTestCase implements MessageListe
test._count = count;
test.test();
}
+
+ public void testModificationAfterSend() throws Exception
+ {
+ Connection connection = getConnection();
+ Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ BytesMessage jmsMsg = session.createBytesMessage();
+ Destination destination = getTestQueue();
+
+ /* Set the constant message contents. */
+
+ jmsMsg.setStringProperty("foo", "test");
+
+ /* Pre-populate the message body buffer to the target size. */
+ byte[] jmsMsgBodyBuffer = new byte[1024];
+
+ connection.start();
+
+ /* Send messages. */
+ MessageProducer producer = session.createProducer(destination);
+
+ MessageConsumer consumer = session.createConsumer(destination);
+
+ for(int writtenMsgCount = 0; writtenMsgCount < 10; writtenMsgCount++)
+ {
+ /* Set the per send message contents. */
+ jmsMsgBodyBuffer[0] = (byte) writtenMsgCount;
+ jmsMsg.writeBytes(jmsMsgBodyBuffer, 0, jmsMsgBodyBuffer.length);
+ /** Try to write a message. */
+ producer.send(jmsMsg);
+ }
+
+
+ for(int writtenMsgCount = 0; writtenMsgCount < 10; writtenMsgCount++)
+ {
+ BytesMessage recvdMsg = (BytesMessage) consumer.receive(1000L);
+ assertNotNull("Expected to receive message " + writtenMsgCount + " but did not", recvdMsg);
+ assertEquals("Message "+writtenMsgCount+" not of expected size", (long) ((writtenMsgCount + 1)*1024),
+ recvdMsg.getBodyLength());
+
+ }
+ }
+
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
index 40c78284da..a07e531b98 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
@@ -147,7 +147,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
((AMQSession<?, ?>) session2).sync();
- if(isJavaBroker() && isExternalBroker())
+ if(isJavaBroker())
{
//Verify that the queue was deleted by querying for its JMX MBean
_jmxc = JMXConnnectionFactory.getJMXConnection(5000, "127.0.0.1",
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java
index 86ba5c2cb7..e940a73bbb 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java
@@ -118,7 +118,7 @@ public class FaultTest extends AbstractXATestCase
_queueFactory = getConnectionFactory();
_xaqueueConnection = _queueFactory.createXAQueueConnection("guest", "guest");
XAQueueSession session = _xaqueueConnection.createXAQueueSession();
- _queueConnection = _queueFactory.createQueueConnection();
+ _queueConnection = _queueFactory.createQueueConnection("guest","guest");
_nonXASession = _queueConnection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
init(session, _queue);
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java
index eb19504dec..3fbe76323a 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java
@@ -162,11 +162,12 @@ public class QueueTest extends AbstractXATestCase
// create a standard session
try
{
- _queueConnection = _queueFactory.createQueueConnection();
+ _queueConnection = _queueFactory.createQueueConnection("guest", "guest");
_nonXASession = _queueConnection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
}
catch (JMSException e)
{
+ e.printStackTrace();
fail("cannot create queue session: " + e.getMessage());
}
init(session, _queue);
@@ -638,7 +639,8 @@ public class QueueTest extends AbstractXATestCase
TextMessage message1 = (TextMessage) nonXAConsumer.receive(1000);
if (message1 != null)
{
- fail("The queue is not empty! ");
+
+ fail("The queue is not empty! " + message1.getLongProperty(_sequenceNumberPropertyName));
}
}
catch (JMSException e)
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java
index 3a6d573205..d955979ad6 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java
@@ -18,6 +18,7 @@
package org.apache.qpid.test.unit.xa;
import junit.framework.TestSuite;
+import org.apache.qpid.configuration.ClientProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,6 +26,8 @@ import javax.jms.*;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
+import java.util.HashSet;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -103,7 +106,7 @@ public class TopicTest extends AbstractXATestCase
}
catch (Exception e)
{
- fail("Exception thrown when cleaning standard connection: " + e.getStackTrace());
+ fail("Exception thrown when cleaning standard connection: " + e);
}
}
super.tearDown();
@@ -116,6 +119,7 @@ public class TopicTest extends AbstractXATestCase
{
if (!isBroker08())
{
+ setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, "1");
// lookup test queue
try
{
@@ -650,7 +654,12 @@ public class TopicTest extends AbstractXATestCase
{
message = (TextMessage) xaDurSub.receive(1000);
- _logger.debug(" received message: " + message.getLongProperty(_sequenceNumberPropertyName));
+
+ if(message != null)
+ {
+ _logger.debug(" received message: " + message.getLongProperty(_sequenceNumberPropertyName));
+ }
+
if (message == null)
{
fail("no message received! expected: " + i);
@@ -882,35 +891,40 @@ public class TopicTest extends AbstractXATestCase
// receive 3 message within tx1: 3, 4 and 7
_xaResource.start(xid1, XAResource.TMRESUME);
// receive messages 3, 4 and 7
+ Set<Long> expected = new HashSet<Long>();
+ expected.add(3L);
+ expected.add(4L);
+ expected.add(7L);
message = (TextMessage) xaDurSub.receive(1000);
if (message == null)
{
- fail("no message received! expected: " + 3);
+ fail("no message received! expected one of: " + expected);
}
- else if (message.getLongProperty(_sequenceNumberPropertyName) != 3)
+ else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName)))
{
fail("wrong sequence number: " + message
- .getLongProperty(_sequenceNumberPropertyName) + " 3 was expected");
+ .getLongProperty(_sequenceNumberPropertyName) + " expected one from " + expected);
}
message = (TextMessage) xaDurSub.receive(1000);
if (message == null)
{
- fail("no message received! expected: " + 4);
+ fail("no message received! expected one of: " + expected);
}
- else if (message.getLongProperty(_sequenceNumberPropertyName) != 4)
+ else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName)))
{
+
fail("wrong sequence number: " + message
- .getLongProperty(_sequenceNumberPropertyName) + " 4 was expected");
+ .getLongProperty(_sequenceNumberPropertyName) + " expected one from " + expected);
}
message = (TextMessage) xaDurSub.receive(1000);
if (message == null)
{
- fail("no message received! expected: " + 7);
+ fail("no message received! expected one of: " + expected);
}
- else if (message.getLongProperty(_sequenceNumberPropertyName) != 7)
+ else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName)))
{
fail("wrong sequence number: " + message
- .getLongProperty(_sequenceNumberPropertyName) + " 7 was expected");
+ .getLongProperty(_sequenceNumberPropertyName) + " expected one from " + expected);
}
}
catch (Exception e)
@@ -936,8 +950,18 @@ public class TopicTest extends AbstractXATestCase
try
{
- // consume messages 1 - 4
- //----- start xid1
+ // consume messages: could be any from (1 - 4, 7-10)
+ //----- start xid4
+ Set<Long> expected = new HashSet<Long>();
+ Set<Long> xid4msgs = new HashSet<Long>();
+ for(long l = 1; l <= 4l; l++)
+ {
+ expected.add(l);
+ }
+ for(long l = 7; l <= 10l; l++)
+ {
+ expected.add(l);
+ }
_xaResource.start(xid4, XAResource.TMNOFLAGS);
for (int i = 1; i <= 4; i++)
{
@@ -946,9 +970,14 @@ public class TopicTest extends AbstractXATestCase
{
fail("no message received! expected: " + i);
}
- else if (message.getLongProperty(_sequenceNumberPropertyName) != i)
+
+ long seqNo = message.getLongProperty(_sequenceNumberPropertyName);
+ xid4msgs.add(seqNo);
+
+ if (!expected.remove(seqNo))
{
- fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName));
+ fail("wrong sequence number: " + seqNo +
+ " expected one from " + expected);
}
}
_xaResource.end(xid4, XAResource.TMSUSPEND);
@@ -961,15 +990,17 @@ public class TopicTest extends AbstractXATestCase
{
fail("no message received! expected: " + i);
}
- else if (message.getLongProperty(_sequenceNumberPropertyName) != i)
+ else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName)))
{
- fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName));
+ fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName)
+ + " expected one from " + expected);
}
}
_xaResource.end(xid5, XAResource.TMSUSPEND);
// abort tx4
_xaResource.prepare(xid4);
_xaResource.rollback(xid4);
+ expected.addAll(xid4msgs);
// consume messages 1-4 with tx5
_xaResource.start(xid5, XAResource.TMRESUME);
for (int i = 1; i <= 4; i++)
@@ -979,13 +1010,15 @@ public class TopicTest extends AbstractXATestCase
{
fail("no message received! expected: " + i);
}
- else if (message.getLongProperty(_sequenceNumberPropertyName) != i)
+ else if (!expected.remove(message.getLongProperty(_sequenceNumberPropertyName)))
{
- fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName));
+ fail("wrong sequence number: " + message.getLongProperty(_sequenceNumberPropertyName)
+ + " expected one from " + expected);
}
}
_xaResource.end(xid5, XAResource.TMSUSPEND);
// commit tx5
+
_xaResource.prepare(xid5);
_xaResource.commit(xid5, false);
}
@@ -1602,6 +1635,7 @@ public class TopicTest extends AbstractXATestCase
}
_xaResource.end(xid2, XAResource.TMSUCCESS);
_xaResource.commit(xid2, true);
+ _session.close();
}
catch (Exception e)
{
diff --git a/java/test-profiles/JavaExcludes b/java/test-profiles/JavaExcludes
index e123d02918..ce0016fcff 100644
--- a/java/test-profiles/JavaExcludes
+++ b/java/test-profiles/JavaExcludes
@@ -28,9 +28,6 @@ org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy
//Moved from JavaStandaloneExcludes when it was removed
///////////////////////////////////////////////////////
-//XA functionality is not fully implemented yet
-org.apache.qpid.jms.xa.XAResourceTest#*
-
//The Java broker doesnt support client auth
org.apache.qpid.client.ssl.SSLTest#testMultipleCertsInSingleStore
diff --git a/java/test-profiles/JavaPre010Excludes b/java/test-profiles/JavaPre010Excludes
index ada22638be..c05f7b51f4 100644
--- a/java/test-profiles/JavaPre010Excludes
+++ b/java/test-profiles/JavaPre010Excludes
@@ -61,3 +61,7 @@ org.apache.qpid.test.unit.client.temporaryqueue.TemporaryQueueTest#testTemporary
// QPID-3604 This fix is applied only to the 0-10 code, hence this test does not work for pre 0-10.
org.apache.qpid.client.prefetch.PrefetchBehaviourTest#testConnectionStop
+
+//XA functionality is not implemented in pre 0-10
+org.apache.qpid.jms.xa.XAResourceTest#*
+
diff --git a/java/test-profiles/JavaTransientExcludes b/java/test-profiles/JavaTransientExcludes
index 7cc541c8b9..cf11e99e89 100644
--- a/java/test-profiles/JavaTransientExcludes
+++ b/java/test-profiles/JavaTransientExcludes
@@ -24,6 +24,13 @@ org.apache.qpid.test.unit.ack.ClientAcknowledgeTest#testClientAckWithLargeFlushe
org.apache.qpid.test.unit.ct.DurableSubscriberTest#*
+org.apache.qpid.test.unit.xa.QueueTest#testRecover
+org.apache.qpid.test.unit.xa.QueueTest#testSendAndRecover
+org.apache.qpid.test.unit.xa.TopicTest#testMultiMessagesDurSubCrash
+org.apache.qpid.test.unit.xa.TopicTest#testDurSubCrash
+org.apache.qpid.test.unit.xa.TopicTest#testRecover
+
+
org.apache.qpid.server.store.MessageStoreTest#testMessagePersistence
org.apache.qpid.server.store.MessageStoreTest#testMessageRemoval
org.apache.qpid.server.store.MessageStoreTest#testBindingPersistence
diff --git a/java/test-profiles/java-bdb-spawn.0-8.testprofile b/java/test-profiles/java-bdb-spawn.0-8.testprofile
index f9837cc4f3..011fd9fe91 100644
--- a/java/test-profiles/java-bdb-spawn.0-8.testprofile
+++ b/java/test-profiles/java-bdb-spawn.0-8.testprofile
@@ -24,7 +24,7 @@ broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes
+profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT
diff --git a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile b/java/test-profiles/java-bdb-spawn.0-9-1.testprofile
index b04fea21b6..7d178d958f 100644
--- a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile
+++ b/java/test-profiles/java-bdb-spawn.0-9-1.testprofile
@@ -24,7 +24,7 @@ broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes
+profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
diff --git a/java/test-profiles/java-bdb-spawn.0-9.testprofile b/java/test-profiles/java-bdb-spawn.0-9.testprofile
index 03082b6f19..f5c321dc02 100644
--- a/java/test-profiles/java-bdb-spawn.0-9.testprofile
+++ b/java/test-profiles/java-bdb-spawn.0-9.testprofile
@@ -24,7 +24,7 @@ broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes
+profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT
diff --git a/java/test-profiles/java-bdb.0-8.testprofile b/java/test-profiles/java-bdb.0-8.testprofile
index ba6cc0fa80..322168064f 100644
--- a/java/test-profiles/java-bdb.0-8.testprofile
+++ b/java/test-profiles/java-bdb.0-8.testprofile
@@ -25,7 +25,7 @@ broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes
+profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT
diff --git a/java/test-profiles/java-bdb.0-9-1.testprofile b/java/test-profiles/java-bdb.0-9-1.testprofile
index 101d38f4b9..f0b34c5f67 100644
--- a/java/test-profiles/java-bdb.0-9-1.testprofile
+++ b/java/test-profiles/java-bdb.0-9-1.testprofile
@@ -25,7 +25,7 @@ broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes
+profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
diff --git a/java/test-profiles/java-bdb.0-9.testprofile b/java/test-profiles/java-bdb.0-9.testprofile
index daa61253bb..1ac4ef74c0 100644
--- a/java/test-profiles/java-bdb.0-9.testprofile
+++ b/java/test-profiles/java-bdb.0-9.testprofile
@@ -25,7 +25,7 @@ broker.ready=BRK-1004
broker.stopped=Exception
broker.config=build/etc/config-systests-bdb.xml
messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes
+profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes
broker.clean.between.tests=true
broker.persistent=true
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT
diff --git a/java/test-profiles/java-dby-spawn.0-8.testprofile b/java/test-profiles/java-dby-spawn.0-8.testprofile
index c186207f6a..3a6023e78f 100644
--- a/java/test-profiles/java-dby-spawn.0-8.testprofile
+++ b/java/test-profiles/java-dby-spawn.0-8.testprofile
@@ -25,7 +25,7 @@ broker.stopped=Exception
broker.config=build/etc/config-systests-derby.xml
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT
messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
#
diff --git a/java/test-profiles/java-dby-spawn.0-9-1.testprofile b/java/test-profiles/java-dby-spawn.0-9-1.testprofile
index e7212d30f8..0e910e8ce5 100644
--- a/java/test-profiles/java-dby-spawn.0-9-1.testprofile
+++ b/java/test-profiles/java-dby-spawn.0-9-1.testprofile
@@ -25,7 +25,7 @@ broker.stopped=Exception
broker.config=build/etc/config-systests-derby.xml
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
#
diff --git a/java/test-profiles/java-dby-spawn.0-9.testprofile b/java/test-profiles/java-dby-spawn.0-9.testprofile
index bd5df9ee82..232586623c 100644
--- a/java/test-profiles/java-dby-spawn.0-9.testprofile
+++ b/java/test-profiles/java-dby-spawn.0-9.testprofile
@@ -25,7 +25,7 @@ broker.stopped=Exception
broker.config=build/etc/config-systests-derby.xml
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT
messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
#
diff --git a/java/test-profiles/java-dby.0-8.testprofile b/java/test-profiles/java-dby.0-8.testprofile
index e4e00c70c2..161c3dcfe2 100644
--- a/java/test-profiles/java-dby.0-8.testprofile
+++ b/java/test-profiles/java-dby.0-8.testprofile
@@ -26,7 +26,7 @@ broker.stopped=Exception
broker.config=build/etc/config-systests-derby.xml
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT
messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
#
diff --git a/java/test-profiles/java-dby.0-9-1.testprofile b/java/test-profiles/java-dby.0-9-1.testprofile
index 83f43d8dbf..b5561782a7 100644
--- a/java/test-profiles/java-dby.0-9-1.testprofile
+++ b/java/test-profiles/java-dby.0-9-1.testprofile
@@ -26,7 +26,7 @@ broker.stopped=Exception
broker.config=build/etc/config-systests-derby.xml
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
#
diff --git a/java/test-profiles/java-dby.0-9.testprofile b/java/test-profiles/java-dby.0-9.testprofile
index b6d1840f9f..289554e618 100644
--- a/java/test-profiles/java-dby.0-9.testprofile
+++ b/java/test-profiles/java-dby.0-9.testprofile
@@ -26,7 +26,7 @@ broker.stopped=Exception
broker.config=build/etc/config-systests-derby.xml
broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT
messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes
+profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes
broker.clean.between.tests=true
broker.persistent=true
#
diff --git a/java/test-profiles/java-mms-spawn.0-8.testprofile b/java/test-profiles/java-mms-spawn.0-8.testprofile
index e46823c3f1..b075890e58 100644
--- a/java/test-profiles/java-mms-spawn.0-8.testprofile
+++ b/java/test-profiles/java-mms-spawn.0-8.testprofile
@@ -27,4 +27,4 @@ broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude
# Do not enable. Allow client to attempt 0-10 and negotiate downwards
#
#qpid.amqp.version=0-8
-profile.excludes=JavaTransientExcludes JavaPre010Excludes
+profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes
diff --git a/java/test-profiles/java-mms-spawn.0-9-1.testprofile b/java/test-profiles/java-mms-spawn.0-9-1.testprofile
index 05b1f89452..7f80dc743a 100644
--- a/java/test-profiles/java-mms-spawn.0-9-1.testprofile
+++ b/java/test-profiles/java-mms-spawn.0-9-1.testprofile
@@ -27,4 +27,4 @@ broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
# Do not enable. Allow client to attempt 0-10 and negotiate downwards
#
#qpid.amqp.version=0-91
-profile.excludes=JavaTransientExcludes JavaPre010Excludes
+profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes
diff --git a/java/test-profiles/java-mms-spawn.0-9.testprofile b/java/test-profiles/java-mms-spawn.0-9.testprofile
index d53a9f42ad..57e670ec31 100644
--- a/java/test-profiles/java-mms-spawn.0-9.testprofile
+++ b/java/test-profiles/java-mms-spawn.0-9.testprofile
@@ -27,4 +27,4 @@ broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude
# Do not enable. Allow client to attempt 0-10 and negotiate downwards
#
#qpid.amqp.version=0-9
-profile.excludes=JavaTransientExcludes JavaPre010Excludes
+profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes
diff --git a/java/test-profiles/java-mms.0-8.testprofile b/java/test-profiles/java-mms.0-8.testprofile
index 02723ab180..d7ef32ae3b 100644
--- a/java/test-profiles/java-mms.0-8.testprofile
+++ b/java/test-profiles/java-mms.0-8.testprofile
@@ -28,4 +28,4 @@ broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude
# Do not enable. Allow client to attempt 0-10 and negotiate downwards
#
#qpid.amqp.version=0-8
-profile.excludes=JavaTransientExcludes JavaPre010Excludes
+profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes
diff --git a/java/test-profiles/java-mms.0-9-1.testprofile b/java/test-profiles/java-mms.0-9-1.testprofile
index 37efa097bb..a2dc90bc63 100644
--- a/java/test-profiles/java-mms.0-9-1.testprofile
+++ b/java/test-profiles/java-mms.0-9-1.testprofile
@@ -28,4 +28,4 @@ broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
# Do not enable. Allow client to attempt 0-10 and negotiate downwards
#
#qpid.amqp.version=0-91
-profile.excludes=JavaTransientExcludes JavaPre010Excludes
+profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes
diff --git a/java/test-profiles/java-mms.0-9.testprofile b/java/test-profiles/java-mms.0-9.testprofile
index 36ee470e09..398a9ac4d0 100644
--- a/java/test-profiles/java-mms.0-9.testprofile
+++ b/java/test-profiles/java-mms.0-9.testprofile
@@ -28,4 +28,4 @@ broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude
# Do not enable. Allow client to attempt 0-10 and negotiate downwards
#
#qpid.amqp.version=0-9
-profile.excludes=JavaTransientExcludes JavaPre010Excludes
+profile.excludes=JavaTransientExcludes XAExcludes JavaPre010Excludes
diff --git a/java/test-profiles/python_tests/Java010PythonExcludes b/java/test-profiles/python_tests/Java010PythonExcludes
index 52afb66890..fd40ebd858 100644
--- a/java/test-profiles/python_tests/Java010PythonExcludes
+++ b/java/test-profiles/python_tests/Java010PythonExcludes
@@ -19,15 +19,14 @@
###### Feature not supported in Java Broker ######
-#The broker does not support DTX
-qpid_tests.broker_0_10.dtx.*
-
-#The broker does not support message groups
-qpid_tests.broker_0_10.msg_groups.*
-
#The broker does not have the appropriate QMF support
qpid_tests.broker_0_10.management.*
qpid_tests.broker_0_10.stats.BrokerStatsTests.*
+qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_default_group_id
+qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_move_*
+qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_purge_*
+qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_query
+qpid_tests.broker_0_10.msg_groups.MultiConsumerMsgGroupTests.test_reroute
#The broker does not use the same threshold alerting system (or the QMF support needed for the tests)
qpid_tests.broker_0_10.threshold.*
@@ -51,14 +50,12 @@ qpid_tests.broker_0_10.message.MessageTests.test_ack
qpid_tests.broker_0_10.message.MessageTests.test_acquire
qpid_tests.broker_0_10.message.MessageTests.test_acquire_with_no_accept_and_credit_flow
-#QPID-3588 Java broker sets expiration and doesnt pass TTL on to consumer
-qpid.tests.messaging.message.MessageEchoTests.testProperties
-
-#QPID-3589 Difference in exception text message causes test to fail
-qpid.tests.messaging.endpoints.AddressTests.testDeleteSpecial
-
-#QPID-3590 Java broker does not support null value for routing key
-qpid.tests.messaging.endpoints.SessionTests.testDoubleCommit
+qpid_tests.broker_0_10.dtx.DtxTests.test_forget_xid_on_completion
+qpid_tests.broker_0_10.dtx.DtxTests.test_implicit_end
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_commit
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_commit
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_rollback
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_rollback
###### Java Broker defects ######
@@ -70,36 +67,6 @@ qpid_tests.broker_0_10.message.MessageTests.test_window_flow_bytes
#QPID-3605 Durable subscriber with no-local true receives messages on re-connection
qpid_tests.broker_0_10.message.MessageTests.test_no_local_awkward
-#QPID-3594 exclusive queues problem
-qpid_tests.broker_0_10.queue.QueueTests.test_declare_exclusive
-
-#QPID-3477: Java broker does not handle rejection code specified in test
-qpid.tests.messaging.endpoints.SessionTests.testReject
-
-#QPID-3595 Alternate Exchanges support requires work to be spec compliant.
-qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_delete_while_used_by_queue
-qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_modify_existing_exchange_alternate
-qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_queue_autodelete
-qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_queue_delete
-qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_queue_delete_loop
-qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_queue_delete_no_match
-qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_reject_no_match
-qpid_tests.broker_0_10.alternate_exchange.AlternateExchangeTests.test_add_alternate_to_exchange
-qpid_tests.broker_0_10.new_api.GeneralTests.test_qpid_3481_acquired_to_alt_exchange
-
-#QPID-3596 Broker does not validate for reserved exchange names on create/bind.
-qpid_tests.broker_0_10.exchange.DeclareMethodExchangeFieldReservedRuleTests.*
-
-#QPID-3597 Headers exchange issues
-qpid_tests.broker_0_10.exchange.HeadersExchangeTests.*
-qpid_tests.broker_0_10.queue.QueueTests.test_unbind_headers
-qpid_tests.broker_0_10.exchange.RecommendedTypesRuleTests.testHeaders
-qpid_tests.broker_0_10.exchange.RequiredInstancesRuleTests.testAmqMatch
-qpid_tests.broker_0_10.query.QueryTests.test_exchange_bound_header
-
-#QPID-3598 Fanout exchange issues
-qpid_tests.broker_0_10.query.QueryTests.test_exchange_bound_fanout
-
#QPID-3599 Tests fail due to differences in expected message Redelivered status
qpid.tests.messaging.endpoints.SessionTests.testCommitAck
qpid.tests.messaging.endpoints.SessionTests.testRelease
diff --git a/java/test-profiles/testprofile.defaults b/java/test-profiles/testprofile.defaults
index bd2faa7915..b0c1aea661 100644
--- a/java/test-profiles/testprofile.defaults
+++ b/java/test-profiles/testprofile.defaults
@@ -47,7 +47,7 @@ test.port.alt.ssl=25671
test.exclude=true
profile.excludes=
-test.excludes=Excludes XAExcludes JavaExcludes ${profile}.excludes ${profile.excludes}
+test.excludes=Excludes JavaExcludes ${profile}.excludes ${profile.excludes}
test.mem=512M
test=*Test
haltonfailure=no
diff --git a/python/qpid/testlib.py b/python/qpid/testlib.py
index 1da53b3378..d9feb6b484 100644
--- a/python/qpid/testlib.py
+++ b/python/qpid/testlib.py
@@ -29,6 +29,9 @@ from qpid.message import Message
from qpid.harness import Skipped
from qpid.exceptions import VersionError
+import qpid.messaging
+import qpidtoollibs.broker
+
class TestBase(unittest.TestCase):
"""Base class for Qpid test cases.
@@ -193,6 +196,15 @@ class TestBase010(unittest.TestCase):
self.qmf = qmf.console.Session(handler)
self.qmf_broker = self.qmf.addBroker(str(self.broker))
+ def startBrokerAccess(self):
+ """
+ New-style management access to the broker. Can be used in lieu of startQmf.
+ """
+ if 'broker_conn' not in self.__dict__:
+ self.broker_conn = qpid.messaging.Connection(str(self.broker))
+ self.broker_conn.open()
+ self.broker_access = qpidtoollibs.broker.BrokerAgent(self.broker_conn)
+
def connect(self, host=None, port=None):
url = self.broker
if url.scheme == URL.AMQPS:
diff --git a/python/qpid/tests/messaging/endpoints.py b/python/qpid/tests/messaging/endpoints.py
index db5ec03df2..62deacd0bd 100644
--- a/python/qpid/tests/messaging/endpoints.py
+++ b/python/qpid/tests/messaging/endpoints.py
@@ -524,7 +524,7 @@ class SessionTests(Base):
self.ssn.acknowledge(echos[0])
self.ssn.acknowledge(echos[1], Disposition(REJECTED))
self.ssn.acknowledge(echos[2],
- Disposition(REJECTED, code=3, text="test-reject"))
+ Disposition(REJECTED, code=0, text="test-reject"))
self.drain(rej, expected=msgs[1:])
self.ssn.acknowledge()
@@ -632,9 +632,9 @@ class SessionTests(Base):
def testDoubleCommit(self):
ssn = self.conn.session(transactional=True)
- snd = ssn.sender("amq.direct")
- rcv = ssn.receiver("amq.direct")
- msgs = [self.message("testDoubleCommit", i) for i in range(3)]
+ snd = ssn.sender("amq.direct/doubleCommit")
+ rcv = ssn.receiver("amq.direct/doubleCommit")
+ msgs = [self.message("testDoubleCommit", i, subject="doubleCommit") for i in range(3)]
for m in msgs:
snd.send(m)
ssn.commit()
@@ -1038,7 +1038,7 @@ class AddressTests(Base):
snd.close()
assert False, "successfully deleted amq.topic"
except SessionError, e:
- assert "Cannot delete default exchange" in str(e)
+ assert e.code == 530
# XXX: need to figure out close after error
self.conn._remove_session(self.ssn)
diff --git a/tests/src/py/qpid_tests/broker_0_10/msg_groups.py b/tests/src/py/qpid_tests/broker_0_10/msg_groups.py
index 938d3b3ee2..18fb0a61a3 100644
--- a/tests/src/py/qpid_tests/broker_0_10/msg_groups.py
+++ b/tests/src/py/qpid_tests/broker_0_10/msg_groups.py
@@ -193,6 +193,10 @@ class MultiConsumerMsgGroupTests(Base):
s2 = self.setup_session()
b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
+ m2 = b1.fetch(0);
+ assert m2.properties['THE-GROUP'] == 'A'
+ assert m2.content['index'] == 0
+
# C1 should acquire A-0
m1 = c1.fetch(0);
@@ -202,10 +206,6 @@ class MultiConsumerMsgGroupTests(Base):
## Queue = A-0, B-1, A-2, b-3, C-4
## Owners= ^C1, ---, +C1, ---, ---
- m2 = b1.fetch(0);
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 0
-
m2 = b1.fetch(0)
assert m2.properties['THE-GROUP'] == 'B'
assert m2.content['index'] == 1
diff --git a/tests/src/py/qpid_tests/broker_0_10/new_api.py b/tests/src/py/qpid_tests/broker_0_10/new_api.py
index 0bbcf342bc..5e03a7b487 100644
--- a/tests/src/py/qpid_tests/broker_0_10/new_api.py
+++ b/tests/src/py/qpid_tests/broker_0_10/new_api.py
@@ -74,7 +74,7 @@ class GeneralTests(Base):
self.assertEqual(rx_alt.available(), 0, "No messages should have been routed to the alt_exchange")
sess1.close()
-
+ sleep(1)
self.assertEqual(rx_alt.available(), 5, "All 5 messages should have been routed to the alt_exchange")
sess2.close()
@@ -108,6 +108,7 @@ class GeneralTests(Base):
# Close sess1; This will cause the queue to be deleted
sess1.close()
+ sleep(1)
self.assertEqual(rx_alt.available(), 2, "2 of the messages should have been routed to the alt_exchange")
# Close sess2; This will cause the acquired messages to be requeued and routed to the alternate
diff --git a/tools/setup.py b/tools/setup.py
index 925c20bee9..dc9a79e0b4 100755
--- a/tools/setup.py
+++ b/tools/setup.py
@@ -23,17 +23,18 @@ setup(name="qpid-tools",
version="0.15",
author="Apache Qpid",
author_email="dev@qpid.apache.org",
+ package_dir={'' : 'src/py'},
packages=["qpidtoollibs"],
- scripts=["qpid-cluster",
- "qpid-cluster-store",
- "qpid-config",
- "qpid-ha-status",
- "qpid-printevents",
- "qpid-queue-stats",
- "qpid-route",
- "qpid-stat",
- "qpid-tool",
- "qmf-tool"],
+ scripts=["src/py/qpid-cluster",
+ "src/py/qpid-cluster-store",
+ "src/py/qpid-config",
+ "src/py/qpid-ha-tool",
+ "src/py/qpid-printevents",
+ "src/py/qpid-queue-stats",
+ "src/py/qpid-route",
+ "src/py/qpid-stat",
+ "src/py/qpid-tool",
+ "src/py/qmf-tool"],
url="http://qpid.apache.org/",
license="Apache Software License",
description="Diagnostic and management tools for Apache Qpid brokers.")
diff --git a/tools/src/py/qpid-config b/tools/src/py/qpid-config
index 0110c60aa2..007b25af86 100755
--- a/tools/src/py/qpid-config
+++ b/tools/src/py/qpid-config
@@ -18,12 +18,18 @@
# specific language governing permissions and limitations
# under the License.
#
+import pdb
import os
from optparse import OptionParser, OptionGroup, IndentedHelpFormatter
import sys
import locale
-from qmf.console import Session
+
+home = os.environ.get("QPID_TOOLS_HOME", os.path.normpath("/usr/share/qpid-tools"))
+sys.path.append(os.path.join(home, "python"))
+
+from qpid.messaging import Connection
+from qpidtoollibs.broker import BrokerAgent
usage = """
Usage: qpid-config [OPTIONS]
@@ -36,15 +42,16 @@ Usage: qpid-config [OPTIONS]
qpid-config [OPTIONS] bind <exchange-name> <queue-name> [binding-key]
<for type xml> [-f -|filename]
<for type header> [all|any] k1=v1 [, k2=v2...]
- qpid-config [OPTIONS] unbind <exchange-name> <queue-name> [binding-key]"""
+ qpid-config [OPTIONS] unbind <exchange-name> <queue-name> [binding-key]
+ qpid-config [OPTIONS] reload-acl"""
description = """
Examples:
$ qpid-config add queue q
$ qpid-config add exchange direct d -a localhost:5672
-$ qpid-config exchanges -a 10.1.1.7:10000
-$ qpid-config queues -a guest/guest@broker-host:10000
+$ qpid-config exchanges -b 10.1.1.7:10000
+$ qpid-config queues -b guest/guest@broker-host:10000
Add Exchange <type> values:
@@ -55,7 +62,7 @@ Add Exchange <type> values:
xml XML Exchange - allows content filtering using an XQuery
-Queue Limit Actions
+Queue Limit Actions:
none (default) - Use broker's default policy
reject - Reject enqueued messages
@@ -63,12 +70,14 @@ Queue Limit Actions
ring - Replace oldest unacquired message with new
ring-strict - Replace oldest message, reject if oldest is acquired
-Queue Ordering Policies
+Replicate levels:
- fifo (default) - First in, first out
- lvq - Last Value Queue ordering, allows queue browsing
- lvq-no-browse - Last Value Queue ordering, browsing clients may lose data"""
+ none - no replication
+ configuration - replicate queue and exchange existence and bindings, but not messages.
+ messages - replicate configuration and messages
+"""
+REPLICATE_LEVELS= ["none", "configuration", "messages"]
class Config:
def __init__(self):
@@ -77,8 +86,8 @@ class Config:
self._connTimeout = 10
self._ignoreDefault = False
self._altern_ex = None
- self._passive = False
self._durable = False
+ self._replicate = None
self._clusterDurable = False
self._if_empty = True
self._if_unused = True
@@ -87,8 +96,8 @@ class Config:
self._maxQueueSize = None
self._maxQueueCount = None
self._limitPolicy = None
- self._order = None
self._msgSequence = False
+ self._lvq_key = None
self._ive = False
self._eventGeneration = None
self._file = None
@@ -110,8 +119,7 @@ MAX_QUEUE_SIZE = "qpid.max_size"
MAX_QUEUE_COUNT = "qpid.max_count"
POLICY_TYPE = "qpid.policy_type"
CLUSTER_DURABLE = "qpid.persist_last_node"
-LVQ = "qpid.last_value_queue"
-LVQNB = "qpid.last_value_queue_no_browse"
+LVQ_KEY = "qpid.last_value_queue_key"
MSG_SEQUENCE = "qpid.msg_sequence"
IVE = "qpid.ive"
QUEUE_EVENT_GENERATION = "qpid.queue_event_generation"
@@ -121,14 +129,18 @@ FLOW_STOP_SIZE = "qpid.flow_stop_size"
FLOW_RESUME_SIZE = "qpid.flow_resume_size"
MSG_GROUP_HDR_KEY = "qpid.group_header_key"
SHARED_MSG_GROUP = "qpid.shared_msg_group"
+REPLICATE = "qpid.replicate"
#There are various arguments to declare that have specific program
#options in this utility. However there is now a generic mechanism for
#passing arguments as well. The SPECIAL_ARGS list contains the
#arguments for which there are specific program options defined
#i.e. the arguments for which there is special processing on add and
#list
-SPECIAL_ARGS=[FILECOUNT,FILESIZE,MAX_QUEUE_SIZE,MAX_QUEUE_COUNT,POLICY_TYPE,CLUSTER_DURABLE,LVQ,LVQNB,MSG_SEQUENCE,IVE,QUEUE_EVENT_GENERATION,FLOW_STOP_COUNT,FLOW_STOP_SIZE,FLOW_RESUME_SIZE,
- MSG_GROUP_HDR_KEY,SHARED_MSG_GROUP]
+SPECIAL_ARGS=[
+ FILECOUNT,FILESIZE,MAX_QUEUE_SIZE,MAX_QUEUE_COUNT,POLICY_TYPE,CLUSTER_DURABLE,
+ LVQ_KEY,MSG_SEQUENCE,IVE,QUEUE_EVENT_GENERATION,
+ FLOW_STOP_COUNT,FLOW_STOP_SIZE,FLOW_RESUME_SIZE,
+ MSG_GROUP_HDR_KEY,SHARED_MSG_GROUP,REPLICATE]
class JHelpFormatter(IndentedHelpFormatter):
"""Format usage and description without stripping newlines from usage strings
@@ -146,7 +158,7 @@ class JHelpFormatter(IndentedHelpFormatter):
def Usage():
print usage
- exit(-1)
+ sys.exit(-1)
def OptionsAndArguments(argv):
""" Set global variables for options, return arguments """
@@ -160,8 +172,8 @@ def OptionsAndArguments(argv):
group1 = OptionGroup(parser, "General Options")
group1.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="<secs>", help="Maximum time to wait for broker connection (in seconds)")
- group1.add_option("-b", "--bindings", action="store_true", help="Show bindings in queue or exchange list")
- group1.add_option("-a", "--broker-addr", action="store", type="string", default="localhost:5672", metavar="<address>", help="Address of qpidd broker with syntax: [username/password@] hostname | ip-address [:<port>]")
+ group1.add_option("-r", "--recursive", action="store_true", help="Show bindings in queue or exchange list")
+ group1.add_option("-b", "--broker", action="store", type="string", default="localhost:5672", metavar="<address>", help="Address of qpidd broker with syntax: [username/password@] hostname | ip-address [:<port>]")
group1.add_option("--sasl-mechanism", action="store", type="string", metavar="<mech>", help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). SASL automatically picks the most secure available mechanism - use this option to override.")
parser.add_option_group(group1)
@@ -171,8 +183,8 @@ def OptionsAndArguments(argv):
group2 = OptionGroup(parser, "Options for Adding Exchanges and Queues")
group2.add_option("--alternate-exchange", action="store", type="string", metavar="<aexname>", help="Name of the alternate-exchange for the new queue or exchange. Exchanges route messages to the alternate exchange if they are unable to route them elsewhere. Queues route messages to the alternate exchange if they are rejected by a subscriber or orphaned by queue deletion.")
- group2.add_option("--passive", "--dry-run", action="store_true", help="Do not actually add the exchange or queue, ensure that all parameters and permissions are correct and would allow it to be created.")
group2.add_option("--durable", action="store_true", help="The new queue or exchange is durable.")
+ group2.add_option("--replicate", action="store", metavar="<level>", help="Replication level for the new queue or exchange (none, configuration or messages).")
parser.add_option_group(group2)
group3 = OptionGroup(parser, "Options for Adding Queues")
@@ -182,7 +194,7 @@ def OptionsAndArguments(argv):
group3.add_option("--max-queue-size", action="store", type="int", metavar="<n>", help="Maximum in-memory queue size as bytes")
group3.add_option("--max-queue-count", action="store", type="int", metavar="<n>", help="Maximum in-memory queue size as a number of messages")
group3.add_option("--limit-policy", action="store", choices=["none", "reject", "flow-to-disk", "ring", "ring-strict"], metavar="<policy>", help="Action to take when queue limit is reached")
- group3.add_option("--order", action="store", choices=["fifo", "lvq", "lvq-no-browse"], metavar="<ordering>", help="Queue ordering policy")
+ group3.add_option("--lvq-key", action="store", metavar="<key>", help="Last Value Queue key")
group3.add_option("--generate-queue-events", action="store", type="int", metavar="<n>", help="If set to 1, every enqueue will generate an event that can be processed by registered listeners (e.g. for replication). If set to 2, events will be generated for enqueues and dequeues.")
group3.add_option("--flow-stop-size", action="store", type="int", metavar="<n>",
help="Turn on sender flow control when the number of queued bytes exceeds this value.")
@@ -224,10 +236,10 @@ def OptionsAndArguments(argv):
except:
args = encArgs
- if opts.bindings:
+ if opts.recursive:
config._recursive = True
- if opts.broker_addr:
- config._host = opts.broker_addr
+ if opts.broker:
+ config._host = opts.broker
if opts.timeout is not None:
config._connTimeout = opts.timeout
if config._connTimeout == 0:
@@ -236,10 +248,12 @@ def OptionsAndArguments(argv):
config._ignoreDefault = True
if opts.alternate_exchange:
config._altern_ex = opts.alternate_exchange
- if opts.passive:
- config._passive = True
if opts.durable:
config._durable = True
+ if opts.replicate:
+ if not opts.replicate in REPLICATE_LEVELS:
+ raise Exception("Invalid replicate level '%s', should be one of: %s" % (opts.replicate, ", ".join(REPLICATE_LEVELS)))
+ config._replicate = opts.replicate
if opts.cluster_durable:
config._clusterDurable = True
if opts.file:
@@ -254,10 +268,10 @@ def OptionsAndArguments(argv):
config._maxQueueCount = opts.max_queue_count
if opts.limit_policy:
config._limitPolicy = opts.limit_policy
- if opts.order:
- config._order = opts.order
if opts.sequence:
config._msgSequence = True
+ if opts.lvq_key:
+ config._lvq_key = opts.lvq_key
if opts.ive:
config._ive = True
if opts.generate_queue_events:
@@ -331,27 +345,23 @@ def snarf_header_args(args):
class BrokerManager:
def __init__(self):
self.brokerName = None
- self.qmf = None
+ self.conn = None
self.broker = None
- self.mechanism = None
def SetBroker(self, brokerUrl, mechanism):
self.url = brokerUrl
- self.qmf = Session()
- self.broker = self.qmf.addBroker(brokerUrl, config._connTimeout, mechanism)
- agents = self.qmf.getAgents()
- for a in agents:
- if a.getAgentBank() == '0':
- self.brokerAgent = a
+ self.conn = Connection(self.url, sasl_mechanisms=mechanism)
+ self.conn.open()
+ self.broker = BrokerAgent(self.conn)
def Disconnect(self):
- if self.broker:
- self.qmf.delBroker(self.broker)
+ if self.conn:
+ self.conn.close()
def Overview(self):
- exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent)
- queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
- print "Total Exchanges: %d" % len (exchanges)
+ exchanges = self.broker.getAllExchanges()
+ queues = self.broker.getAllQueues()
+ print "Total Exchanges: %d" % len(exchanges)
etype = {}
for ex in exchanges:
if ex.type not in etype:
@@ -362,16 +372,16 @@ class BrokerManager:
print "%15s: %d" % (typ, etype[typ])
print
- print " Total Queues: %d" % len (queues)
+ print " Total Queues: %d" % len(queues)
durable = 0
for queue in queues:
if queue.durable:
durable = durable + 1
print " durable: %d" % durable
- print " non-durable: %d" % (len (queues) - durable)
+ print " non-durable: %d" % (len(queues) - durable)
def ExchangeList(self, filter):
- exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent)
+ exchanges = self.broker.getAllExchanges()
caption1 = "Type "
caption2 = "Exchange Name"
maxNameLen = len(caption2)
@@ -401,19 +411,19 @@ class BrokerManager:
if MSG_SEQUENCE in args and args[MSG_SEQUENCE] == 1: print "--sequence",
if IVE in args and args[IVE] == 1: print "--ive",
if ex.altExchange:
- print "--alternate-exchange=%s" % ex._altExchange_.name,
+ print "--alternate-exchange=%s" % ex.altExchange,
print
def ExchangeListRecurse(self, filter):
- exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent)
- bindings = self.qmf.getObjects(_class="binding", _agent=self.brokerAgent)
- queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
+ exchanges = self.broker.getAllExchanges()
+ bindings = self.broker.getAllBindings()
+ queues = self.broker.getAllQueues()
for ex in exchanges:
if config._ignoreDefault and not ex.name: continue
if self.match(ex.name, filter):
print "Exchange '%s' (%s)" % (ex.name, ex.type)
for bind in bindings:
- if bind.exchangeRef == ex.getObjectId():
+ if bind.exchangeRef == ex.name:
qname = "<unknown>"
queue = self.findById(queues, bind.queueRef)
if queue != None:
@@ -425,7 +435,7 @@ class BrokerManager:
def QueueList(self, filter):
- queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
+ queues = self.broker.getAllQueues()
caption = "Queue Name"
maxNameLen = len(caption)
found = False
@@ -450,6 +460,7 @@ class BrokerManager:
args = q.arguments
if not args: args = {}
if q.durable: print "--durable",
+ if REPLICATE in args: print "--replicate=%s" % args[REPLICATE],
if CLUSTER_DURABLE in args and args[CLUSTER_DURABLE] == 1: print "--cluster-durable",
if q.autoDelete: print "auto-del",
if q.exclusive: print "excl",
@@ -458,8 +469,7 @@ class BrokerManager:
if MAX_QUEUE_SIZE in args: print "--max-queue-size=%s" % args[MAX_QUEUE_SIZE],
if MAX_QUEUE_COUNT in args: print "--max-queue-count=%s" % args[MAX_QUEUE_COUNT],
if POLICY_TYPE in args: print "--limit-policy=%s" % args[POLICY_TYPE].replace("_", "-"),
- if LVQ in args and args[LVQ] == 1: print "--order lvq",
- if LVQNB in args and args[LVQNB] == 1: print "--order lvq-no-browse",
+ if LVQ_KEY in args: print "--lvq-key=%s" % args[LVQ_KEY],
if QUEUE_EVENT_GENERATION in args: print "--generate-queue-events=%s" % args[QUEUE_EVENT_GENERATION],
if q.altExchange:
print "--alternate-exchange=%s" % q._altExchange_.name,
@@ -472,14 +482,14 @@ class BrokerManager:
print " ".join(["--argument %s=%s" % (k, v) for k,v in args.iteritems() if not k in SPECIAL_ARGS])
def QueueListRecurse(self, filter):
- exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent)
- bindings = self.qmf.getObjects(_class="binding", _agent=self.brokerAgent)
- queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
+ exchanges = self.broker.getAllExchanges()
+ bindings = self.broker.getAllBindings()
+ queues = self.broker.getAllQueues()
for queue in queues:
if self.match(queue.name, filter):
print "Queue '%s'" % queue.name
for bind in bindings:
- if bind.queueRef == queue.getObjectId():
+ if bind.queueRef == queue.name:
ename = "<unknown>"
ex = self.findById(exchanges, bind.exchangeRef)
if ex != None:
@@ -508,16 +518,21 @@ class BrokerManager:
declArgs[MSG_SEQUENCE] = 1
if config._ive:
declArgs[IVE] = 1
- if config._altern_ex != None:
- self.broker.getAmqpSession().exchange_declare(exchange=ename, type=etype, alternate_exchange=config._altern_ex, passive=config._passive, durable=config._durable, arguments=declArgs)
- else:
- self.broker.getAmqpSession().exchange_declare(exchange=ename, type=etype, passive=config._passive, durable=config._durable, arguments=declArgs)
+ if config._altern_ex:
+ declArgs['alternate-exchange'] = config._altern_ex
+ if config._durable:
+ declArgs['durable'] = 1
+ if config._replicate:
+ declArgs[REPLICATE] = config._replicate
+ self.broker.addExchange(etype, ename, declArgs)
+
def DelExchange(self, args):
if len(args) < 1:
Usage()
ename = args[0]
- self.broker.getAmqpSession().exchange_delete(exchange=ename)
+ self.broker.delExchange(ename)
+
def AddQueue(self, args):
if len(args) < 1:
@@ -550,15 +565,10 @@ class BrokerManager:
elif config._limitPolicy == "ring-strict":
declArgs[POLICY_TYPE] = "ring_strict"
- if config._clusterDurable:
+ if config._clusterDurable:
declArgs[CLUSTER_DURABLE] = 1
- if config._order:
- if config._order == "fifo":
- pass
- elif config._order == "lvq":
- declArgs[LVQ] = 1
- elif config._order == "lvq-no-browse":
- declArgs[LVQNB] = 1
+ if config._lvq_key:
+ declArgs[LVQ_KEY] = config._lvq_key
if config._eventGeneration:
declArgs[QUEUE_EVENT_GENERATION] = config._eventGeneration
@@ -576,17 +586,21 @@ class BrokerManager:
if config._sharedMsgGroup:
declArgs[SHARED_MSG_GROUP] = 1
- if config._altern_ex != None:
- self.broker.getAmqpSession().queue_declare(queue=qname, alternate_exchange=config._altern_ex, passive=config._passive, durable=config._durable, arguments=declArgs)
- else:
- self.broker.getAmqpSession().queue_declare(queue=qname, passive=config._passive, durable=config._durable, arguments=declArgs)
+ if config._altern_ex:
+ declArgs['alternate-exchange'] = config._altern_ex
+ if config._durable:
+ declArgs['durable'] = 1
+ if config._replicate:
+ declArgs[REPLICATE] = config._replicate
+
+ self.broker.addQueue(qname, declArgs)
def DelQueue(self, args):
if len(args) < 1:
Usage()
qname = args[0]
- self.broker.getAmqpSession().queue_delete(queue=qname, if_empty=config._if_empty, if_unused=config._if_unused)
+ self.broker.delQueue(qname)
def Bind(self, args):
@@ -599,7 +613,7 @@ class BrokerManager:
key = args[2]
# query the exchange to determine its type.
- res = self.broker.getAmqpSession().exchange_query(ename)
+ res = self.broker.getExchange(ename)
# type of the xchg determines the processing of the rest of
# argv. if it's an xml xchg, we want to find a file
@@ -608,7 +622,7 @@ class BrokerManager:
# map containing key/value pairs. if neither of those, extra
# args are ignored.
ok = True
- _args = None
+ _args = {}
if res.type == "xml":
# this checks/imports the -f arg
[ok, xquery] = snarf_xquery_args()
@@ -622,10 +636,7 @@ class BrokerManager:
if not ok:
sys.exit(1)
- self.broker.getAmqpSession().exchange_bind(queue=qname,
- exchange=ename,
- binding_key=key,
- arguments=_args)
+ self.broker.bind(ename, qname, key, _args)
def Unbind(self, args):
if len(args) < 2:
@@ -635,11 +646,20 @@ class BrokerManager:
key = ""
if len(args) > 2:
key = args[2]
- self.broker.getAmqpSession().exchange_unbind(queue=qname, exchange=ename, binding_key=key)
+ self.broker.unbind(ename, qname, key)
+
+ def ReloadAcl(self):
+ try:
+ self.broker.reloadAclFile()
+ except Exception, e:
+ if str(e).find('No object found') != -1:
+ print "Failed: ACL Module Not Loaded in Broker"
+ else:
+ raise
def findById(self, items, id):
for item in items:
- if item.getObjectId() == id:
+ if item.name == id:
return item
return None
@@ -697,6 +717,8 @@ def main(argv=None):
bm.Bind(args[1:])
elif cmd == "unbind":
bm.Unbind(args[1:])
+ elif cmd == "reload-acl":
+ bm.ReloadAcl()
else:
Usage()
except KeyboardInterrupt:
diff --git a/tools/src/py/qpid-ha b/tools/src/py/qpid-ha
new file mode 100755
index 0000000000..90e11fc5ab
--- /dev/null
+++ b/tools/src/py/qpid-ha
@@ -0,0 +1,239 @@
+#!/usr/bin/env python
+
+#
+# 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.
+#
+
+import qmf.console, optparse, sys
+from qpid.management import managementChannel, managementClient
+from qpid.messaging import Connection
+from qpid.messaging import Message as QpidMessage
+try:
+ from uuid import uuid4
+except ImportError:
+ from qpid.datatypes import uuid4
+
+# Utility for doing fast qmf2 operations on a broker.
+class QmfBroker(object):
+ def __init__(self, conn):
+ self.conn = conn
+ self.sess = self.conn.session()
+ self.reply_to = "qmf.default.topic/direct.%s;{node:{type:topic}, link:{x-declare:{auto-delete:True,exclusive:True}}}" % \
+ str(uuid4())
+ self.reply_rx = self.sess.receiver(self.reply_to)
+ self.reply_rx.capacity = 10
+ self.tx = self.sess.sender("qmf.default.direct/broker")
+ self.next_correlator = 1
+
+ def close(self):
+ self.conn.close()
+
+ def __repr__(self):
+ return "Qpid Broker: %s" % self.url
+
+ def _method(self, method, arguments, addr="org.apache.qpid.broker:broker:amqp-broker"):
+ props = {'method' : 'request',
+ 'qmf.opcode' : '_method_request',
+ 'x-amqp-0-10.app-id' : 'qmf2'}
+ correlator = str(self.next_correlator)
+ self.next_correlator += 1
+
+ content = {'_object_id' : {'_object_name' : addr},
+ '_method_name' : method,
+ '_arguments' : arguments}
+
+ message = QpidMessage(content, reply_to=self.reply_to, correlation_id=correlator,
+ properties=props, subject="broker")
+ self.tx.send(message)
+ response = self.reply_rx.fetch(10)
+ if response.properties['qmf.opcode'] == '_exception':
+ raise Exception("Exception from Agent: %r" % response.content['_values'])
+ if response.properties['qmf.opcode'] != '_method_response':
+ raise Exception("bad response: %r" % response.properties)
+ return response.content['_arguments']
+
+ def _sendRequest(self, opcode, content):
+ props = {'method' : 'request',
+ 'qmf.opcode' : opcode,
+ 'x-amqp-0-10.app-id' : 'qmf2'}
+ correlator = str(self.next_correlator)
+ self.next_correlator += 1
+ message = QpidMessage(content, reply_to=self.reply_to, correlation_id=correlator,
+ properties=props, subject="broker")
+ self.tx.send(message)
+ return correlator
+
+ def _doClassQuery(self, class_name):
+ query = {'_what' : 'OBJECT',
+ '_schema_id' : {'_class_name' : class_name}}
+ correlator = self._sendRequest('_query_request', query)
+ response = self.reply_rx.fetch(10)
+ if response.properties['qmf.opcode'] != '_query_response':
+ raise Exception("bad response")
+ items = []
+ done = False
+ while not done:
+ for item in response.content:
+ items.append(item['_values'])
+ if 'partial' in response.properties:
+ response = self.reply_rx.fetch(10)
+ else:
+ done = True
+ return items
+
+ def _doNameQuery(self, class_name, object_name, package_name='org.apache.qpid.broker'):
+ query = {'_what' : 'OBJECT',
+ '_object_id' : {'_object_name' : "%s:%s:%s" % (package_name, class_name, object_name)}}
+ correlator = self._sendRequest('_query_request', query)
+ response = self.reply_rx.fetch(10)
+ if response.properties['qmf.opcode'] != '_query_response':
+ raise Exception("bad response")
+ items = []
+ done = False
+ while not done:
+ for item in response.content:
+ items.append(item['_values'])
+ if 'partial' in response.properties:
+ response = self.reply_rx.fetch(10)
+ else:
+ done = True
+ if len(items) == 1:
+ return items[0]
+ return None
+
+ def _getAllBrokerObjects(self, cls):
+ items = self._doClassQuery(cls.__name__.lower())
+ objs = []
+ for item in items:
+ objs.append(cls(self, item))
+ return objs
+
+ def _getBrokerObject(self, cls, name):
+ obj = self._doNameQuery(cls.__name__.lower(), name)
+ if obj:
+ return cls(self, obj)
+ return None
+
+ def get_ha_broker(self):
+ ha_brokers = self._doClassQuery("habroker")
+ if (not ha_brokers): raise Exception("Broker does not have HA enabled.")
+ return ha_brokers[0]
+
+HA_BROKER = "org.apache.qpid.ha:habroker:ha-broker"
+
+class Command:
+ commands = {}
+
+ def __init__(self, name, help, args=[]):
+ Command.commands[name] = self
+ self.name = name
+ self.args = args
+ usage="%s [options] %s\n\n%s"%(name, " ".join(args), help)
+ self.help = help
+ self.op=optparse.OptionParser(usage)
+ self.op.add_option("-b", "--broker", metavar="<url>", help="Connect to broker at <url>")
+
+ def execute(self, command):
+ opts, args = self.op.parse_args(command)
+ if len(args) != len(self.args)+1:
+ self.op.print_help()
+ print "Error: wrong number of arguments"
+ return
+ broker = opts.broker or "localhost:5672"
+ # FIXME aconway 2012-02-23: enforce not doing primary-only operations on a backup & vice versa
+ connection = Connection.establish(broker, client_properties={"qpid.ha-admin":1})
+ try: self.do_execute(QmfBroker(connection), opts, args)
+ finally: connection.close()
+
+ def do_execute(self, qmf_broker, opts, args):
+ raise Exception("Command '%s' is not yet implemented"%self.name)
+
+def print_all_help(name):
+ print "usage: %s <command> [<arguments>]\n\nCommands are:\n"%name
+ for c in Command.commands:
+ help = Command.commands[c].help
+ print " %-12s %s."%(c, help.split(".")[0])
+ print "\nFor help with a command: %s <command> --help\n"%name
+
+
+class PromoteCmd(Command):
+ def __init__(self):
+ Command.__init__(self, "promote","Promote broker from backup to primary")
+ def do_execute(self, qmf_broker, opts, args):
+ qmf_broker._method("promote", {}, HA_BROKER)
+PromoteCmd()
+
+class ReadyCmd(Command):
+ def __init__(self):
+ Command.__init__(self, "ready", "Test if a backup broker is ready.\nReturn 0 if broker is a ready backup, non-0 otherwise.")
+ self.op.add_option(
+ "--wait", type="int", metavar="<seconds>",
+ help="Wait up to <seconds> for broker to be ready. 0 means wait forever.")
+ReadyCmd()
+
+class ReplicateCmd(Command):
+ def __init__(self):
+ Command.__init__(self, "replicate", "Replicate <queue> from broker <primary> to the current broker.", ["<queue>", "<primary>"])
+ReplicateCmd()
+
+class SetCmd(Command):
+ def __init__(self):
+ Command.__init__(self, "set", "Set HA configuration settings")
+ def add(optname, metavar, type, help):
+ self.op.add_option(optname, metavar=metavar, type=type, help=help, action="store")
+ add("--brokers", "<url>", "string", "HA brokers use <url> to connect to each other")
+ add("--public-brokers", "<url>", "string", "Clients use <url> to connect to HA brokers")
+ add("--backups", "<n>", "int", "Expect <n> backups to be running")
+
+ def do_execute(self, qmf_broker, opts, args):
+ if (opts.brokers): qmf_broker._method("setBrokers", {"url":opts.brokers}, HA_BROKER)
+ if (opts.public_brokers): qmf_broker._method("setPublicBrokers", {"url":opts.public_brokers}, HA_BROKER)
+ if (opts.backups): qmf_broker._method("setExpectedBackups", {"expectedBackups":opts.backups}, HA_BROKER)
+SetCmd()
+
+class QueryCmd(Command):
+ def __init__(self):
+ Command.__init__(self, "query", "Print HA configuration settings")
+
+ def do_execute(self, qmf_broker, opts, args):
+ hb = qmf_broker.get_ha_broker()
+ for x in [("Status:", "status"),
+ ("Brokers URL:", "brokers"),
+ ("Public URL:", "publicBrokers")]:
+ print "%-16s%s"%(x[0], hb[x[1]])
+
+QueryCmd()
+
+def main(argv):
+ try:
+ command=argv[1:]
+ if command and command[0] == "--help-all":
+ for c in Command.commands.itervalues():
+ c.op.print_help(); print
+ return 1
+ if not command or not command[0] in Command.commands:
+ print_all_help(argv[0]);
+ return 1;
+ Command.commands[command[0]].execute(command)
+ except Exception, e:
+ raise # FIXME aconway 2012-02-23:
+ print e
+ return 1
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/tools/src/py/qpid-ha-tool b/tools/src/py/qpid-ha-tool
deleted file mode 100755
index 8e8107657c..0000000000
--- a/tools/src/py/qpid-ha-tool
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/env python
-
-#
-# 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.
-#
-
-import qmf.console, optparse, sys
-from qpid.management import managementChannel, managementClient
-from qpid.messaging import Connection
-from qpid.messaging import Message as QpidMessage
-try:
- from uuid import uuid4
-except ImportError:
- from qpid.datatypes import uuid4
-
-# Utility for doing fast qmf2 operations on a broker.
-class QmfBroker(object):
- def __init__(self, conn):
- self.conn = conn
- self.sess = self.conn.session()
- self.reply_to = "qmf.default.topic/direct.%s;{node:{type:topic}, link:{x-declare:{auto-delete:True,exclusive:True}}}" % \
- str(uuid4())
- self.reply_rx = self.sess.receiver(self.reply_to)
- self.reply_rx.capacity = 10
- self.tx = self.sess.sender("qmf.default.direct/broker")
- self.next_correlator = 1
-
- def close(self):
- self.conn.close()
-
- def __repr__(self):
- return "Qpid Broker: %s" % self.url
-
- def _method(self, method, arguments, addr="org.apache.qpid.broker:broker:amqp-broker"):
- props = {'method' : 'request',
- 'qmf.opcode' : '_method_request',
- 'x-amqp-0-10.app-id' : 'qmf2'}
- correlator = str(self.next_correlator)
- self.next_correlator += 1
-
- content = {'_object_id' : {'_object_name' : addr},
- '_method_name' : method,
- '_arguments' : arguments}
-
- message = QpidMessage(content, reply_to=self.reply_to, correlation_id=correlator,
- properties=props, subject="broker")
- self.tx.send(message)
- response = self.reply_rx.fetch(10)
- if response.properties['qmf.opcode'] == '_exception':
- raise Exception("Exception from Agent: %r" % response.content['_values'])
- if response.properties['qmf.opcode'] != '_method_response':
- raise Exception("bad response: %r" % response.properties)
- return response.content['_arguments']
-
- def _sendRequest(self, opcode, content):
- props = {'method' : 'request',
- 'qmf.opcode' : opcode,
- 'x-amqp-0-10.app-id' : 'qmf2'}
- correlator = str(self.next_correlator)
- self.next_correlator += 1
- message = QpidMessage(content, reply_to=self.reply_to, correlation_id=correlator,
- properties=props, subject="broker")
- self.tx.send(message)
- return correlator
-
- def _doClassQuery(self, class_name):
- query = {'_what' : 'OBJECT',
- '_schema_id' : {'_class_name' : class_name}}
- correlator = self._sendRequest('_query_request', query)
- response = self.reply_rx.fetch(10)
- if response.properties['qmf.opcode'] != '_query_response':
- raise Exception("bad response")
- items = []
- done = False
- while not done:
- for item in response.content:
- items.append(item['_values'])
- if 'partial' in response.properties:
- response = self.reply_rx.fetch(10)
- else:
- done = True
- return items
-
- def _doNameQuery(self, class_name, object_name, package_name='org.apache.qpid.broker'):
- query = {'_what' : 'OBJECT',
- '_object_id' : {'_object_name' : "%s:%s:%s" % (package_name, class_name, object_name)}}
- correlator = self._sendRequest('_query_request', query)
- response = self.reply_rx.fetch(10)
- if response.properties['qmf.opcode'] != '_query_response':
- raise Exception("bad response")
- items = []
- done = False
- while not done:
- for item in response.content:
- items.append(item['_values'])
- if 'partial' in response.properties:
- response = self.reply_rx.fetch(10)
- else:
- done = True
- if len(items) == 1:
- return items[0]
- return None
-
- def _getAllBrokerObjects(self, cls):
- items = self._doClassQuery(cls.__name__.lower())
- objs = []
- for item in items:
- objs.append(cls(self, item))
- return objs
-
- def _getBrokerObject(self, cls, name):
- obj = self._doNameQuery(cls.__name__.lower(), name)
- if obj:
- return cls(self, obj)
- return None
-
-
-op=optparse.OptionParser(usage="Usage: %prog [options] [broker-address]")
-
-op.add_option("-p", "--promote", action="store_true",
- help="Promote a backup broker to become the primary.")
-op.add_option("-c", "--client-addresses", action="store", type="string",
- help="Set list of addresses used by clients to connect to the HA cluster.")
-op.add_option("-b", "--broker-addresses", action="store", type="string",
- help="Set list of addresses used by HA brokers to connect to each other.")
-op.add_option("-q", "--query", action="store_true",
- help="Show the current HA settings on the broker.")
-
-def get_ha_broker(qmf_broker):
- ha_brokers = qmf_broker._doClassQuery("habroker")
- if (not ha_brokers): raise Exception("Broker does not have HA enabled.")
- return ha_brokers[0]
-
-def main(argv):
- try:
- opts, args = op.parse_args(argv)
- if len(args) >1: broker = args[1]
- else: broker = "localhost:5672"
- conn = Connection.establish(broker, client_properties={"qpid.ha-admin":1})
- ha_broker = "org.apache.qpid.ha:habroker:ha-broker"
- try:
- qmf_broker = QmfBroker(conn)
- get_ha_broker(qmf_broker) # Verify that HA is enabled
- action=False
- if opts.promote:
- qmf_broker._method("promote", {}, ha_broker)
- action=True
- if opts.broker_addresses:
- qmf_broker._method('setBrokerAddresses', {'brokerAddresses':opts.broker_addresses}, ha_broker)
- action=True
- if opts.client_addresses:
- qmf_broker._method('setClientAddresses', {'clientAddresses':opts.client_addresses}, ha_broker)
- action=True
- if opts.query or not action:
- hb = get_ha_broker(qmf_broker)
- print "status=%s"%hb["status"]
- print "broker-addresses=%s"%hb["brokerAddresses"]
- print "client-addresses=%s"%hb["clientAddresses"]
- return 0
- finally:
- conn.close() # Avoid errors shutting down threads.
- except Exception, e:
- raise # FIXME aconway 2012-01-31:
- print e
- return 1
-
-if __name__ == "__main__":
- sys.exit(main(sys.argv))
diff --git a/tools/src/py/qpid-stat b/tools/src/py/qpid-stat
index bb094554e6..cfe88c5eb3 100755
--- a/tools/src/py/qpid-stat
+++ b/tools/src/py/qpid-stat
@@ -31,7 +31,7 @@ home = os.environ.get("QPID_TOOLS_HOME", os.path.normpath("/usr/share/qpid-tools
sys.path.append(os.path.join(home, "python"))
from qpidtoollibs.broker import BrokerAgent
-from qpidtoollibs.disp import Display, Header, Sorter
+from qpidtoollibs.disp import Display, Header, Sorter, YN, Commas, TimeLong
class Config:
@@ -42,7 +42,6 @@ class Config:
self._limit = 50
self._increasing = False
self._sortcol = None
- self._details = None
self._sasl_mechanism = None
config = Config()
@@ -52,42 +51,43 @@ def OptionsAndArguments(argv):
global config
- parser = OptionParser(usage="usage: %prog [options] BROKER",
- description="Example: $ qpid-stat -q broker-host:10000")
+ parser = OptionParser(usage="usage: %prog [options] -[gcequm] [object-name]")
group1 = OptionGroup(parser, "General Options")
- group1.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="<secs>", help="Maximum time to wait for broker connection (in seconds)")
- group1.add_option("--sasl-mechanism", action="store", type="string", metavar="<mech>", help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). SASL automatically picks the most secure available mechanism - use this option to override.")
+ group1.add_option("-b", "--broker", action="store", type="string", default="localhost", metavar="<url>",
+ help="URL of the broker to query")
+ group1.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="<secs>",
+ help="Maximum time to wait for broker connection (in seconds)")
+ group1.add_option("--sasl-mechanism", action="store", type="string", metavar="<mech>",
+ help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). SASL automatically picks the most secure available mechanism - use this option to override.")
parser.add_option_group(group1)
group2 = OptionGroup(parser, "Display Options")
- group2.add_option("-b", "--broker", help="Show Brokers", action="store_const", const="b", dest="show")
- group2.add_option("-c", "--connections", help="Show Connections", action="store_const", const="c", dest="show")
- group2.add_option("-e", "--exchanges", help="Show Exchanges", action="store_const", const="e", dest="show")
- group2.add_option("-q", "--queues", help="Show Queues", action="store_const", const="q", dest="show")
- group2.add_option("-u", "--subscriptions", help="Show Subscriptions", action="store_const", const="u", dest="show")
- group2.add_option("-m", "--memory", help="Show Broker Memory Stats", action="store_const", const="m", dest="show")
+ group2.add_option("-g", "--general", help="Show General Broker Stats", action="store_const", const="g", dest="show")
+ group2.add_option("-c", "--connections", help="Show Connections", action="store_const", const="c", dest="show")
+ group2.add_option("-e", "--exchanges", help="Show Exchanges", action="store_const", const="e", dest="show")
+ group2.add_option("-q", "--queues", help="Show Queues", action="store_const", const="q", dest="show")
+ group2.add_option("-u", "--subscriptions", help="Show Subscriptions", action="store_const", const="u", dest="show")
+ group2.add_option("-m", "--memory", help="Show Broker Memory Stats", action="store_const", const="m", dest="show")
+ group2.add_option( "--acl", help="Show Access Control List Stats", action="store_const", const="acl", dest="show")
group2.add_option("-S", "--sort-by", metavar="<colname>", help="Sort by column name")
group2.add_option("-I", "--increasing", action="store_true", default=False, help="Sort by increasing value (default = decreasing)")
group2.add_option("-L", "--limit", type="int", default=50, metavar="<n>", help="Limit output to n rows")
- group2.add_option("-D", "--details", action="store", metavar="<name>", dest="detail", default=None, help="Display details on a single object.")
+
parser.add_option_group(group2)
opts, args = parser.parse_args(args=argv)
if not opts.show:
- parser.error("You must specify one of these options: -b, -c, -e, -q. or -u. For details, try $ qpid-stat --help")
+ parser.error("You must specify one of these options: -g, -c, -e, -q, -m, or -u. For details, try $ qpid-stat --help")
config._types = opts.show
config._sortcol = opts.sort_by
+ config._host = opts.broker
config._connTimeout = opts.timeout
config._increasing = opts.increasing
config._limit = opts.limit
config._sasl_mechanism = opts.sasl_mechanism
- config._detail = opts.detail
-
- if args:
- config._host = args[0]
return args
@@ -118,24 +118,23 @@ class IpAddr:
class BrokerManager:
def __init__(self):
- self.brokerName = None
- self.connections = []
- self.brokers = []
- self.cluster = None
+ self.brokerName = None
+ self.connection = None
+ self.broker = None
+ self.cluster = None
def SetBroker(self, brokerUrl, mechanism):
self.url = brokerUrl
- self.connections.append(Connection(self.url, sasl_mechanism=mechanism))
- self.connections[0].open()
- self.brokers.append(BrokerAgent(self.connections[0]))
+ self.connection = Connection(self.url, sasl_mechanisms=mechanism)
+ self.connection.open()
+ self.broker = BrokerAgent(self.connection)
def Disconnect(self):
""" Release any allocated brokers. Ignore any failures as the tool is
shutting down.
"""
try:
- for conn in self.connections:
- conn.close()
+ connection.close()
except:
pass
@@ -175,7 +174,7 @@ class BrokerManager:
hosts.append(bestUrl)
return hosts
- def displayBroker(self, subs):
+ def displayBroker(self):
disp = Display(prefix=" ")
heads = []
heads.append(Header('uptime', Header.DURATION))
@@ -184,7 +183,7 @@ class BrokerManager:
heads.append(Header('exchanges', Header.COMMAS))
heads.append(Header('queues', Header.COMMAS))
rows = []
- broker = self.brokers[0].getBroker()
+ broker = self.broker.getBroker()
connections = self.getConnectionMap()
sessions = self.getSessionMap()
exchanges = self.getExchangeMap()
@@ -229,7 +228,7 @@ class BrokerManager:
disp.formattedTable('Aggregate Broker Statistics:', heads, rows)
- def displayConn(self, subs):
+ def displayConn(self):
disp = Display(prefix=" ")
heads = []
heads.append(Header('client-addr'))
@@ -241,8 +240,8 @@ class BrokerManager:
heads.append(Header('msgIn', Header.KMG))
heads.append(Header('msgOut', Header.KMG))
rows = []
- connections = self.brokers[0].getAllConnections()
- broker = self.brokers[0].getBroker()
+ connections = self.broker.getAllConnections()
+ broker = self.broker.getBroker()
for conn in connections:
row = []
row.append(conn.address)
@@ -262,10 +261,10 @@ class BrokerManager:
dispRows = rows
disp.formattedTable(title, heads, dispRows)
- def displaySession(self, subs):
+ def displaySession(self):
disp = Display(prefix=" ")
- def displayExchange(self, subs):
+ def displayExchange(self):
disp = Display(prefix=" ")
heads = []
heads.append(Header("exchange"))
@@ -279,7 +278,7 @@ class BrokerManager:
heads.append(Header("byteOut", Header.KMG))
heads.append(Header("byteDrop", Header.KMG))
rows = []
- exchanges = self.brokers[0].getAllExchanges()
+ exchanges = self.broker.getAllExchanges()
for ex in exchanges:
row = []
row.append(ex.name)
@@ -301,7 +300,7 @@ class BrokerManager:
dispRows = rows
disp.formattedTable(title, heads, dispRows)
- def displayQueues(self, subs):
+ def displayQueues(self):
disp = Display(prefix=" ")
heads = []
heads.append(Header("queue"))
@@ -317,7 +316,7 @@ class BrokerManager:
heads.append(Header("cons", Header.KMG))
heads.append(Header("bind", Header.KMG))
rows = []
- queues = self.brokers[0].getAllQueues()
+ queues = self.broker.getAllQueues()
for q in queues:
row = []
row.append(q.name)
@@ -341,11 +340,67 @@ class BrokerManager:
dispRows = rows
disp.formattedTable(title, heads, dispRows)
- def displayQueue(self, subs):
+
+ def displayQueue(self, name):
+ queue = self.broker.getQueue(name)
+ if not queue:
+ print "Queue '%s' not found" % name
+ return
+
disp = Display(prefix=" ")
heads = []
+ heads.append(Header('Name'))
+ heads.append(Header('Durable', Header.YN))
+ heads.append(Header('AutoDelete', Header.YN))
+ heads.append(Header('Exclusive', Header.YN))
+ heads.append(Header('FlowStopped', Header.YN))
+ heads.append(Header('FlowStoppedCount', Header.COMMAS))
+ heads.append(Header('Consumers', Header.COMMAS))
+ heads.append(Header('Bindings', Header.COMMAS))
+ rows = []
+ rows.append([queue.name, queue.durable, queue.autoDelete, queue.exclusive,
+ queue.flowStopped, queue.flowStoppedCount,
+ queue.consumerCount, queue.bindingCount])
+ disp.formattedTable("Properties:", heads, rows)
+ print
+
+ heads = []
+ heads.append(Header('Property'))
+ heads.append(Header('Value'))
+ rows = []
+ rows.append(['arguments', queue.arguments])
+ rows.append(['alt-exchange', queue.altExchange])
+ disp.formattedTable("Optional Properties:", heads, rows)
+ print
- def displaySubscriptions(self, subs):
+ heads = []
+ heads.append(Header('Statistic'))
+ heads.append(Header('Messages', Header.COMMAS))
+ heads.append(Header('Bytes', Header.COMMAS))
+ rows = []
+ rows.append(['queue-depth', queue.msgDepth, queue.byteDepth])
+ rows.append(['total-enqueues', queue.msgTotalEnqueues, queue.byteTotalEnqueues])
+ rows.append(['total-dequeues', queue.msgTotalDequeues, queue.byteTotalDequeues])
+ rows.append(['persistent-enqueues', queue.msgPersistEnqueues, queue.bytePersistEnqueues])
+ rows.append(['persistent-dequeues', queue.msgPersistDequeues, queue.bytePersistDequeues])
+ rows.append(['transactional-enqueues', queue.msgTxnEnqueues, queue.byteTxnEnqueues])
+ rows.append(['transactional-dequeues', queue.msgTxnDequeues, queue.byteTxnDequeues])
+ rows.append(['flow-to-disk-depth', queue.msgFtdDepth, queue.byteFtdDepth])
+ rows.append(['flow-to-disk-enqueues', queue.msgFtdEnqueues, queue.byteFtdEnqueues])
+ rows.append(['flow-to-disk-dequeues', queue.msgFtdDequeues, queue.byteFtdDequeues])
+ rows.append(['acquires', queue.acquires, None])
+ rows.append(['releases', queue.releases, None])
+ rows.append(['discards-ttl-expired', queue.discardsTtl, None])
+ rows.append(['discards-limit-overflow', queue.discardsOverflow, None])
+ rows.append(['discards-ring-overflow', queue.discardsRing, None])
+ rows.append(['discards-lvq-replace', queue.discardsLvq, None])
+ rows.append(['discards-subscriber-reject', queue.discardsSubscriber, None])
+ rows.append(['discards-purged', queue.discardsPurge, None])
+ rows.append(['reroutes', queue.reroutes, None])
+ disp.formattedTable("Statistics:", heads, rows)
+
+
+ def displaySubscriptions(self):
disp = Display(prefix=" ")
heads = []
heads.append(Header("subscr"))
@@ -359,7 +414,7 @@ class BrokerManager:
heads.append(Header("creditMode"))
heads.append(Header("delivered", Header.KMG))
rows = []
- subscriptions = self.brokers[0].getAllSubscriptions()
+ subscriptions = self.broker.getAllSubscriptions()
sessions = self.getSessionMap()
connections = self.getConnectionMap()
for s in subscriptions:
@@ -392,55 +447,71 @@ class BrokerManager:
disp = Display(prefix=" ")
heads = [Header('Statistic'), Header('Value', Header.COMMAS)]
rows = []
- memory = self.brokers[0].getMemory()
+ memory = self.broker.getMemory()
for k,v in memory.values.items():
if k != 'name':
rows.append([k, v])
disp.formattedTable('Broker Memory Statistics:', heads, rows)
+ def displayAcl(self):
+ acl = self.broker.getAcl()
+ if not acl:
+ print "ACL Policy Module is not installed"
+ return
+ disp = Display(prefix=" ")
+ heads = [Header('Statistic'), Header('Value')]
+ rows = []
+ rows.append(['policy-file', acl.policyFile])
+ rows.append(['enforcing', YN(acl.enforcingAcl)])
+ rows.append(['has-transfer-acls', YN(acl.transferAcl)])
+ rows.append(['last-acl-load', TimeLong(acl.lastAclLoad)])
+ rows.append(['acl-denials', Commas(acl.aclDenyCount)])
+ disp.formattedTable('ACL Policy Statistics:', heads, rows)
+
def getExchangeMap(self):
- exchanges = self.brokers[0].getAllExchanges()
+ exchanges = self.broker.getAllExchanges()
emap = {}
for e in exchanges:
emap[e.name] = e
return emap
def getQueueMap(self):
- queues = self.brokers[0].getAllQueues()
+ queues = self.broker.getAllQueues()
qmap = {}
for q in queues:
qmap[q.name] = q
return qmap
def getSessionMap(self):
- sessions = self.brokers[0].getAllSessions()
+ sessions = self.broker.getAllSessions()
smap = {}
for s in sessions:
smap[s.name] = s
return smap
def getConnectionMap(self):
- connections = self.brokers[0].getAllConnections()
+ connections = self.broker.getAllConnections()
cmap = {}
for c in connections:
cmap[c.address] = c
return cmap
- def displayMain(self, main, subs):
- if main == 'b': self.displayBroker(subs)
- elif main == 'c': self.displayConn(subs)
- elif main == 's': self.displaySession(subs)
- elif main == 'e': self.displayExchange(subs)
+ def displayMain(self, names, main):
+ if main == 'g': self.displayBroker()
+ elif main == 'c': self.displayConn()
+ elif main == 's': self.displaySession()
+ elif main == 'e': self.displayExchange()
elif main == 'q':
- if config._detail:
- self.displayQueue(subs, config._detail)
+ if len(names) >= 1:
+ self.displayQueue(names[0])
else:
- self.displayQueues(subs)
- elif main == 'u': self.displaySubscriptions(subs)
- elif main == 'm': self.displayMemory(subs)
+ self.displayQueues()
+ elif main == 'u': self.displaySubscriptions()
+ elif main == 'm': self.displayMemory()
+ elif main == 'acl': self.displayAcl()
- def display(self):
- self.displayMain(config._types[0], config._types[1:])
+ def display(self, names):
+ self.displayMain(names, config._types)
def main(argv=None):
@@ -450,7 +521,7 @@ def main(argv=None):
try:
bm.SetBroker(config._host, config._sasl_mechanism)
- bm.display()
+ bm.display(args)
bm.Disconnect()
return 0
except KeyboardInterrupt:
diff --git a/tools/src/py/qpidtoollibs/broker.py b/tools/src/py/qpidtoollibs/broker.py
index 6a380caf8d..0714dd5d61 100644
--- a/tools/src/py/qpidtoollibs/broker.py
+++ b/tools/src/py/qpidtoollibs/broker.py
@@ -24,6 +24,9 @@ except ImportError:
from qpid.datatypes import uuid4
class BrokerAgent(object):
+ """
+ Proxy for a manageable Qpid Broker - Invoke with an opened qpid.messaging.Connection.
+ """
def __init__(self, conn):
self.conn = conn
self.sess = self.conn.session()
@@ -35,6 +38,9 @@ class BrokerAgent(object):
self.next_correlator = 1
def close(self):
+ """
+ Close the proxy session. This will not affect the connection used in creating the object.
+ """
self.sess.close()
def _method(self, method, arguments, addr="org.apache.qpid.broker:broker:amqp-broker", timeout=10):
@@ -124,9 +130,15 @@ class BrokerAgent(object):
return None
def getCluster(self):
+ """
+ Get the broker's Cluster object.
+ """
return self._getAllBrokerObjects(Cluster)
def getBroker(self):
+ """
+ Get the Broker object that contains broker-scope statistics and operations.
+ """
#
# getAllBrokerObjects is used instead of getBrokerObject(Broker, 'amqp-broker') because
# of a bug that used to be in the broker whereby by-name queries did not return the
@@ -173,8 +185,14 @@ class BrokerAgent(object):
def getAllBindings(self):
return self._getAllBrokerObjects(Binding)
- def getBinding(self, exchange=None, queue=None):
- pass
+ def getAllLinks(self):
+ return self._getAllBrokerObjects(Link)
+
+ def getAcl(self):
+ objects = self._getAllBrokerObjects(Acl)
+ if len(objects) > 0:
+ return objects[0]
+ return None # Acl module not loaded
def echo(self, sequence, body):
"""Request a response to test the path to the management broker"""
@@ -204,23 +222,55 @@ class BrokerAgent(object):
"""Get the message timestamping configuration"""
pass
-# def addExchange(self, exchange_type, name, **kwargs):
-# pass
-
-# def delExchange(self, name):
-# pass
-
-# def addQueue(self, name, **kwargs):
-# pass
-
-# def delQueue(self, name):
-# pass
-
-# def bind(self, exchange, queue, key, **kwargs):
-# pass
-
-# def unbind(self, exchange, queue, key, **kwargs):
-# pass
+ def addExchange(self, exchange_type, name, options={}, **kwargs):
+ properties = {}
+ properties['exchange-type'] = exchange_type
+ for k,v in options.items():
+ properties[k] = v
+ for k,v in kwargs.items():
+ properties[k] = v
+ args = {'type': 'exchange',
+ 'name': name,
+ 'properties': properties,
+ 'strict': True}
+ self._method('create', args)
+
+ def delExchange(self, name):
+ args = {'type': 'exchange', 'name': name}
+ self._method('delete', args)
+
+ def addQueue(self, name, options={}, **kwargs):
+ properties = options
+ for k,v in kwargs.items():
+ properties[k] = v
+ args = {'type': 'queue',
+ 'name': name,
+ 'properties': properties,
+ 'strict': True}
+ self._method('create', args)
+
+ def delQueue(self, name):
+ args = {'type': 'queue', 'name': name}
+ self._method('delete', args)
+
+ def bind(self, exchange, queue, key, options={}, **kwargs):
+ properties = options
+ for k,v in kwargs.items():
+ properties[k] = v
+ args = {'type': 'binding',
+ 'name': "%s/%s/%s" % (exchange, queue, key),
+ 'properties': properties,
+ 'strict': True}
+ self._method('create', args)
+
+ def unbind(self, exchange, queue, key, **kwargs):
+ args = {'type': 'binding',
+ 'name': "%s/%s/%s" % (exchange, queue, key),
+ 'strict': True}
+ self._method('delete', args)
+
+ def reloadAclFile(self):
+ self._method('reloadACLFile', {}, "org.apache.qpid.acl:acl:org.apache.qpid.broker:broker:amqp-broker")
def create(self, _type, name, properties, strict):
"""Create an object of the specified type"""
@@ -328,3 +378,10 @@ class Queue(BrokerObject):
self.broker._method("reroute", {'request':request,'useAltExchange':useAltExchange,'exchange':exchange,'filter':filter},
"org.apache.qpid.broker:queue:%s" % self.name)
+class Link(BrokerObject):
+ def __init__(self, broker, values):
+ BrokerObject.__init__(self, broker, values)
+
+class Acl(BrokerObject):
+ def __init__(self, broker, values):
+ BrokerObject.__init__(self, broker, values)
diff --git a/tools/src/py/qpidtoollibs/disp.py b/tools/src/py/qpidtoollibs/disp.py
index cb7d3da306..a0c77370a5 100644
--- a/tools/src/py/qpidtoollibs/disp.py
+++ b/tools/src/py/qpidtoollibs/disp.py
@@ -21,6 +21,31 @@
from time import strftime, gmtime
+def YN(val):
+ if val:
+ return 'Y'
+ return 'N'
+
+def Commas(value):
+ sval = str(value)
+ result = ""
+ while True:
+ if len(sval) == 0:
+ return result
+ left = sval[:-3]
+ right = sval[-3:]
+ result = right + result
+ if len(left) > 0:
+ result = ',' + result
+ sval = left
+
+def TimeLong(value):
+ return strftime("%c", gmtime(value / 1000000000))
+
+def TimeShort(value):
+ return strftime("%X", gmtime(value / 1000000000))
+
+
class Header:
""" """
NONE = 1
@@ -59,9 +84,9 @@ class Header:
return 'Y'
return ''
if self.format == Header.TIME_LONG:
- return strftime("%c", gmtime(value / 1000000000))
+ return TimeLong(value)
if self.format == Header.TIME_SHORT:
- return strftime("%X", gmtime(value / 1000000000))
+ return TimeShort(value)
if self.format == Header.DURATION:
if value < 0: value = 0
sec = value / 1000000000
@@ -78,17 +103,7 @@ class Header:
result += "%ds" % (sec % 60)
return result
if self.format == Header.COMMAS:
- sval = str(value)
- result = ""
- while True:
- if len(sval) == 0:
- return result
- left = sval[:-3]
- right = sval[-3:]
- result = right + result
- if len(left) > 0:
- result = ',' + result
- sval = left
+ return Commas(value)
except:
return "?"