summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Rudyy <orudyy@apache.org>2014-02-12 13:27:51 +0000
committerAlex Rudyy <orudyy@apache.org>2014-02-12 13:27:51 +0000
commit25ebb1e1221f4ab473089c7240496d3c82558188 (patch)
treeba586a37d8affb5e1aabfe33ed6ce329bc085ace
parentbc7dbb7e518ae34485356f66132c804671c00d84 (diff)
parent759eb840f3b5ffcc56155369b02ed360ce19c409 (diff)
downloadqpid-python-25ebb1e1221f4ab473089c7240496d3c82558188.tar.gz
NO-JIRA: Merge changes from the trunk in revisions 1564250:1567584 using
svn merge -r 1564250:1567584 https://svn.apache.org/repos/asf/qpid/trunk git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-broker-bdb-ha@1567616 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/cpp/bindings/qmf2/ruby/ruby.i2
-rwxr-xr-xqpid/cpp/bindings/qpid/examples/perl/drain.pl4
-rwxr-xr-xqpid/cpp/bindings/qpid/examples/perl/spout.pl2
-rw-r--r--qpid/cpp/bindings/qpid/perl/lib/qpid/messaging/Message.pm33
-rw-r--r--qpid/cpp/bindings/qpid/perl/perl.i2
-rw-r--r--qpid/cpp/bindings/qpid/ruby/ruby.i42
-rw-r--r--qpid/cpp/include/qpid/swig_perl_typemaps.i2
-rw-r--r--qpid/cpp/include/qpid/swig_ruby_typemaps.i2
-rw-r--r--qpid/cpp/src/CMakeLists.txt2
-rw-r--r--qpid/cpp/src/qpid/broker/Broker.cpp6
-rw-r--r--qpid/cpp/src/qpid/broker/Broker.h2
-rw-r--r--qpid/cpp/src/qpid/broker/DtxManager.cpp15
-rw-r--r--qpid/cpp/src/qpid/broker/DtxManager.h3
-rw-r--r--qpid/cpp/src/qpid/broker/SessionAdapter.cpp2
-rw-r--r--qpid/cpp/src/qpid/client/windows/SslConnector.cpp264
-rw-r--r--qpid/cpp/src/qpid/ha/Backup.cpp8
-rw-r--r--qpid/cpp/src/qpid/ha/BrokerReplicator.cpp56
-rw-r--r--qpid/cpp/src/qpid/ha/BrokerReplicator.h4
-rw-r--r--qpid/cpp/src/qpid/ha/ErrorListener.h60
-rw-r--r--qpid/cpp/src/qpid/ha/QueueReplicator.cpp24
-rw-r--r--qpid/cpp/src/qpid/ha/QueueReplicator.h2
-rw-r--r--qpid/cpp/src/qpid/linearstore/ISSUES37
-rw-r--r--qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp13
-rw-r--r--qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h2
-rw-r--r--qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp4
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/JournalFile.cpp68
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/JournalFile.h13
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/LinearFileController.cpp82
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/LinearFileController.h13
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp195
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.h24
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp8
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/deq_rec.h4
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp8
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/enq_rec.h4
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp20
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/jcntl.h2
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp4
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/jrec.h2
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp8
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/txn_rec.h4
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp100
-rw-r--r--qpid/cpp/src/qpid/linearstore/journal/wmgr.h12
-rw-r--r--qpid/cpp/src/qpid/log/Logger.cpp2
-rw-r--r--qpid/cpp/src/qpid/log/Statement.cpp53
-rw-r--r--qpid/cpp/src/qpid/log/Statement.h1
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp5
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h1
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp10
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/TransportContext.h3
-rw-r--r--qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp16
-rw-r--r--qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h2
-rw-r--r--qpid/cpp/src/qpid/sys/windows/SslCredential.cpp273
-rw-r--r--qpid/cpp/src/qpid/sys/windows/SslCredential.h81
-rw-r--r--qpid/cpp/src/tests/brokertest.py2
-rwxr-xr-xqpid/cpp/src/tests/ha_test.py2
-rwxr-xr-xqpid/cpp/src/tests/linearstore/tx-test-soak.sh254
-rw-r--r--qpid/doc/book/src/programming/Programming-In-Apache-Qpid.xml489
-rw-r--r--qpid/java/amqp-1-0-client-jms/pom.xml17
-rw-r--r--qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java31
-rw-r--r--qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java4
-rw-r--r--qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java17
-rw-r--r--qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java6
-rw-r--r--qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java20
-rw-r--r--qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java8
-rw-r--r--qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java4
-rw-r--r--qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java20
-rw-r--r--qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java5
-rw-r--r--qpid/java/amqp-1-0-client-websocket/pom.xml138
-rw-r--r--qpid/java/amqp-1-0-client/pom.xml13
-rw-r--r--qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java92
-rw-r--r--qpid/java/amqp-1-0-common/pom.xml10
-rw-r--r--qpid/java/bdbstore/jmx/pom.xml25
-rw-r--r--qpid/java/bdbstore/pom.xml27
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java2
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/PreparedTransactionBinding.java16
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java2
-rw-r--r--qpid/java/bdbstore/systests/pom.xml27
-rw-r--r--qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java36
-rw-r--r--qpid/java/broker-core/pom.xml50
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java73
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/Consumer.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/Subscription.java)76
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java67
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java42
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java9
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/Exchange.java21
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/filter/FilterSupport.java7
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java1
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/GenericActor.java23
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubject.java55
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java45
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java175
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageNode.java26
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java105
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java259
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageHeader.java197
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java95
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaDataType.java76
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AmqpManagement.java35
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java11
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java28
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java18
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupProvider.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Plugin.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java40
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ReplicationNode.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java4
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/TrustStore.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/User.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java46
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java31
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java87
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java29
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java29
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemNodeCreator.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/MessageGroupManager.java)23
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java3
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/CapacityChecker.java26
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java122
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java4
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AssignedConsumerMessageGroupManager.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java)51
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java14
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java4
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java65
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java)89
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java39
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntry.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryImpl.java)24
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java198
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java20
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueue.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java)20
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java231
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java474
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerList.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java)88
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueContext.java20
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java196
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java170
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java6
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java16
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java4
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java6
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueRunner.java4
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java655
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java220
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java27
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntry.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryImpl.java)44
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java112
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryListFactory.java5
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueue.java41
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntry.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/SubscriptionActor.java)31
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntryList.java57
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java7
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java20
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java5
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/Transaction.java2
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java2
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java12
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java12
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java13
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DtxBranch.java23
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java12
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java9
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/Action.java26
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/StateChangeListener.java26
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java90
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java6
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java24
-rw-r--r--qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType19
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java12
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java (renamed from qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java)193
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java19
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java86
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/ConsumerMessagesTest.java (renamed from qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java)2
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/VirtualHostMessagesTest.java2
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java105
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java4
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java12
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConsumerListTest.java445
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java107
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockMessageInstance.java (renamed from qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java)102
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java17
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueTest.java (renamed from qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java)33
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java63
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java50
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SelfValidatingSortedQueueEntryList.java22
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTestBase.java (renamed from qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java)795
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java21
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java71
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryTest.java (renamed from qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryImplTest.java)26
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueEntryListTest.java (renamed from qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java)50
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java363
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java6
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java6
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMessageMetaData.java3
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/SubscriptionListTest.java429
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java15
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java15
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java6
-rw-r--r--qpid/java/broker-plugins/access-control/pom.xml18
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/pom.xml20
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java587
-rwxr-xr-xqpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java31
-rwxr-xr-xqpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java26
-rwxr-xr-xqpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java12
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java156
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java84
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10_to_Internal.java271
-rwxr-xr-xqpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java4
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java4
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java139
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java104
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java944
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter2
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/pom.xml18
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java471
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java7
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolSession.java1
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ClientDeliveryMethod.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/ClientDeliveryMethod.java)5
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java571
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java76
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/IncomingMessage.java15
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java268
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_v0_8_to_Internal.java148
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java2
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/RecordDeliveryMethod.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/RecordDeliveryMethod.java)7
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java68
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.java109
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java858
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java13
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java37
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java15
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java95
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java3
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java2
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java2
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java69
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java9
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java2
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter20
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java94
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java8
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java171
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java30
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java11
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImplTest.java96
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/pom.xml17
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java25
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java (renamed from qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java)288
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java140
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java154
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java281
-rwxr-xr-xqpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java4
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageSourceDestination.java59
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/NodeReceivingDestination.java106
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java14
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java131
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java25
-rw-r--r--qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter20
-rw-r--r--qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/pom.xml24
-rw-r--r--qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/pom.xml21
-rw-r--r--qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java2
-rw-r--r--qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/pom.xml24
-rw-r--r--qpid/java/broker-plugins/derby-store/pom.xml21
-rw-r--r--qpid/java/broker-plugins/jdbc-provider-bone/pom.xml15
-rw-r--r--qpid/java/broker-plugins/jdbc-store/pom.xml19
-rw-r--r--qpid/java/broker-plugins/management-amqp/build.xml32
-rw-r--r--qpid/java/broker-plugins/management-amqp/pom.xml48
-rw-r--r--qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagedEntityType.java73
-rw-r--r--qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java1402
-rw-r--r--qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java242
-rw-r--r--qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeCreator.java39
-rw-r--r--qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java220
-rw-r--r--qpid/java/broker-plugins/management-amqp/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.SystemNodeCreator19
-rw-r--r--qpid/java/broker-plugins/management-http/pom.xml118
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java3
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java7
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html8
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js8
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js4
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html2
-rw-r--r--qpid/java/broker-plugins/management-jmx/pom.xml19
-rw-r--r--qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java2
-rw-r--r--qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java2
-rw-r--r--qpid/java/broker-plugins/memory-store/pom.xml12
-rw-r--r--qpid/java/broker-plugins/websocket/pom.xml119
-rw-r--r--qpid/java/broker/pom.xml52
-rw-r--r--qpid/java/build.deps1
-rw-r--r--qpid/java/client/pom.xml18
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java2
-rw-r--r--qpid/java/common/pom.xml20
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java4
-rw-r--r--qpid/java/ivy.nexus.xml6
-rw-r--r--qpid/java/jca/pom.xml22
-rw-r--r--qpid/java/jca/rar/pom.xml40
-rw-r--r--qpid/java/management/common/pom.xml10
-rw-r--r--qpid/java/management/example/pom.xml13
-rw-r--r--qpid/java/perftests/pom.xml31
-rw-r--r--qpid/java/perftests/visualisation-jfc/pom.xml35
-rw-r--r--qpid/java/pom.xml490
-rw-r--r--qpid/java/qpid-test-utils/pom.xml18
-rw-r--r--qpid/java/systests/pom.xml91
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ConsumerLoggingTest.java (renamed from qpid/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java)11
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java11
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java6
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java7
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java4
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java41
-rwxr-xr-xqpid/java/test-profiles/Java010Excludes2
-rw-r--r--qpid/java/test-profiles/python_tests/Java010PythonExcludes3
-rw-r--r--qpid/java/tools/pom.xml19
-rw-r--r--qpid/tests/src/py/qpid_tests/broker_0_10/dtx.py20
-rw-r--r--qpid/tools/src/py/qls/efp.py3
-rw-r--r--qpid/tools/src/py/qls/err.py10
-rw-r--r--qpid/tools/src/py/qls/jrnl.py194
-rwxr-xr-xqpid/tools/src/py/qpid-ha3
-rwxr-xr-xqpid/tools/src/py/qpid_qls_analyze.py8
328 files changed, 13496 insertions, 8345 deletions
diff --git a/qpid/cpp/bindings/qmf2/ruby/ruby.i b/qpid/cpp/bindings/qmf2/ruby/ruby.i
index 0254017555..65d0770224 100644
--- a/qpid/cpp/bindings/qmf2/ruby/ruby.i
+++ b/qpid/cpp/bindings/qmf2/ruby/ruby.i
@@ -30,7 +30,7 @@
}
catch (qpid::types::Exception& mex) {
static VALUE qmferror = rb_define_class("QmfError", rb_eStandardError);
- rb_raise(qmferror, mex.what());
+ rb_raise(qmferror, "%s", mex.what());
}
}
diff --git a/qpid/cpp/bindings/qpid/examples/perl/drain.pl b/qpid/cpp/bindings/qpid/examples/perl/drain.pl
index f7a710c485..d0150854b2 100755
--- a/qpid/cpp/bindings/qpid/examples/perl/drain.pl
+++ b/qpid/cpp/bindings/qpid/examples/perl/drain.pl
@@ -92,13 +92,13 @@ eval {
# if the message content was a map, then we will print
# it out as a series of name => value pairs
+ my $content = $message->get_content_object;
if ( $message->get_content_type() eq "amqp/map" ) {
- my $content = $message->get_content();
map { print "\n$_ => $content->{$_}"; } keys %{$content};
}
else {
# it's not a map, so just print the content as a string
- print $message->get_content();
+ print $content;
}
print "')\n";
diff --git a/qpid/cpp/bindings/qpid/examples/perl/spout.pl b/qpid/cpp/bindings/qpid/examples/perl/spout.pl
index 7468a25a3a..c97c2a58af 100755
--- a/qpid/cpp/bindings/qpid/examples/perl/spout.pl
+++ b/qpid/cpp/bindings/qpid/examples/perl/spout.pl
@@ -91,7 +91,7 @@ eval {
if (@entries) {
my $content = {};
setEntries($content);
- $message->set_content($content);
+ $message->set_content_object($content);
}
elsif ($content) {
$message->set_content($content);
diff --git a/qpid/cpp/bindings/qpid/perl/lib/qpid/messaging/Message.pm b/qpid/cpp/bindings/qpid/perl/lib/qpid/messaging/Message.pm
index 6437290244..6926eb221f 100644
--- a/qpid/cpp/bindings/qpid/perl/lib/qpid/messaging/Message.pm
+++ b/qpid/cpp/bindings/qpid/perl/lib/qpid/messaging/Message.pm
@@ -527,6 +527,39 @@ sub get_properties {
=pod
+=head2 CONTENT OBJECT
+
+The message content, represented as anh object.
+
+=over
+
+=item $msg->set_content_object( \%content )
+
+=item $content = $msg->get_Content_object
+
+=back
+
+=cut
+
+sub set_content_object {
+ my ($self) = @_;
+ my $impl = $self->{_impl};
+
+ my $content = $_[1];
+
+ $impl->setContentObject($content);
+}
+
+sub get_content_object {
+ my ($self) = @_;
+ my $impl = $self->{_impl};
+ my $content = $impl->getContentObject;
+
+ return $content;
+}
+
+=pod
+
=head2 CONTENT
The message content.
diff --git a/qpid/cpp/bindings/qpid/perl/perl.i b/qpid/cpp/bindings/qpid/perl/perl.i
index 0d118ae0fb..4dc2665c2b 100644
--- a/qpid/cpp/bindings/qpid/perl/perl.i
+++ b/qpid/cpp/bindings/qpid/perl/perl.i
@@ -27,7 +27,7 @@
$action
}
catch (qpid::messaging::MessagingException& mex) {
- Perl_croak(aTHX_ mex.what());
+ Perl_croak(aTHX_ "%s", mex.what());
}
}
diff --git a/qpid/cpp/bindings/qpid/ruby/ruby.i b/qpid/cpp/bindings/qpid/ruby/ruby.i
index 34388a2b16..a2f2ffab4c 100644
--- a/qpid/cpp/bindings/qpid/ruby/ruby.i
+++ b/qpid/cpp/bindings/qpid/ruby/ruby.i
@@ -34,86 +34,86 @@
}
catch(qpid::messaging::ConnectionError& error) {
static VALUE merror = rb_define_class("ConnectionError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::TransportFailure& error) {
static VALUE merror = rb_define_class("TransportFailure", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::TransactionAborted& error) {
static VALUE merror = rb_define_class("TransactionAborted", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::TransactionError& error) {
static VALUE merror = rb_define_class("TransactionError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::UnauthorizedAccess& error) {
static VALUE merror = rb_define_class("UnauthorizedAccess", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::SessionError& error) {
static VALUE merror = rb_define_class("SessionError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::TargetCapacityExceeded& error) {
static VALUE merror = rb_define_class("TargetCapacityExceeded", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::SendError& error) {
static VALUE merror = rb_define_class("SendError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::SenderError& error) {
static VALUE merror = rb_define_class("SenderError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::NoMessageAvailable& error) {
static VALUE merror = rb_define_class("NoMessageAvailable", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::FetchError& error) {
static VALUE merror = rb_define_class("FetchError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::ReceiverError& error) {
static VALUE merror = rb_define_class("ReceiverError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::InvalidOptionString& error) {
static VALUE merror = rb_define_class("InvalidOptionString", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::KeyError& error) {
static VALUE merror = rb_define_class("KeyError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::AssertionFailed& error) {
static VALUE merror = rb_define_class("AssertionFailed", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::NotFound& error) {
static VALUE merror = rb_define_class("NotFound", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::ResolutionError& error) {
static VALUE merror = rb_define_class("ResolutionError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::MalformedAddress& error) {
static VALUE merror = rb_define_class("MalformedAddress", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::AddressError& error) {
static VALUE merror = rb_define_class("AddressError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::LinkError& error) {
static VALUE merror = rb_define_class("LinkError", eMessagingError);
- rb_raise(merror, error.what());
+ rb_raise(merror, "%s", error.what());
}
catch(qpid::messaging::MessagingException& error) {
- rb_raise(eMessagingError, error.what());
+ rb_raise(eMessagingError, "%s", error.what());
}
}
diff --git a/qpid/cpp/include/qpid/swig_perl_typemaps.i b/qpid/cpp/include/qpid/swig_perl_typemaps.i
index f1425ebd67..6c0e6d8bac 100644
--- a/qpid/cpp/include/qpid/swig_perl_typemaps.i
+++ b/qpid/cpp/include/qpid/swig_perl_typemaps.i
@@ -120,7 +120,7 @@
}
}
} catch (qpid::types::Exception& ex) {
- Perl_croak(aTHX_ ex.what());
+ Perl_croak(aTHX_ "%s", ex.what());
}
if (!result)
diff --git a/qpid/cpp/include/qpid/swig_ruby_typemaps.i b/qpid/cpp/include/qpid/swig_ruby_typemaps.i
index 1a07cc86b0..4e07088bce 100644
--- a/qpid/cpp/include/qpid/swig_ruby_typemaps.i
+++ b/qpid/cpp/include/qpid/swig_ruby_typemaps.i
@@ -106,7 +106,7 @@
}
} catch (qpid::types::Exception& ex) {
static VALUE error = rb_define_class("Error", rb_eStandardError);
- rb_raise(error, ex.what());
+ rb_raise(error, "%s", ex.what());
}
return result;
diff --git a/qpid/cpp/src/CMakeLists.txt b/qpid/cpp/src/CMakeLists.txt
index 46b526579f..d8b823fc8e 100644
--- a/qpid/cpp/src/CMakeLists.txt
+++ b/qpid/cpp/src/CMakeLists.txt
@@ -460,6 +460,8 @@ if (BUILD_SSL)
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
set (sslcommon_SOURCES
qpid/sys/windows/SslAsynchIO.cpp
+ qpid/sys/windows/SslCredential.cpp
+ qpid/sys/windows/SslCredential.h
qpid/sys/windows/util.cpp
qpid/sys/windows/util.h
)
diff --git a/qpid/cpp/src/qpid/broker/Broker.cpp b/qpid/cpp/src/qpid/broker/Broker.cpp
index 4017fdbfe3..7f076e92cd 100644
--- a/qpid/cpp/src/qpid/broker/Broker.cpp
+++ b/qpid/cpp/src/qpid/broker/Broker.cpp
@@ -148,6 +148,8 @@ Broker::Options::Options(const std::string& name) :
timestampRcvMsgs(false), // set the 0.10 timestamp delivery property
linkMaintenanceInterval(2*sys::TIME_SEC),
linkHeartbeatInterval(120*sys::TIME_SEC),
+ dtxDefaultTimeout(60), // 60s
+ dtxMaxTimeout(3600), // 3600s
maxNegotiateTime(10000) // 10s
{
int c = sys::SystemInfo::concurrency();
@@ -192,6 +194,8 @@ Broker::Options::Options(const std::string& name) :
"Interval to check link health and re-connect if need be")
("link-heartbeat-interval", optValue(linkHeartbeatInterval, "SECONDS"),
"Heartbeat interval for a federation link")
+ ("dtx-default-timeout", optValue(dtxDefaultTimeout, "SECONDS"), "Default timeout for DTX transaction before aborting it")
+ ("dtx-max-timeout", optValue(dtxMaxTimeout, "SECONDS"), "Maximum allowed timeout for DTX transaction. A value of zero disables maximum timeout limit checks and allows arbitrarily large timeout settings.")
("max-negotiate-time", optValue(maxNegotiateTime, "MILLISECONDS"), "Maximum time a connection can take to send the initial protocol negotiation")
("federation-tag", optValue(fedTag, "NAME"), "Override the federation tag")
;
@@ -224,7 +228,7 @@ Broker::Broker(const Broker::Options& conf) :
exchanges(this),
links(this),
factory(new SecureConnectionFactory(*this)),
- dtxManager(*timer.get()),
+ dtxManager(*timer.get(), getOptions().dtxDefaultTimeout),
sessionManager(
qpid::SessionState::Configuration(
conf.replayFlushLimit*1024, // convert kb to bytes.
diff --git a/qpid/cpp/src/qpid/broker/Broker.h b/qpid/cpp/src/qpid/broker/Broker.h
index 4bad8f2960..5d1e241be9 100644
--- a/qpid/cpp/src/qpid/broker/Broker.h
+++ b/qpid/cpp/src/qpid/broker/Broker.h
@@ -121,6 +121,8 @@ class Broker : public sys::Runnable, public Plugin::Target,
bool timestampRcvMsgs;
sys::Duration linkMaintenanceInterval;
sys::Duration linkHeartbeatInterval;
+ uint32_t dtxDefaultTimeout; // Default timeout of a DTX transaction
+ uint32_t dtxMaxTimeout; // Maximal timeout of a DTX transaction
uint32_t maxNegotiateTime; // Max time in ms for connection with no negotiation
std::string fedTag;
diff --git a/qpid/cpp/src/qpid/broker/DtxManager.cpp b/qpid/cpp/src/qpid/broker/DtxManager.cpp
index 5ba1ce4dac..4fb82bb41b 100644
--- a/qpid/cpp/src/qpid/broker/DtxManager.cpp
+++ b/qpid/cpp/src/qpid/broker/DtxManager.cpp
@@ -62,7 +62,12 @@ namespace {
}
-DtxManager::DtxManager(qpid::sys::Timer& t) : store(0), timer(&t) {}
+DtxManager::DtxManager(qpid::sys::Timer& t, uint32_t _dtxDefaultTimeout) :
+ store(0),
+ timer(&t),
+ dtxDefaultTimeout(_dtxDefaultTimeout)
+{
+}
DtxManager::~DtxManager() {}
@@ -150,8 +155,12 @@ DtxWorkRecord* DtxManager::createWork(const std::string& xid)
if (i != work.end()) {
throw NotAllowedException(QPID_MSG("Xid " << convert(xid) << " is already known (use 'join' to add work to an existing xid)"));
} else {
- std::string ncxid = xid; // Work around const correctness problems in ptr_map.
- return ptr_map_ptr(work.insert(ncxid, new DtxWorkRecord(ncxid, store)).first);
+ std::string ncxid = xid; // Work around const correctness problems with work.insert
+ DtxWorkRecord* dtxWorkRecord = new DtxWorkRecord(xid, store);
+ work.insert(ncxid, dtxWorkRecord);
+ if (dtxDefaultTimeout>0)
+ setTimeout(xid, dtxDefaultTimeout);
+ return dtxWorkRecord;
}
}
diff --git a/qpid/cpp/src/qpid/broker/DtxManager.h b/qpid/cpp/src/qpid/broker/DtxManager.h
index 000fc7b4b8..ad30ed61a0 100644
--- a/qpid/cpp/src/qpid/broker/DtxManager.h
+++ b/qpid/cpp/src/qpid/broker/DtxManager.h
@@ -44,12 +44,13 @@ class DtxManager{
TransactionalStore* store;
qpid::sys::Mutex lock;
qpid::sys::Timer* timer;
+ uint32_t dtxDefaultTimeout;
void remove(const std::string& xid);
DtxWorkRecord* createWork(const std::string& xid);
public:
- DtxManager(sys::Timer&);
+ DtxManager(sys::Timer&, uint32_t _dtxDefaultTimeout=0);
~DtxManager();
void start(const std::string& xid, boost::intrusive_ptr<DtxBuffer> work);
void join(const std::string& xid, boost::intrusive_ptr<DtxBuffer> work);
diff --git a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp b/qpid/cpp/src/qpid/broker/SessionAdapter.cpp
index 5b1a6aa267..7c2d1cf9f5 100644
--- a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp
+++ b/qpid/cpp/src/qpid/broker/SessionAdapter.cpp
@@ -678,6 +678,8 @@ DtxGetTimeoutResult SessionAdapter::DtxHandlerImpl::getTimeout(const Xid& xid)
void SessionAdapter::DtxHandlerImpl::setTimeout(const Xid& xid,
uint32_t timeout)
{
+ if ((timeout > getBroker().getOptions().dtxMaxTimeout) && (getBroker().getOptions().dtxMaxTimeout > 0))
+ throw InvalidArgumentException(QPID_MSG("xid " << xid << " has timeout " << timeout << " bigger than maximum allowed " << getBroker().getOptions().dtxMaxTimeout));
getBroker().getDtxManager().setTimeout(DtxManager::convert(xid), timeout);
}
diff --git a/qpid/cpp/src/qpid/client/windows/SslConnector.cpp b/qpid/cpp/src/qpid/client/windows/SslConnector.cpp
index 4f4ef4f559..d0be818df0 100644
--- a/qpid/cpp/src/qpid/client/windows/SslConnector.cpp
+++ b/qpid/cpp/src/qpid/client/windows/SslConnector.cpp
@@ -32,26 +32,14 @@
#include "qpid/sys/windows/check.h"
#include "qpid/sys/windows/util.h"
#include "qpid/sys/windows/SslAsynchIO.h"
+#include "qpid/sys/windows/SslCredential.h"
#include <boost/bind.hpp>
#include <memory.h>
-// security.h needs to see this to distinguish from kernel use.
-#define SECURITY_WIN32
-#include <security.h>
-#include <Schnlsp.h>
-#undef SECURITY_WIN32
#include <winsock2.h>
-/*
- * Note on client certificates: The Posix/NSS implementation performs a lazy
- * client certificate search part way through the ssl handshake if the server
- * requests one. Here, it is not known in advance if the server will
- * request the certificate so the certificate is pre-loaded (even if never
- * used). To match the Linux behavior, client certificate load problems are
- * remembered and reported later if appropriate, but do not prevent the
- * connection attempt.
- */
+
namespace qpid {
namespace client {
@@ -61,34 +49,16 @@ using qpid::sys::Socket;
class SslConnector : public qpid::client::TCPConnector
{
- struct SavedError {
- std::string logMessage;
- std::string error;
- void set(const std::string &lm, const std::string es);
- void set(const std::string &lm, int status);
- void clear();
- bool pending();
- };
-
qpid::sys::windows::ClientSslAsynchIO *shim;
boost::shared_ptr<qpid::sys::Poller> poller;
std::string brokerHost;
- HCERTSTORE certStore;
- PCCERT_CONTEXT cert;
- SCHANNEL_CRED cred;
- CredHandle credHandle;
- TimeStamp credExpiry;
- SavedError clientCertError;
+ qpid::sys::windows::SslCredential sslCredential;
+ bool certLoaded;
- virtual ~SslConnector();
void negotiationDone(SECURITY_STATUS status);
void connect(const std::string& host, const std::string& port);
void connected(const Socket&);
- PCCERT_CONTEXT findCertificate(const std::string& name);
- void loadPrivCertStore();
- std::string getPasswd(const std::string& filename);
- void importHostCert(const ConnectionSettings&);
public:
SslConnector(boost::shared_ptr<qpid::sys::Poller>,
@@ -127,15 +97,12 @@ namespace {
void SslConnector::negotiationDone(SECURITY_STATUS status)
{
if (status == SEC_E_OK) {
- clientCertError.clear();
initAmqp();
}
else {
- if (status == SEC_E_INCOMPLETE_CREDENTIALS && clientCertError.pending()) {
+ if (status == SEC_E_INCOMPLETE_CREDENTIALS && !certLoaded) {
// Server requested a client cert but we supplied none for the following reason:
- if (!clientCertError.logMessage.empty())
- QPID_LOG(warning, clientCertError.logMessage);
- connectFailed(QPID_MSG(clientCertError.error));
+ connectFailed(QPID_MSG(sslCredential.error()));
}
else
connectFailed(QPID_MSG(qpid::sys::strError(status)));
@@ -146,46 +113,15 @@ SslConnector::SslConnector(boost::shared_ptr<qpid::sys::Poller> p,
framing::ProtocolVersion ver,
const ConnectionSettings& settings,
ConnectionImpl* cimpl)
- : TCPConnector(p, ver, settings, cimpl), shim(0), poller(p), certStore(0), cert(0)
+ : TCPConnector(p, ver, settings, cimpl), shim(0), poller(p)
{
- SecInvalidateHandle(&credHandle);
- memset(&cred, 0, sizeof(cred));
- cred.dwVersion = SCHANNEL_CRED_VERSION;
- cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS;
const std::string& name = (settings.sslCertName != "") ?
settings.sslCertName : qpid::sys::ssl::SslOptions::global.certName;
- cert = findCertificate(name);
- if (cert != NULL) {
- // assign the certificate into the credentials
- cred.paCred = &cert;
- cred.cCreds = 1;
- }
-
- SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL,
- UNISP_NAME,
- SECPKG_CRED_OUTBOUND,
- NULL,
- &cred,
- NULL,
- NULL,
- &credHandle,
- &credExpiry);
- if (status != SEC_E_OK)
- throw QPID_WINDOWS_ERROR(status);
+ certLoaded = sslCredential.load(name);
QPID_LOG(debug, "SslConnector created for " << ver.toString());
}
-SslConnector::~SslConnector()
-{
- if (SecIsValidHandle(&credHandle))
- ::FreeCredentialsHandle(&credHandle);
- if (cert)
- ::CertFreeCertificateContext(cert);
- if (certStore)
- ::CertCloseStore(certStore, CERT_CLOSE_STORE_FORCE_FLAG);
-}
-
void SslConnector::connect(const std::string& host, const std::string& port) {
brokerHost = host;
TCPConnector::connect(host, port);
@@ -194,7 +130,7 @@ void SslConnector::connect(const std::string& host, const std::string& port) {
void SslConnector::connected(const Socket& s) {
shim = new qpid::sys::windows::ClientSslAsynchIO(brokerHost,
s,
- credHandle,
+ sslCredential.handle(),
boost::bind(&SslConnector::readbuff, this, _1, _2),
boost::bind(&SslConnector::eof, this, _1),
boost::bind(&SslConnector::disconnected, this, _1),
@@ -206,186 +142,4 @@ void SslConnector::connected(const Socket& s) {
shim->start(poller);
}
-
-void SslConnector::loadPrivCertStore()
-{
- // Get a handle to the system store or pkcs#12 file
- qpid::sys::ssl::SslOptions& opts = qpid::sys::ssl::SslOptions::global;
- if (opts.certFilename.empty()) {
- // opening a system store, names are not case sensitive
- std::string store = opts.certStore.empty() ? "my" : opts.certStore;
- std::transform(store.begin(), store.end(), store.begin(), ::tolower);
- // map confusing GUI name to actual registry store name
- if (store == "personal")
- store = "my";
- certStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, NULL,
- CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG |
- CERT_SYSTEM_STORE_CURRENT_USER, store.c_str());
- if (!certStore) {
- HRESULT status = GetLastError();
- clientCertError.set(Msg() << "Could not open system certificate store: " << store, status);
- return;
- }
- QPID_LOG(debug, "SslConnector using certifcates from system store: " << store);
- } else {
- // opening the store from file and populating it with a private key
- HANDLE certFileHandle = NULL;
- certFileHandle = CreateFile(opts.certFilename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (INVALID_HANDLE_VALUE == certFileHandle) {
- HRESULT status = GetLastError();
- clientCertError.set(Msg() << "Failed to open the file holding the private key: " << opts.certFilename, status);
- return;
- }
- std::vector<BYTE> certEncoded;
- DWORD certEncodedSize = 0L;
- const DWORD fileSize = GetFileSize(certFileHandle, NULL);
- if (INVALID_FILE_SIZE != fileSize) {
- certEncoded.resize(fileSize);
- bool result = false;
- result = ReadFile(certFileHandle, &certEncoded[0],
- fileSize,
- &certEncodedSize,
- NULL);
- if (!result) {
- // the read failed, return the error as an HRESULT
- HRESULT status = GetLastError();
- CloseHandle(certFileHandle);
- clientCertError.set(Msg() << "Reading the private key from file failed " << opts.certFilename, status);
- return;
- }
- }
- else {
- HRESULT status = GetLastError();
- clientCertError.set(Msg() << "Unable to read the certificate file " << opts.certFilename, status);
- return;
- }
- CloseHandle(certFileHandle);
-
- CRYPT_DATA_BLOB blobData;
- blobData.cbData = certEncodedSize;
- blobData.pbData = &certEncoded[0];
-
- // get passwd from file and convert to null terminated wchar_t (Windows UCS2)
- std::string passwd = getPasswd(opts.certPasswordFile);
- if (clientCertError.pending())
- return;
- int pwlen = passwd.length();
- std::vector<wchar_t> pwUCS2(pwlen + 1, L'\0');
- int nwc = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, passwd.data(), pwlen, &pwUCS2[0], pwlen);
- if (!nwc) {
- HRESULT status = GetLastError();
- clientCertError.set("Error converting password from UTF8", status);
- return;
- }
-
- certStore = PFXImportCertStore(&blobData, &pwUCS2[0], 0);
- if (certStore == NULL) {
- HRESULT status = GetLastError();
- clientCertError.set("Failed to open the certificate store", status);
- return;
- }
- QPID_LOG(debug, "SslConnector using certificate from pkcs#12 file: " << opts.certFilename);
- }
-}
-
-
-PCCERT_CONTEXT SslConnector::findCertificate(const std::string& name)
-{
- loadPrivCertStore();
- if (clientCertError.pending())
- return NULL;
-
- // search for the certificate by Friendly Name
- PCCERT_CONTEXT tmpctx = NULL;
- while (tmpctx = CertEnumCertificatesInStore(certStore, tmpctx)) {
- DWORD len = CertGetNameString(tmpctx, CERT_NAME_FRIENDLY_DISPLAY_TYPE,
- 0, NULL, NULL, 0);
- if (len == 1)
- continue;
- std::vector<char> ctxname(len);
- CertGetNameString(tmpctx, CERT_NAME_FRIENDLY_DISPLAY_TYPE,
- 0, NULL, &ctxname[0], len);
- bool found = !name.compare(&ctxname[0]);
- if (found)
- break;
- }
-
- // verify whether some certificate has been found
- if (tmpctx == NULL) {
- clientCertError.set(Msg() << "Client SSL/TLS certificate not found in the certificate store for name " << name,
- "client certificate not found");
- }
- return tmpctx;
-}
-
-
-std::string SslConnector::getPasswd(const std::string& filename)
-{
- std::string passwd;
- if (filename == "")
- return passwd;
-
- HANDLE pwfHandle = CreateFile(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (INVALID_HANDLE_VALUE == pwfHandle) {
- HRESULT status = GetLastError();
- clientCertError.set(Msg() << "Failed to open the password file: " << filename, status);
- return passwd;
- }
-
- const DWORD fileSize = GetFileSize(pwfHandle, NULL);
- if (fileSize == INVALID_FILE_SIZE) {
- CloseHandle(pwfHandle);
- clientCertError.set("", "Cannot read password file");
- return passwd;
- }
-
- std::vector<char> pwbuf;
- pwbuf.resize(fileSize);
- DWORD nbytes = 0;
- if (!ReadFile(pwfHandle, &pwbuf[0], fileSize, &nbytes, NULL)) {
- HRESULT status = GetLastError();
- CloseHandle(pwfHandle);
- clientCertError.set("Error reading password file", status);
- return passwd;
- }
- CloseHandle(pwfHandle);
-
- if (nbytes == 0)
- return passwd;
-
- while (nbytes) {
- if ((pwbuf[nbytes-1] == 012) || (pwbuf[nbytes-1] == 015))
- nbytes--;
- else
- break;
- }
-
- if (nbytes)
- passwd.assign(&pwbuf[0], nbytes);
-
- return passwd;
-}
-
-void SslConnector::SavedError::set(const std::string &lm, const std::string es) {
- logMessage = lm;
- error = es;
-}
-
-void SslConnector::SavedError::set(const std::string &lm, int status) {
- logMessage = lm;
- error = qpid::sys::strError(status);
-}
-
-void SslConnector::SavedError::clear() {
- logMessage.clear();
- error.clear();
-}
-
-bool SslConnector::SavedError::pending() {
- return !logMessage.empty() || !error.empty();
-}
-
}}} // namespace qpid::client::windows
diff --git a/qpid/cpp/src/qpid/ha/Backup.cpp b/qpid/cpp/src/qpid/ha/Backup.cpp
index beae53d85f..9d50b1c665 100644
--- a/qpid/cpp/src/qpid/ha/Backup.cpp
+++ b/qpid/cpp/src/qpid/ha/Backup.cpp
@@ -63,18 +63,16 @@ void Backup::setBrokerUrl(const Url& brokers) {
QPID_LOG(info, logPrefix << "Connecting to cluster, broker URL: " << brokers);
string protocol = brokers[0].protocol.empty() ? "tcp" : brokers[0].protocol;
types::Uuid uuid(true);
- std::pair<Link::shared_ptr, bool> result;
- result = broker.getLinks().declare(
+ link = broker.getLinks().declare(
broker::QPID_NAME_PREFIX + string("ha.link.") + uuid.str(),
brokers[0].host, brokers[0].port, protocol,
false, // durable
settings.mechanism, settings.username, settings.password,
- false); // no amq.failover - don't want to use client URL.
- link = result.first;
+ false).first; // no amq.failover - don't want to use client URL.
replicator = BrokerReplicator::create(haBroker, link);
broker.getExchanges().registerExchange(replicator);
}
- link->setUrl(brokers); // Outside the lock, once set link doesn't change.
+ link->setUrl(brokers);
}
void Backup::stop(Mutex::ScopedLock&) {
diff --git a/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp b/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp
index 7928b6ab71..3957ef5a0c 100644
--- a/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp
+++ b/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp
@@ -270,7 +270,8 @@ template <class EventType> std::string key() {
}
boost::shared_ptr<BrokerReplicator> BrokerReplicator::create(
- HaBroker& hb, const boost::shared_ptr<broker::Link>& l) {
+ HaBroker& hb, const boost::shared_ptr<broker::Link>& l)
+{
boost::shared_ptr<BrokerReplicator> br(new BrokerReplicator(hb, l));
br->initialize();
return br;
@@ -330,13 +331,21 @@ void BrokerReplicator::initialize() {
BrokerReplicator::~BrokerReplicator() {}
namespace {
-void collectQueueReplicators(
- const boost::shared_ptr<Exchange>& ex,
- set<boost::shared_ptr<QueueReplicator> >& collect)
-{
- boost::shared_ptr<QueueReplicator> qr(boost::dynamic_pointer_cast<QueueReplicator>(ex));
- if (qr) collect.insert(qr);
-}
+struct QueueReplicators : public std::deque<boost::shared_ptr<QueueReplicator> > {
+ QueueReplicators(const ExchangeRegistry& er) { addAll(er); }
+
+ /** Add the exchange if it is a QueueReplicator. */
+ void add(const boost::shared_ptr<Exchange>& ex) {
+ boost::shared_ptr<QueueReplicator> qr =
+ boost::dynamic_pointer_cast<QueueReplicator>(ex);
+ if (qr) push_back(qr);
+ }
+ /** Add all QueueReplicator in the ExchangeRegistry. */
+ void addAll(const ExchangeRegistry& er) {
+ // Make copy of exchanges so we can work outside the registry lock.
+ er.eachExchange(boost::bind(&QueueReplicators::add, this, _1));
+ }
+};
} // namespace
void BrokerReplicator::shutdown() {
@@ -877,35 +886,22 @@ void BrokerReplicator::forced(broker::Connection& c, const std::string& message)
string BrokerReplicator::getType() const { return QPID_CONFIGURATION_REPLICATOR; }
-void BrokerReplicator::disconnectedQueueReplicator(boost::shared_ptr<Exchange> ex) {
- boost::shared_ptr<QueueReplicator> qr(boost::dynamic_pointer_cast<QueueReplicator>(ex));
- if (qr) {
- qr->disconnect();
- if (TxReplicator::isTxQueue(qr->getQueue()->getName())) {
- // Transactions are aborted on failover so clean up tx-queues
- deleteQueue(qr->getQueue()->getName());
- }
+void BrokerReplicator::disconnectedQueueReplicator(
+ const boost::shared_ptr<QueueReplicator>& qr)
+{
+ qr->disconnect();
+ if (TxReplicator::isTxQueue(qr->getQueue()->getName())) {
+ // Transactions are aborted on failover so clean up tx-queues
+ deleteQueue(qr->getQueue()->getName());
}
}
-typedef vector<boost::shared_ptr<Exchange> > ExchangeVector;
-
-// Callback function for accumulating exchange candidates
-namespace {
-void exchangeAccumulatorCallback(ExchangeVector& ev, const Exchange::shared_ptr& i) {
- ev.push_back(i);
-}
-}
-
// Called by ConnectionObserver::disconnected, disconnected from the network side.
void BrokerReplicator::disconnected() {
QPID_LOG(info, logPrefix << "Disconnected from primary " << primary);
connect = 0;
-
- // Make copy of exchanges so we can work outside the registry lock.
- ExchangeVector exs;
- exchanges.eachExchange(boost::bind(&exchangeAccumulatorCallback, boost::ref(exs), _1));
- for_each(exs.begin(), exs.end(),
+ QueueReplicators qrs(broker.getExchanges());
+ for_each(qrs.begin(), qrs.end(),
boost::bind(&BrokerReplicator::disconnectedQueueReplicator, this, _1));
}
diff --git a/qpid/cpp/src/qpid/ha/BrokerReplicator.h b/qpid/cpp/src/qpid/ha/BrokerReplicator.h
index 445406ad19..1e051878ae 100644
--- a/qpid/cpp/src/qpid/ha/BrokerReplicator.h
+++ b/qpid/cpp/src/qpid/ha/BrokerReplicator.h
@@ -108,8 +108,6 @@ class BrokerReplicator : public broker::Exchange,
typedef void (BrokerReplicator::*DispatchFunction)(types::Variant::Map&);
typedef qpid::sys::unordered_map<std::string, DispatchFunction> EventDispatchMap;
- typedef qpid::sys::unordered_map<std::string, QueueReplicatorPtr> QueueReplicatorMap;
-
class UpdateTracker;
class ErrorListener;
@@ -152,7 +150,7 @@ class BrokerReplicator : public broker::Exchange,
void deleteQueue(const std::string& name, bool purge=true);
void deleteExchange(const std::string& name);
- void disconnectedQueueReplicator(boost::shared_ptr<broker::Exchange>);
+ void disconnectedQueueReplicator(const boost::shared_ptr<QueueReplicator>&);
void disconnected();
void setMembership(const types::Variant::List&); // Set membership from list.
diff --git a/qpid/cpp/src/qpid/ha/ErrorListener.h b/qpid/cpp/src/qpid/ha/ErrorListener.h
deleted file mode 100644
index 1ae2078a11..0000000000
--- a/qpid/cpp/src/qpid/ha/ErrorListener.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef QPID_HA_ERRORLISTENER_H
-#define QPID_HA_ERRORLISTENER_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/broker/SessionHandler.h"
-#include "qpid/log/Statement.h"
-#include "qpid/framing/reply_exceptions.h"
-
-namespace qpid {
-namespace ha {
-
-/** Default ErrorListener for HA module */
-class ErrorListener : public broker::SessionHandler::ErrorListener {
- public:
- ErrorListener(const std::string& logPrefix_) : logPrefix(logPrefix_) {}
-
- void connectionException(framing::connection::CloseCode code, const std::string& msg) {
- QPID_LOG(error, logPrefix << framing::createConnectionException(code, msg).what());
- }
- void channelException(framing::session::DetachCode code, const std::string& msg) {
- QPID_LOG(error, logPrefix << framing::createChannelException(code, msg).what());
- }
- void executionException(framing::execution::ErrorCode code, const std::string& msg) {
- QPID_LOG(error, logPrefix << framing::createSessionException(code, msg).what());
- }
- void incomingExecutionException(framing::execution::ErrorCode code, const std::string& msg) {
- QPID_LOG(error, logPrefix << "Incoming " << framing::createSessionException(code, msg).what());
- }
- void detach() {
- QPID_LOG(error, logPrefix << "Session detached.");
- }
-
- private:
- std::string logPrefix;
-};
-
-
-}} // namespace qpid::ha
-
-#endif /*!QPID_HA_ERRORLISTENER_H*/
diff --git a/qpid/cpp/src/qpid/ha/QueueReplicator.cpp b/qpid/cpp/src/qpid/ha/QueueReplicator.cpp
index 59b2013f59..6881896f5e 100644
--- a/qpid/cpp/src/qpid/ha/QueueReplicator.cpp
+++ b/qpid/cpp/src/qpid/ha/QueueReplicator.cpp
@@ -39,6 +39,7 @@
#include "qpid/Msg.h"
#include "qpid/assert.h"
#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
#include <boost/bind.hpp>
@@ -90,7 +91,8 @@ class QueueReplicator::ErrorListener : public SessionHandler::ErrorListener {
QPID_LOG(debug, logPrefix << framing::createSessionException(code, msg).what());
}
void incomingExecutionException(ErrorCode code, const std::string& msg) {
- if (!queueReplicator->deletedOnPrimary(code, msg))
+ boost::shared_ptr<QueueReplicator> qr = queueReplicator.lock();
+ if (qr && !qr->deletedOnPrimary(code, msg))
QPID_LOG(error, logPrefix << "Incoming "
<< framing::createSessionException(code, msg).what());
}
@@ -98,7 +100,7 @@ class QueueReplicator::ErrorListener : public SessionHandler::ErrorListener {
QPID_LOG(debug, logPrefix << "Session detached");
}
private:
- boost::shared_ptr<QueueReplicator> queueReplicator;
+ boost::weak_ptr<QueueReplicator> queueReplicator;
std::string logPrefix;
};
@@ -112,9 +114,12 @@ class QueueReplicator::QueueObserver : public broker::QueueObserver {
void consumerAdded( const Consumer& ) {}
void consumerRemoved( const Consumer& ) {}
// Queue observer is destroyed when the queue is.
- void destroy() { queueReplicator->destroy(); }
+ void destroy() {
+ boost::shared_ptr<QueueReplicator> qr = queueReplicator.lock();
+ if (qr) qr->destroy();
+ }
private:
- boost::shared_ptr<QueueReplicator> queueReplicator;
+ boost::weak_ptr<QueueReplicator> queueReplicator;
};
boost::shared_ptr<QueueReplicator> QueueReplicator::create(
@@ -171,8 +176,7 @@ void QueueReplicator::initialize() {
throw Exception(QPID_MSG("Duplicate queue replicator " << getName()));
// Enable callback to initializeBridge
- std::pair<Bridge::shared_ptr, bool> result =
- queue->getBroker()->getLinks().declare(
+ boost::shared_ptr<Bridge> b = queue->getBroker()->getLinks().declare(
bridgeName,
*link,
false, // durable
@@ -189,10 +193,10 @@ void QueueReplicator::initialize() {
// Include shared_ptr to self to ensure we are not deleted
// before initializeBridge is called.
boost::bind(&QueueReplicator::initializeBridge, shared_from_this(), _1, _2)
- );
- bridge = result.first;
- bridge->setErrorListener(
+ ).first;
+ b->setErrorListener(
boost::shared_ptr<ErrorListener>(new ErrorListener(shared_from_this())));
+ bridge = b; // bridge is a weak_ptr to avoid a cycle.
// Enable callback to destroy()
queue->getObservers().add(
@@ -211,7 +215,7 @@ void QueueReplicator::destroy() {
{
Mutex::ScopedLock l(lock);
if (!queue) return; // Already destroyed
- bridge2 = bridge; // call close outside the lock.
+ bridge2 = bridge.lock(); // !call close outside the lock.
destroy(l);
}
if (bridge2) bridge2->close(); // Outside of lock, avoid deadlock.
diff --git a/qpid/cpp/src/qpid/ha/QueueReplicator.h b/qpid/cpp/src/qpid/ha/QueueReplicator.h
index f94c6de116..757f12c7a9 100644
--- a/qpid/cpp/src/qpid/ha/QueueReplicator.h
+++ b/qpid/cpp/src/qpid/ha/QueueReplicator.h
@@ -112,7 +112,7 @@ class QueueReplicator : public broker::Exchange,
const BrokerInfo brokerInfo;
DispatchMap dispatch;
boost::shared_ptr<broker::Link> link;
- boost::shared_ptr<broker::Bridge> bridge;
+ boost::weak_ptr<broker::Bridge> bridge;
boost::shared_ptr<broker::Queue> queue;
broker::SessionHandler* sessionHandler;
diff --git a/qpid/cpp/src/qpid/linearstore/ISSUES b/qpid/cpp/src/qpid/linearstore/ISSUES
index 8c5b08bb61..7f4d7750d0 100644
--- a/qpid/cpp/src/qpid/linearstore/ISSUES
+++ b/qpid/cpp/src/qpid/linearstore/ISSUES
@@ -26,6 +26,7 @@ Current/pending:
5359 - Linearstore: Implement new management schema and wire into store
5360 - Linearstore: Evaluate and rework logging to produce a consistent log output
5361 - Linearstore: No tests for linearstore functionality currently exist
+ svn r.1564893 2014-02-05: Added tx-test-soak.sh
* No existing tests for linearstore:
** Basic broker-level tests for txn and non-txn recovery
** Store-level tests which check write boundary conditions
@@ -34,29 +35,29 @@ Current/pending:
** Basic performance tests
5362 - Linearstore: No store tools exist for examining the journals
svn r.1558888 2014-01-09: WIP checkin for linearstore version of qpid_qls_analyze. Needs testing and tidy-up.
+ svn r.1560530 2014-01-22: Bugfixes for qpid_qls_analyze
+ svn r.1561848 2014-01-27: Bugfixes and enhancements for qpid_qls_analyze
+ svn r.1564808 2014-02-05: Bugfixes and enhancements for qpid_qls_analyze
* Store analysis and status
* Recovery/reading of message content
* Empty file pool status and management
5464 - [linearstore] Incompletely created journal files accumulate in EFP
- 5479 1053701 [linearstore] Using recovered store results in "JERR_JNLF_FILEOFFSOVFL: Attempted to increase submitted offset past file size. (JournalFile::submittedDblkCount)" error message
- * Probablilty: 2 of 600 (0.3%) using tx-test-soak.sh
- 5480 1053749 [linearstore] Recovery of store failure with "JERR_MAP_NOTFOUND: Key not found in map." error message
- * Probability: 6 of 600 (1.0%) using tx-test-soak.sh
- * If broker is started a second time after failure, it starts correctly and test completes ok.
5484 1035843 Slow performance for producers
- svn r.1558592 fixes an issue with using /dev/random as a source of random numbers for Journal serial numbers.
- - 1036026 [LinearStore] Qpid linear store unable to create durable queue - framing-error: Queue <q-name>: create() failed: jexception 0x0000
+ svn r.1558592 2014-01-15 fixes an issue with using /dev/random as a source of random numbers for Journal serial numbers.
+ svn r.1558913 2014-01-16 replaces use of /dev/urandom with several calls to rand() to construct a 64-bit random number.
+ * Recommend rebuilding and testing for performance again with these two fixes. Marked POST.
+# - 1036026 [LinearStore] Qpid linear store unable to create durable queue - framing-error: Queue <q-name>: create() failed: jexception 0x0000
UNABLE TO REPRODUCE - but Frantizek has additional info
- 1039522 Qpid crashes while recovering from linear store around apid::linearstore::journal::JournalFile::getFqFileName() including enq_rec::decode() threw JERR_JREC_BAD_RECTAIL
* Possible dup of 1039525
- * May be fixed by QPID-5483 - waiting for needinfo
+ * May be fixed by QPID-5483 - waiting for needinfo, recommend rebuilding with QPID-5483 fix and re-testing
- 1039525 Qpid crashes while recovering from linear store around apid::linearstore::journal::jexception::format including enq_rec::decode() threw JERR_JREC_BAD_REC_TAIL
* Possible dup of 1039522
- * May be fixed by QPID-5483 - waiting for needinfo
- 5487 - [linearstore] Replace use of /dev/urandom with c random generator calls
+ * May be fixed by QPID-5483 - waiting for needinfo, recommend rebuilding with QPID-5483 fix and re-testing
+# - 1049870 [LinearStore] auto-delete property does not survive restart
-Fixed/closed:
-=============
+Fixed/closed (in commit order):
+===============================
Q-JIRA RHBZ Description / Comments
------ ------- ----------------------
5357 1052518 Linearstore: Empty file recycling not functional
@@ -85,6 +86,17 @@ NO-JIRA - Added missing Apache copyright/license text
svn r.1558589 2014-01-15: Proposed fix
* May be linked to RHBZ 1039522 - waiting for needinfo
* May be linked to RHBZ 1039525 - waiting for needinfo
+ 5487 1054448 [linearstore] Replace use of /dev/urandom with c random generator calls
+ svn r.1558913 2014-01-16: Proposed fix
+ 5480 1053749 [linearstore] Recovery of store failure with "JERR_MAP_NOTFOUND: Key not found in map." error message
+ svn r.1564877 2014-02-05: Proposed fix
+ * Probability: 6 of 600 (1.0%) using tx-test-soak.sh
+ * If broker is started a second time after failure, it starts correctly and test completes ok.
+ * Problem: File is being recycled to EFP with still-locked enqueues in it (ie dequeued transactionally).
+ * Problem: Record alignment check writes filler records to wrong file when decoding bad record moves across a file boundary
+ 5479 1053701 [linearstore] Using recovered store results in "JERR_JNLF_FILEOFFSOVFL: Attempted to increase submitted offset past file size. (JournalFile::submittedDblkCount)" error message
+ * Probability: 2 of 600 (0.3%) using tx-test-soak.sh
+ * Fixed by checkin for QPID-5480, no longer able to reproduce. Marked POST.
Future:
=======
@@ -101,3 +113,4 @@ Code tidy-up
* Member names: xxx_
* Rename classes, functions and variables to camel-case
* Add Doxygen docs to classes
+* Make fid's consistent in name (fid, file_id, pfid) and format (hex vs decimal)
diff --git a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp b/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp
index 483b494c2c..ff5b41b962 100644
--- a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp
+++ b/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.cpp
@@ -593,7 +593,7 @@ void MessageStoreImpl::recover(qpid::broker::RecoveryManager& registry_)
std::ostringstream oss;
oss << "Recovered transaction prepared list:";
for (txn_list::iterator i = prepared.begin(); i != prepared.end(); i++) {
- oss << std::endl << " " << str2hexnum(i->xid);
+ oss << std::endl << " " << qpid::linearstore::journal::jcntl::str2hexnum(i->xid);
}
QLS_LOG(debug, oss.str());
@@ -1292,7 +1292,7 @@ void MessageStoreImpl::completed(TxnCtxt& txn_,
mgmtObject->inc_tplTxnAborts();
}
} catch (const std::exception& e) {
- QLS_LOG(error, "Error completing xid " << txn_.getXid() << ": " << e.what());
+ QLS_LOG(error, "Error completing xid " << qpid::linearstore::journal::jcntl::str2hexnum(txn_.getXid()) << ": " << e.what());
throw;
}
}
@@ -1516,15 +1516,6 @@ void MessageStoreImpl::journalDeleted(JournalImpl& j_) {
journalList.erase(j_.id());
}
-std::string MessageStoreImpl::str2hexnum(const std::string& str) {
- std::ostringstream oss;
- oss << "(" << str.size() << ")0x" << std::hex;
- for (unsigned i=str.size(); i>0; --i) {
- oss << std::setfill('0') << std::setw(2) << (uint16_t)(uint8_t)str[i-1];
- }
- return oss.str();
-}
-
MessageStoreImpl::StoreOptions::StoreOptions(const std::string& name_) :
qpid::Options(name_),
truncateFlag(defTruncateFlag),
diff --git a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h b/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h
index 3157b9be9d..c2eb0deab0 100644
--- a/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h
+++ b/qpid/cpp/src/qpid/linearstore/MessageStoreImpl.h
@@ -235,8 +235,6 @@ class MessageStoreImpl : public qpid::broker::MessageStore, public qpid::managem
}
void chkTplStoreInit();
- static std::string str2hexnum(const std::string& str);
-
public:
typedef boost::shared_ptr<MessageStoreImpl> shared_ptr;
diff --git a/qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp b/qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp
index 743d12989a..df2e7a442d 100644
--- a/qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp
+++ b/qpid/cpp/src/qpid/linearstore/TxnCtxt.cpp
@@ -52,7 +52,9 @@ void TxnCtxt::commitTxn(JournalImpl* jc, bool commit) {
jc->txn_abort(dtokp.get(), getXid());
}
} catch (const qpid::linearstore::journal::jexception& e) {
- THROW_STORE_EXCEPTION(std::string("Error commit") + e.what());
+ std::ostringstream oss;
+ oss << "Error during " << (commit ? "commit" : "abort") << ": " << e.what();
+ THROW_STORE_EXCEPTION(oss.str());
}
}
}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/JournalFile.cpp b/qpid/cpp/src/qpid/linearstore/journal/JournalFile.cpp
index 1b2025bd5a..fc6ced4fd2 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/JournalFile.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/JournalFile.cpp
@@ -27,18 +27,18 @@
#include "qpid/linearstore/journal/utils/file_hdr.h"
#include <unistd.h>
-//#include <iostream> // DEBUG
-
namespace qpid {
namespace linearstore {
namespace journal {
JournalFile::JournalFile(const std::string& fqFileName,
const efpIdentity_t& efpIdentity,
- const uint64_t fileSeqNum) :
+ const uint64_t fileSeqNum,
+ const std::string queueName) :
efpIdentity_(efpIdentity),
fqFileName_(fqFileName),
fileSeqNum_(fileSeqNum),
+ queueName_(queueName),
serial_(getRandom64()),
firstRecordOffset_(0ULL),
fileHandle_(-1),
@@ -47,6 +47,7 @@ JournalFile::JournalFile(const std::string& fqFileName,
fileHeaderPtr_(0),
aioControlBlockPtr_(0),
fileSize_dblks_(((efpIdentity.ds_ * 1024) + (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES)) / QLS_DBLK_SIZE_BYTES),
+ initializedFlag_(false),
enqueuedRecordCount_("JournalFile::enqueuedRecordCount", 0),
submittedDblkCount_("JournalFile::submittedDblkCount", 0),
completedDblkCount_("JournalFile::completedDblkCount", 0),
@@ -54,10 +55,12 @@ JournalFile::JournalFile(const std::string& fqFileName,
{}
JournalFile::JournalFile(const std::string& fqFileName,
- const ::file_hdr_t& fileHeader) :
+ const ::file_hdr_t& fileHeader,
+ const std::string queueName) :
efpIdentity_(fileHeader._efp_partition, fileHeader._data_size_kib),
fqFileName_(fqFileName),
fileSeqNum_(fileHeader._file_number),
+ queueName_(queueName),
serial_(fileHeader._rhdr._serial),
firstRecordOffset_(fileHeader._fro),
fileHandle_(-1),
@@ -66,6 +69,7 @@ JournalFile::JournalFile(const std::string& fqFileName,
fileHeaderPtr_(0),
aioControlBlockPtr_(0),
fileSize_dblks_(((fileHeader._data_size_kib * 1024) + (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_BYTES)) / QLS_DBLK_SIZE_BYTES),
+ initializedFlag_(false),
enqueuedRecordCount_("JournalFile::enqueuedRecordCount", 0),
submittedDblkCount_("JournalFile::submittedDblkCount", 0),
completedDblkCount_("JournalFile::completedDblkCount", 0),
@@ -78,18 +82,21 @@ JournalFile::~JournalFile() {
void
JournalFile::initialize(const uint32_t completedDblkCount) {
- if (::posix_memalign(&fileHeaderBasePtr_, QLS_AIO_ALIGN_BOUNDARY_BYTES, QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024))
- {
- std::ostringstream oss;
- oss << "posix_memalign(): blksize=" << QLS_AIO_ALIGN_BOUNDARY_BYTES << " size=" << (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024);
- oss << FORMAT_SYSERR(errno);
- throw jexception(jerrno::JERR__MALLOC, oss.str(), "JournalFile", "initialize");
+ if (!initializedFlag_) {
+ if (::posix_memalign(&fileHeaderBasePtr_, QLS_AIO_ALIGN_BOUNDARY_BYTES, QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024))
+ {
+ std::ostringstream oss;
+ oss << "posix_memalign(): blksize=" << QLS_AIO_ALIGN_BOUNDARY_BYTES << " size=" << (QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024);
+ oss << FORMAT_SYSERR(errno);
+ throw jexception(jerrno::JERR__MALLOC, oss.str(), "JournalFile", "initialize");
+ }
+ fileHeaderPtr_ = (::file_hdr_t*)fileHeaderBasePtr_;
+ aioControlBlockPtr_ = new aio_cb;
+ initializedFlag_ = true;
}
- fileHeaderPtr_ = (::file_hdr_t*)fileHeaderBasePtr_;
- aioControlBlockPtr_ = new aio_cb;
if (completedDblkCount > 0UL) {
- submittedDblkCount_.add(completedDblkCount);
- completedDblkCount_.add(completedDblkCount);
+ submittedDblkCount_.set(completedDblkCount);
+ completedDblkCount_.set(completedDblkCount);
}
}
@@ -149,8 +156,7 @@ void JournalFile::asyncFileHeaderWrite(io_context_t ioContextPtr,
const efpDataSize_kib_t efpDataSize_kib,
const uint16_t userFlags,
const uint64_t recordId,
- const uint64_t firstRecordOffset,
- const std::string queueName) {
+ const uint64_t firstRecordOffset) {
firstRecordOffset_ = firstRecordOffset;
::file_hdr_create(fileHeaderPtr_, QLS_FILE_MAGIC, QLS_JRNL_VERSION, QLS_JRNL_FHDR_RES_SIZE_SBLKS, efpPartitionNumber, efpDataSize_kib);
::file_hdr_init(fileHeaderBasePtr_,
@@ -160,15 +166,15 @@ void JournalFile::asyncFileHeaderWrite(io_context_t ioContextPtr,
recordId,
firstRecordOffset,
fileSeqNum_,
- queueName.size(),
- queueName.data());
- aio::prep_pwrite(aioControlBlockPtr_,
- fileHandle_,
- (void*)fileHeaderBasePtr_,
- QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024,
- 0UL);
- if (aio::submit(ioContextPtr, 1, &aioControlBlockPtr_) < 0)
- throw jexception(jerrno::JERR__AIO, "JournalFile", "asyncPageWrite");
+ queueName_.size(),
+ queueName_.data());
+ const std::size_t wr_size = QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_KIB * 1024;
+ aio::prep_pwrite(aioControlBlockPtr_, fileHandle_, (void*)fileHeaderBasePtr_, wr_size, 0UL);
+ if (aio::submit(ioContextPtr, 1, &aioControlBlockPtr_) < 0) {
+ std::ostringstream oss;
+ oss << "queue=\"" << queueName_ << "\" fid=0x" << std::hex << fileSeqNum_ << " wr_size=0x" << wr_size << " foffs=0x0";
+ throw jexception(jerrno::JERR__AIO, oss.str(), "JournalFile", "asyncFileHeaderWrite");
+ }
addSubmittedDblkCount(QLS_JRNL_FHDR_RES_SIZE_SBLKS * QLS_SBLK_SIZE_DBLKS);
incrOutstandingAioOperationCount();
}
@@ -177,16 +183,16 @@ void JournalFile::asyncPageWrite(io_context_t ioContextPtr,
aio_cb* aioControlBlockPtr,
void* data,
uint32_t dataSize_dblks) {
- aio::prep_pwrite_2(aioControlBlockPtr,
- fileHandle_,
- data,
- dataSize_dblks * QLS_DBLK_SIZE_BYTES,
- submittedDblkCount_.get() * QLS_DBLK_SIZE_BYTES);
+ const std::size_t wr_size = dataSize_dblks * QLS_DBLK_SIZE_BYTES;
+ const uint64_t foffs = submittedDblkCount_.get() * QLS_DBLK_SIZE_BYTES;
+ aio::prep_pwrite_2(aioControlBlockPtr, fileHandle_, data, wr_size, foffs);
pmgr::page_cb* pcbp = (pmgr::page_cb*)(aioControlBlockPtr->data); // This page's control block (pcb)
pcbp->_wdblks = dataSize_dblks;
pcbp->_jfp = this;
if (aio::submit(ioContextPtr, 1, &aioControlBlockPtr) < 0) {
- throw jexception(jerrno::JERR__AIO, "JournalFile", "asyncPageWrite"); // TODO: complete exception details
+ std::ostringstream oss;
+ oss << "queue=\"" << queueName_ << "\" fid=0x" << std::hex << fileSeqNum_ << " wr_size=0x" << wr_size << " foffs=0x" << foffs;
+ throw jexception(jerrno::JERR__AIO, oss.str(), "JournalFile", "asyncPageWrite");
}
addSubmittedDblkCount(dataSize_dblks);
incrOutstandingAioOperationCount();
diff --git a/qpid/cpp/src/qpid/linearstore/journal/JournalFile.h b/qpid/cpp/src/qpid/linearstore/journal/JournalFile.h
index f0ad432fd8..e33830ef7f 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/JournalFile.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/JournalFile.h
@@ -38,6 +38,7 @@ protected:
const efpIdentity_t efpIdentity_;
const std::string fqFileName_;
const uint64_t fileSeqNum_;
+ const std::string queueName_;
const uint64_t serial_;
uint64_t firstRecordOffset_;
int fileHandle_;
@@ -46,6 +47,7 @@ protected:
::file_hdr_t* fileHeaderPtr_;
aio_cb* aioControlBlockPtr_;
uint32_t fileSize_dblks_; ///< File size in data blocks, including file header
+ bool initializedFlag_;
AtomicCounter<uint32_t> enqueuedRecordCount_; ///< Count of enqueued records
AtomicCounter<uint32_t> submittedDblkCount_; ///< Write file count (data blocks) for submitted AIO
@@ -56,10 +58,12 @@ public:
// Constructor for creating new file with known fileSeqNum and random serial
JournalFile(const std::string& fqFileName,
const efpIdentity_t& efpIdentity,
- const uint64_t fileSeqNum);
+ const uint64_t fileSeqNum,
+ const std::string queueName);
// Constructor for recovery in which fileSeqNum and serial are recovered from fileHeader param
JournalFile(const std::string& fqFileName,
- const ::file_hdr_t& fileHeader);
+ const ::file_hdr_t& fileHeader,
+ const std::string queueName);
virtual ~JournalFile();
void initialize(const uint32_t completedDblkCount);
@@ -76,13 +80,13 @@ public:
const efpDataSize_kib_t efpDataSize_kib,
const uint16_t userFlags,
const uint64_t recordId,
- const uint64_t firstRecordOffset,
- const std::string queueName);
+ const uint64_t firstRecordOffset);
void asyncPageWrite(io_context_t ioContextPtr,
aio_cb* aioControlBlockPtr,
void* data,
uint32_t dataSize_dblks);
+ uint32_t getSubmittedDblkCount() const;
uint32_t getEnqueuedRecordCount() const;
uint32_t incrEnqueuedRecordCount();
uint32_t decrEnqueuedRecordCount();
@@ -109,7 +113,6 @@ protected:
static uint64_t getRandom64();
bool isOpen() const;
- uint32_t getSubmittedDblkCount() const;
uint32_t addSubmittedDblkCount(const uint32_t a);
uint32_t getCompletedDblkCount() const;
diff --git a/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.cpp b/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.cpp
index 5483f3bb94..86d1b0e93c 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.cpp
@@ -25,8 +25,6 @@
#include "qpid/linearstore/journal/jcntl.h"
#include "qpid/linearstore/journal/JournalFile.h"
-//#include <iostream> // DEBUG
-
namespace qpid {
namespace linearstore {
namespace journal {
@@ -34,10 +32,10 @@ namespace journal {
LinearFileController::LinearFileController(jcntl& jcntlRef) :
jcntlRef_(jcntlRef),
emptyFilePoolPtr_(0),
- currentJournalFilePtr_(0),
fileSeqCounter_("LinearFileController::fileSeqCounter", 0),
recordIdCounter_("LinearFileController::recordIdCounter", 0),
- decrCounter_("LinearFileController::decrCounter", 0)
+ decrCounter_("LinearFileController::decrCounter", 0),
+ currentJournalFilePtr_(0)
{}
LinearFileController::~LinearFileController() {}
@@ -53,7 +51,7 @@ void LinearFileController::initialize(const std::string& journalDirectory,
void LinearFileController::finalize() {
if (currentJournalFilePtr_) {
currentJournalFilePtr_->close();
- currentJournalFilePtr_ = NULL;
+ currentJournalFilePtr_ = 0;
}
while (!journalFileList_.empty()) {
delete journalFileList_.front();
@@ -62,17 +60,21 @@ void LinearFileController::finalize() {
}
void LinearFileController::addJournalFile(JournalFile* journalFilePtr,
- const uint32_t completedDblkCount) {
- if (currentJournalFilePtr_) {
+ const uint32_t completedDblkCount,
+ const bool makeCurrentFlag) {
+ if (makeCurrentFlag && currentJournalFilePtr_) {
currentJournalFilePtr_->close();
+ currentJournalFilePtr_ = 0;
}
journalFilePtr->initialize(completedDblkCount);
- currentJournalFilePtr_ = journalFilePtr;
{
slock l(journalFileListMutex_);
- journalFileList_.push_back(currentJournalFilePtr_);
+ journalFileList_.push_back(journalFilePtr);
+ }
+ if (makeCurrentFlag) {
+ currentJournalFilePtr_ = journalFilePtr;
+ currentJournalFilePtr_->open();
}
- currentJournalFilePtr_->open();
}
efpDataSize_sblks_t LinearFileController::dataSize_sblks() const {
@@ -83,16 +85,20 @@ efpFileSize_sblks_t LinearFileController::fileSize_sblks() const {
return emptyFilePoolPtr_->fileSize_sblks();
}
+void LinearFileController::getNextJournalFile() {
+ if (currentJournalFilePtr_)
+ currentJournalFilePtr_->close();
+ pullEmptyFileFromEfp();
+}
+
uint64_t LinearFileController::getNextRecordId() {
return recordIdCounter_.increment();
}
-void LinearFileController::pullEmptyFileFromEfp() {
- if (currentJournalFilePtr_)
- currentJournalFilePtr_->close();
- std::string ef = emptyFilePoolPtr_->takeEmptyFile(journalDirectory_); // Moves file from EFP only, returns new file name
-//std::cout << "*** LinearFileController::pullEmptyFileFromEfp() qn=" << jcntlRef.id() << " ef=" << ef << std::endl; // DEBUG
- addJournalFile(ef, emptyFilePoolPtr_->getIdentity(), getNextFileSeqNum(), 0);
+void LinearFileController::removeFileToEfp(const std::string& fileName) {
+ if (emptyFilePoolPtr_) {
+ emptyFilePoolPtr_->returnEmptyFile(fileName);
+ }
}
void LinearFileController::restoreEmptyFile(const std::string& fileName) {
@@ -101,7 +107,11 @@ void LinearFileController::restoreEmptyFile(const std::string& fileName) {
void LinearFileController::purgeEmptyFilesToEfp() {
slock l(journalFileListMutex_);
- purgeEmptyFilesToEfpNoLock();
+ while (journalFileList_.front()->isNoEnqueuedRecordsRemaining() && journalFileList_.size() > 1) { // Can't purge last file, even if it has no enqueued records
+ emptyFilePoolPtr_->returnEmptyFile(journalFileList_.front()->getFqFileName());
+ delete journalFileList_.front();
+ journalFileList_.pop_front();
+ }
}
uint32_t LinearFileController::getEnqueuedRecordCount(const efpFileCount_t fileSeqNumber) {
@@ -113,7 +123,6 @@ uint32_t LinearFileController::incrEnqueuedRecordCount(const efpFileCount_t file
}
uint32_t LinearFileController::decrEnqueuedRecordCount(const efpFileCount_t fileSeqNumber) {
- slock l(journalFileListMutex_);
uint32_t r = find(fileSeqNumber)->decrEnqueuedRecordCount();
// TODO: Re-evaluate after testing and profiling
@@ -122,18 +131,16 @@ uint32_t LinearFileController::decrEnqueuedRecordCount(const efpFileCount_t file
// records). We need to check this rather simple scheme works for outlying scenarios (large and tiny data
// records) without impacting performance or performing badly (leaving excessive empty files in the journals).
if (decrCounter_.increment() % 100ULL == 0ULL) {
- purgeEmptyFilesToEfpNoLock();
+ purgeEmptyFilesToEfp();
}
return r;
}
uint32_t LinearFileController::addWriteCompletedDblkCount(const efpFileCount_t fileSeqNumber, const uint32_t a) {
- slock l(journalFileListMutex_);
return find(fileSeqNumber)->addCompletedDblkCount(a);
}
uint16_t LinearFileController::decrOutstandingAioOperationCount(const efpFileCount_t fileSeqNumber) {
- slock l(journalFileListMutex_);
return find(fileSeqNumber)->decrOutstandingAioOperationCount();
}
@@ -142,12 +149,11 @@ void LinearFileController::asyncFileHeaderWrite(io_context_t ioContextPtr,
const uint64_t recordId,
const uint64_t firstRecordOffset) {
currentJournalFilePtr_->asyncFileHeaderWrite(ioContextPtr,
- emptyFilePoolPtr_->getPartitionNumber(),
- emptyFilePoolPtr_->dataSize_kib(),
- userFlags,
- recordId,
- firstRecordOffset,
- jcntlRef_.id());
+ emptyFilePoolPtr_->getPartitionNumber(),
+ emptyFilePoolPtr_->dataSize_kib(),
+ userFlags,
+ recordId,
+ firstRecordOffset);
}
void LinearFileController::asyncPageWrite(io_context_t ioContextPtr,
@@ -195,8 +201,8 @@ void LinearFileController::addJournalFile(const std::string& fileName,
const efpIdentity_t& efpIdentity,
const uint64_t fileNumber,
const uint32_t completedDblkCount) {
- JournalFile* jfp = new JournalFile(fileName, efpIdentity, fileNumber);
- addJournalFile(jfp, completedDblkCount);
+ JournalFile* jfp = new JournalFile(fileName, efpIdentity, fileNumber, jcntlRef_.id());
+ addJournalFile(jfp, completedDblkCount, true);
}
void LinearFileController::assertCurrentJournalFileValid(const char* const functionName) const {
@@ -209,15 +215,17 @@ bool LinearFileController::checkCurrentJournalFileValid() const {
return currentJournalFilePtr_ != 0;
}
-// NOTE: NOT THREAD SAFE - journalFileList is accessed by multiple threads - use under external lock
JournalFile* LinearFileController::find(const efpFileCount_t fileSeqNumber) {
- if (currentJournalFilePtr_ != 0 && currentJournalFilePtr_->getFileSeqNum() == fileSeqNumber)
+ if (currentJournalFilePtr_ && currentJournalFilePtr_->getFileSeqNum() == fileSeqNumber)
return currentJournalFilePtr_;
+
+ slock l(journalFileListMutex_);
for (JournalFileListItr_t i=journalFileList_.begin(); i!=journalFileList_.end(); ++i) {
if ((*i)->getFileSeqNum() == fileSeqNumber) {
return *i;
}
}
+
std::ostringstream oss;
oss << "fileSeqNumber=" << fileSeqNumber;
throw jexception(jerrno::JERR_LFCR_SEQNUMNOTFOUND, oss.str(), "LinearFileController", "find");
@@ -227,15 +235,9 @@ uint64_t LinearFileController::getNextFileSeqNum() {
return fileSeqCounter_.increment();
}
-void LinearFileController::purgeEmptyFilesToEfpNoLock() {
-//std::cout << " >P n=" << journalFileList_.size() << " e=" << (journalFileList_.front()->isNoEnqueuedRecordsRemaining()?"T":"F") << std::flush; // DEBUG
- while (journalFileList_.front()->isNoEnqueuedRecordsRemaining() &&
- journalFileList_.size() > 1) { // Can't purge last file, even if it has no enqueued records
-//std::cout << " *f=" << journalFileList_.front()->getFqFileName() << std::flush; // DEBUG
- emptyFilePoolPtr_->returnEmptyFile(journalFileList_.front()->getFqFileName());
- delete journalFileList_.front();
- journalFileList_.pop_front();
- }
+void LinearFileController::pullEmptyFileFromEfp() {
+ std::string efn = emptyFilePoolPtr_->takeEmptyFile(journalDirectory_); // Moves file from EFP only (ie no file init), returns new file name
+ addJournalFile(efn, emptyFilePoolPtr_->getIdentity(), getNextFileSeqNum(), 0);
}
}}}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.h b/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.h
index 933b9792a4..05f08144b9 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/LinearFileController.h
@@ -44,12 +44,12 @@ protected:
jcntl& jcntlRef_;
std::string journalDirectory_;
EmptyFilePool* emptyFilePoolPtr_;
- JournalFile* currentJournalFilePtr_;
AtomicCounter<uint64_t> fileSeqCounter_;
AtomicCounter<uint64_t> recordIdCounter_;
AtomicCounter<uint64_t> decrCounter_;
JournalFileList_t journalFileList_;
+ JournalFile* currentJournalFilePtr_;
smutex journalFileListMutex_;
public:
@@ -62,12 +62,14 @@ public:
void finalize();
void addJournalFile(JournalFile* journalFilePtr,
- const uint32_t completedDblkCount);
+ const uint32_t completedDblkCount,
+ const bool makeCurrentFlag);
efpDataSize_sblks_t dataSize_sblks() const;
efpFileSize_sblks_t fileSize_sblks() const;
+ void getNextJournalFile();
uint64_t getNextRecordId();
- void pullEmptyFileFromEfp();
+ void removeFileToEfp(const std::string& fileName);
void restoreEmptyFile(const std::string& fileName);
void purgeEmptyFilesToEfp();
@@ -105,11 +107,12 @@ protected:
bool checkCurrentJournalFileValid() const;
JournalFile* find(const efpFileCount_t fileSeqNumber);
uint64_t getNextFileSeqNum();
- void purgeEmptyFilesToEfpNoLock();
+ void pullEmptyFileFromEfp();
};
typedef void (LinearFileController::*lfcAddJournalFileFn)(JournalFile* journalFilePtr,
- const uint32_t completedDblkCount);
+ const uint32_t completedDblkCount,
+ const bool makeCurrentFlag);
}}}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp b/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp
index 72308cc929..a1cec53ca1 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.cpp
@@ -56,11 +56,15 @@ RecoveredRecordData_t::RecoveredRecordData_t(const uint64_t rid, const uint64_t
pendingTransaction_(ptxn)
{}
-
bool recordIdListCompare(RecoveredRecordData_t a, RecoveredRecordData_t b) {
return a.recordId_ < b.recordId_;
}
+RecoveredFileData_t::RecoveredFileData_t(JournalFile* journalFilePtr, const uint32_t completedDblkCount) :
+ journalFilePtr_(journalFilePtr),
+ completedDblkCount_(completedDblkCount)
+{}
+
RecoveryManager::RecoveryManager(const std::string& journalDirectory,
const std::string& queuename,
enq_map& enqueueMapRef,
@@ -77,11 +81,17 @@ RecoveryManager::RecoveryManager(const std::string& journalDirectory,
highestRecordId_(0ULL),
highestFileNumber_(0ULL),
lastFileFullFlag_(false),
+ initial_fid_(0),
currentSerial_(0),
efpFileSize_kib_(0)
{}
-RecoveryManager::~RecoveryManager() {}
+RecoveryManager::~RecoveryManager() {
+ for (fileNumberMapItr_t i = fileNumberMap_.begin(); i != fileNumberMap_.end(); ++i) {
+ delete i->second;
+ }
+ fileNumberMap_.clear();
+}
void RecoveryManager::analyzeJournals(const std::vector<std::string>* preparedTransactionListPtr,
EmptyFilePoolManager* emptyFilePoolManager,
@@ -92,9 +102,6 @@ void RecoveryManager::analyzeJournals(const std::vector<std::string>* preparedTr
*emptyFilePoolPtrPtr = emptyFilePoolManager->getEmptyFilePool(efpIdentity);
efpFileSize_kib_ = (*emptyFilePoolPtrPtr)->fileSize_kib();
- // Check for file full condition
- lastFileFullFlag_ = endOffset_ == (std::streamoff)(*emptyFilePoolPtrPtr)->fileSize_kib() * 1024;
-
if (!journalEmptyFlag_) {
// Read all records, establish remaining enqueued records
@@ -106,6 +113,9 @@ void RecoveryManager::analyzeJournals(const std::vector<std::string>* preparedTr
inFileStream_.close();
}
+ // Check for file full condition
+ lastFileFullFlag_ = endOffset_ == (std::streamoff)(*emptyFilePoolPtrPtr)->fileSize_kib() * 1024;
+
// Remove leading files which have no enqueued records
removeEmptyFiles(*emptyFilePoolPtrPtr);
@@ -121,7 +131,7 @@ void RecoveryManager::analyzeJournals(const std::vector<std::string>* preparedTr
// Unlock any affected enqueues in emap
for (tdl_itr_t i=tdl.begin(); i<tdl.end(); i++) {
if (i->enq_flag_) { // enq op - decrement enqueue count
- fileNumberMap_[i->pfid_]->decrEnqueuedRecordCount();
+ fileNumberMap_[i->pfid_]->journalFilePtr_->decrEnqueuedRecordCount();
} else if (enqueueMapRef_.is_enqueued(i->drid_, true)) { // deq op - unlock enq record
if (enqueueMapRef_.unlock(i->drid_) < enq_map::EMAP_OK) { // fail
// enq_map::unlock()'s only error is enq_map::EMAP_RID_NOT_FOUND
@@ -174,7 +184,7 @@ bool RecoveryManager::readNextRemainingRecord(void** const dataPtrPtr,
}
} while (!foundRecord);
- if (!inFileStream_.is_open() || currentJournalFileConstItr_->first != recordIdListConstItr_->fileId_) {
+ if (!inFileStream_.is_open() || currentJournalFileItr_->first != recordIdListConstItr_->fileId_) {
if (!getFile(recordIdListConstItr_->fileId_, false)) {
std::ostringstream oss;
oss << "Failed to open file with file-id=" << recordIdListConstItr_->fileId_;
@@ -231,7 +241,6 @@ bool RecoveryManager::readNextRemainingRecord(void** const dataPtrPtr,
::rec_tail_t enqueueTail;
inFileStream_.read((char*)&enqueueTail, sizeof(::rec_tail_t));
uint32_t cs = checksum.getChecksum();
-//std::cout << std::hex << "### rid=0x" << enqueueHeader._rhdr._rid << " rtcs=0x" << enqueueTail._checksum << " cs=0x" << cs << std::dec << std::endl; // DEBUG
uint16_t res = ::rec_tail_check(&enqueueTail, &enqueueHeader._rhdr, cs);
if (res != 0) {
std::stringstream oss;
@@ -266,17 +275,30 @@ bool RecoveryManager::readNextRemainingRecord(void** const dataPtrPtr,
void RecoveryManager::setLinearFileControllerJournals(lfcAddJournalFileFn fnPtr,
LinearFileController* lfcPtr) {
if (journalEmptyFlag_) {
- if (uninitializedJournal_.size() > 0) {
- lfcPtr->restoreEmptyFile(uninitializedJournal_);
+ if (uninitFileList_.size() > 0) {
+ std::string uninitFile = uninitFileList_.back();
+ uninitFileList_.pop_back();
+ lfcPtr->restoreEmptyFile(uninitFile);
}
} else {
for (fileNumberMapConstItr_t i = fileNumberMap_.begin(); i != fileNumberMap_.end(); ++i) {
- uint32_t fileDblkCount = i->first == highestFileNumber_ ? // Is this this last file?
- endOffset_ / QLS_DBLK_SIZE_BYTES : // Last file uses _endOffset
- efpFileSize_kib_ * 1024 / QLS_DBLK_SIZE_BYTES; // All others use file size to make them full
- (lfcPtr->*fnPtr)(i->second, fileDblkCount);
+ (lfcPtr->*fnPtr)(i->second->journalFilePtr_, i->second->completedDblkCount_, i->first == initial_fid_);
}
}
+
+ std::ostringstream oss;
+ bool logFlag = !notNeededFilesList_.empty();
+ if (logFlag) {
+ oss << "Files removed from head of journal: prior truncation during recovery:";
+ }
+ while (!notNeededFilesList_.empty()) {
+ lfcPtr->removeFileToEfp(notNeededFilesList_.back());
+ oss << std::endl << " * " << notNeededFilesList_.back();
+ notNeededFilesList_.pop_back();
+ }
+ if (logFlag) {
+ journalLogRef_.log(JournalLog::LOG_NOTICE, queueName_, oss.str());
+ }
}
std::string RecoveryManager::toString(const std::string& jid) {
@@ -285,7 +307,7 @@ std::string RecoveryManager::toString(const std::string& jid) {
oss << " Number of journal files = " << fileNumberMap_.size() << std::endl;
oss << " Journal File List:" << std::endl;
for (fileNumberMapConstItr_t k=fileNumberMap_.begin(); k!=fileNumberMap_.end(); ++k) {
- std::string fqFileName = k->second->getFqFileName();
+ std::string fqFileName = k->second->journalFilePtr_->getFqFileName();
oss << " " << k->first << ": " << fqFileName.substr(fqFileName.rfind('/')+1) << std::endl;
}
oss << " Enqueue Counts: [ ";
@@ -293,7 +315,7 @@ std::string RecoveryManager::toString(const std::string& jid) {
if (l != fileNumberMap_.begin()) {
oss << ", ";
}
- oss << l->second->getEnqueuedRecordCount();
+ oss << l->second->journalFilePtr_->getEnqueuedRecordCount();
}
oss << " ]" << std::endl;
oss << " Journal empty = " << (journalEmptyFlag_ ? "TRUE" : "FALSE") << std::endl;
@@ -330,15 +352,17 @@ std::string RecoveryManager::toLog(const std::string& jid, const int indent) {
<< std::setw(10) << "--------"
<< std::endl;
for (fileNumberMapConstItr_t k=fileNumberMap_.begin(); k!=fileNumberMap_.end(); ++k) {
- std::string fqFileName = k->second->getFqFileName();
+ std::string fqFileName = k->second->journalFilePtr_->getFqFileName();
+ std::ostringstream fid;
+ fid << std::hex << "0x" << k->first;
std::ostringstream fro;
- fro << std::hex << "0x" << k->second->getFirstRecordOffset();
- oss << indentStr << std::setw(7) << k->first
+ fro << std::hex << "0x" << k->second->journalFilePtr_->getFirstRecordOffset();
+ oss << indentStr << std::setw(7) << fid.str()
<< std::setw(43) << fqFileName.substr(fqFileName.rfind('/')+1)
<< std::setw(16) << fro.str()
- << std::setw(12) << k->second->getEnqueuedRecordCount()
- << std::setw(5) << k->second->getEfpIdentity().pn_
- << std::setw(9) << k->second->getEfpIdentity().ds_ << "k"
+ << std::setw(12) << k->second->journalFilePtr_->getEnqueuedRecordCount()
+ << std::setw(5) << k->second->journalFilePtr_->getEfpIdentity().pn_
+ << std::setw(9) << k->second->journalFilePtr_->getEfpIdentity().ds_ << "k"
<< std::endl;
}
oss << indentStr << "First record offset in first file = 0x" << std::hex << firstRecordOffset_ <<
@@ -347,7 +371,7 @@ std::string RecoveryManager::toLog(const std::string& jid, const int indent) {
(endOffset_/QLS_DBLK_SIZE_BYTES) << " dblks)" << std::endl;
oss << indentStr << "Highest rid found = 0x" << std::hex << highestRecordId_ << std::dec << std::endl;
oss << indentStr << "Last file full = " << (lastFileFullFlag_ ? "TRUE" : "FALSE") << std::endl;
- oss << indentStr << "Enqueued records (txn & non-txn):";
+ //oss << indentStr << "Enqueued records (txn & non-txn):"; // TODO: complete report
}
return oss.str();
}
@@ -357,27 +381,28 @@ std::string RecoveryManager::toLog(const std::string& jid, const int indent) {
void RecoveryManager::analyzeJournalFileHeaders(efpIdentity_t& efpIdentity) {
std::string headerQueueName;
::file_hdr_t fileHeader;
- directoryList_t directoryList;
+ stringList_t directoryList;
jdir::read_dir(journalDirectory_, directoryList, false, true, false, true);
- for (directoryListConstItr_t i = directoryList.begin(); i != directoryList.end(); ++i) {
+ for (stringListConstItr_t i = directoryList.begin(); i != directoryList.end(); ++i) {
readJournalFileHeader(*i, fileHeader, headerQueueName);
if (headerQueueName.empty()) {
std::ostringstream oss;
- if (uninitializedJournal_.empty()) {
- oss << "Journal file " << (*i) << " is first uninitialized (not yet written) journal file.";
- journalLogRef_.log(JournalLog::LOG_NOTICE, queueName_, oss.str());
- uninitializedJournal_ = *i;
- } else {
- oss << "Journal file " << (*i) << " is second or greater uninitialized journal file - ignoring";
- journalLogRef_.log(JournalLog::LOG_WARN, queueName_, oss.str());
- }
+ oss << "Journal file " << (*i) << " is uninitialized";
+ journalLogRef_.log(JournalLog::LOG_WARN, queueName_, oss.str());
+ uninitFileList_.push_back(*i);
} else if (headerQueueName.compare(queueName_) != 0) {
std::ostringstream oss;
oss << "Journal file " << (*i) << " belongs to queue \"" << headerQueueName << "\": ignoring";
journalLogRef_.log(JournalLog::LOG_WARN, queueName_, oss.str());
} else {
- JournalFile* jfp = new JournalFile(*i, fileHeader);
- fileNumberMap_[fileHeader._file_number] = jfp;
+ JournalFile* jfp = new JournalFile(*i, fileHeader, queueName_);
+ std::pair<fileNumberMapItr_t, bool> res = fileNumberMap_.insert(
+ std::pair<uint64_t, RecoveredFileData_t*>(fileHeader._file_number, new RecoveredFileData_t(jfp, 0)));
+ if (!res.second) {
+ std::ostringstream oss;
+ oss << "Journal file " << (*i) << " has fid=0x" << std::hex << jfp->getFileSeqNum() << " which already exists for this journal.";
+ throw jexception(oss.str()); // TODO: complete this exception
+ }
if (fileHeader._file_number > highestFileNumber_) {
highestFileNumber_ = fileHeader._file_number;
}
@@ -393,7 +418,7 @@ void RecoveryManager::analyzeJournalFileHeaders(efpIdentity_t& efpIdentity) {
if (fileNumberMap_.empty()) {
journalEmptyFlag_ = true;
} else {
- currentJournalFileConstItr_ = fileNumberMap_.begin();
+ currentJournalFileItr_ = fileNumberMap_.begin();
}
}
@@ -408,7 +433,7 @@ void RecoveryManager::checkFileStreamOk(bool checkEof) {
}
}
-void RecoveryManager::checkJournalAlignment(const std::streampos recordPosition) {
+void RecoveryManager::checkJournalAlignment(const uint64_t start_fid, const std::streampos recordPosition) {
if (recordPosition % QLS_DBLK_SIZE_BYTES != 0) {
std::ostringstream oss;
oss << "Current read pointer not dblk aligned: recordPosition=0x" << std::hex << recordPosition;
@@ -420,12 +445,13 @@ void RecoveryManager::checkJournalAlignment(const std::streampos recordPosition)
if (sblkOffset)
{
std::ostringstream oss1;
- oss1 << std::hex << "Bad record alignment found at fid=0x" << getCurrentFileNumber();
+ oss1 << std::hex << "Bad record alignment found at fid=0x" << start_fid;
oss1 << " offs=0x" << currentPosn << " (likely journal overwrite boundary); " << std::dec;
oss1 << (QLS_SBLK_SIZE_DBLKS - (sblkOffset/QLS_DBLK_SIZE_BYTES)) << " filler record(s) required.";
journalLogRef_.log(JournalLog::LOG_WARN, queueName_, oss1.str());
- std::ofstream outFileStream(getCurrentFileName().c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
+ fileNumberMapConstItr_t fnmItr = fileNumberMap_.find(start_fid);
+ std::ofstream outFileStream(fnmItr->second->journalFilePtr_->getFqFileName().c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
if (!outFileStream.good()) {
throw jexception(jerrno::JERR__FILEIO, getCurrentFileName(), "RecoveryManager", "checkJournalAlignment");
}
@@ -447,7 +473,7 @@ void RecoveryManager::checkJournalAlignment(const std::streampos recordPosition)
throw jexception(jerrno::JERR_RCVM_WRITE, "RecoveryManager", "checkJournalAlignment");
}
std::ostringstream oss2;
- oss2 << std::hex << "Recover phase write: Wrote filler record: fid=0x" << getCurrentFileNumber();
+ oss2 << std::hex << "Recover phase write: Wrote filler record: fid=0x" << start_fid;
oss2 << " offs=0x" << currentPosn;
journalLogRef_.log(JournalLog::LOG_NOTICE, queueName_, oss2.str());
currentPosn = outFileStream.tellp();
@@ -456,16 +482,15 @@ void RecoveryManager::checkJournalAlignment(const std::streampos recordPosition)
std::free(writeBuffer);
journalLogRef_.log(JournalLog::LOG_INFO, queueName_, "Bad record alignment fixed.");
}
- endOffset_ = currentPosn;
+ lastRecord(start_fid, currentPosn);
}
bool RecoveryManager::decodeRecord(jrec& record,
std::size_t& cumulativeSizeRead,
::rec_hdr_t& headerRecord,
- std::streampos& fileOffset)
+ const uint64_t start_fid,
+ const std::streampos recordOffset)
{
- std::streampos start_file_offs = fileOffset;
-
if (highestRecordId_ == 0) {
highestRecordId_ = headerRecord._rid;
} else if (headerRecord._rid - highestRecordId_ < 0x8000000000000000ULL) { // RFC 1982 comparison for unsigned 64-bit
@@ -475,7 +500,7 @@ bool RecoveryManager::decodeRecord(jrec& record,
bool done = false;
while (!done) {
try {
- done = record.decode(headerRecord, &inFileStream_, cumulativeSizeRead);
+ done = record.decode(headerRecord, &inFileStream_, cumulativeSizeRead, recordOffset);
}
catch (const jexception& e) {
if (e.err_code() == jerrno::JERR_JREC_BADRECTAIL) {
@@ -485,11 +510,12 @@ bool RecoveryManager::decodeRecord(jrec& record,
} else {
journalLogRef_.log(JournalLog::LOG_INFO, queueName_, e.what());
}
- checkJournalAlignment(start_file_offs);
+ checkJournalAlignment(start_fid, recordOffset);
return false;
}
if (!done && needNextFile()) {
if (!getNextFile(false)) {
+ checkJournalAlignment(start_fid, recordOffset);
return false;
}
}
@@ -498,11 +524,11 @@ bool RecoveryManager::decodeRecord(jrec& record,
}
std::string RecoveryManager::getCurrentFileName() const {
- return currentJournalFileConstItr_->second->getFqFileName();
+ return currentJournalFileItr_->second->journalFilePtr_->getFqFileName();
}
uint64_t RecoveryManager::getCurrentFileNumber() const {
- return currentJournalFileConstItr_->first;
+ return currentJournalFileItr_->first;
}
bool RecoveryManager::getFile(const uint64_t fileNumber, bool jumpToFirstRecordOffsetFlag) {
@@ -511,8 +537,8 @@ bool RecoveryManager::getFile(const uint64_t fileNumber, bool jumpToFirstRecordO
//std::cout << " f=" << getCurrentFileName() << "]" << std::flush; // DEBUG
inFileStream_.clear(); // clear eof flag, req'd for older versions of c++
}
- currentJournalFileConstItr_ = fileNumberMap_.find(fileNumber);
- if (currentJournalFileConstItr_ == fileNumberMap_.end()) {
+ currentJournalFileItr_ = fileNumberMap_.find(fileNumber);
+ if (currentJournalFileItr_ == fileNumberMap_.end()) {
return false;
}
inFileStream_.open(getCurrentFileName().c_str(), std::ios_base::in | std::ios_base::binary);
@@ -536,7 +562,8 @@ bool RecoveryManager::getNextFile(bool jumpToFirstRecordOffsetFlag) {
if (inFileStream_.is_open()) {
inFileStream_.close();
//std::cout << " .f=" << getCurrentFileName() << "]" << std::flush; // DEBUG
- if (++currentJournalFileConstItr_ == fileNumberMap_.end()) {
+ currentJournalFileItr_->second->completedDblkCount_ = efpFileSize_kib_ * 1024 / QLS_DBLK_SIZE_BYTES;
+ if (++currentJournalFileItr_ == fileNumberMap_.end()) {
return false;
}
inFileStream_.clear(); // clear eof flag, req'd for older versions of c++
@@ -562,13 +589,15 @@ bool RecoveryManager::getNextRecordHeader()
rec_hdr_t h;
bool hdr_ok = false;
- std::streampos file_pos;
+ uint64_t file_id = 0;
+ std::streampos file_pos = 0;
while (!hdr_ok) {
if (needNextFile()) {
if (!getNextFile(true)) {
return false;
}
}
+ file_id = currentJournalFileItr_->second->journalFilePtr_->getFileSeqNum();
file_pos = inFileStream_.tellg();
if (file_pos == std::streampos(-1)) {
std::ostringstream oss;
@@ -587,21 +616,21 @@ bool RecoveryManager::getNextRecordHeader()
}
}
+ uint64_t start_fid = getCurrentFileNumber(); // fid may increment in decode() if record folds over file boundary
switch(h._magic) {
case QLS_ENQ_MAGIC:
{
//std::cout << " 0x" << std::hex << file_pos << ".e.0x" << h._rid << std::dec << std::flush; // DEBUG
if (::rec_hdr_check(&h, QLS_ENQ_MAGIC, QLS_JRNL_VERSION, currentSerial_) != 0) {
- endOffset_ = file_pos;
+ lastRecord(file_id, file_pos);
return false;
}
enq_rec er;
- uint64_t start_fid = getCurrentFileNumber(); // fid may increment in decode() if record folds over file boundary
- if (!decodeRecord(er, cum_size_read, h, file_pos)) {
+ if (!decodeRecord(er, cum_size_read, h, start_fid, file_pos)) {
return false;
}
if (!er.is_transient()) { // Ignore transient msgs
- fileNumberMap_[start_fid]->incrEnqueuedRecordCount();
+ fileNumberMap_[start_fid]->journalFilePtr_->incrEnqueuedRecordCount();
if (er.xid_size()) {
er.get_xid(&xidp);
if (xidp == 0) {
@@ -629,12 +658,11 @@ bool RecoveryManager::getNextRecordHeader()
{
//std::cout << " 0x" << std::hex << file_pos << ".d.0x" << h._rid << std::dec << std::flush; // DEBUG
if (::rec_hdr_check(&h, QLS_DEQ_MAGIC, QLS_JRNL_VERSION, currentSerial_) != 0) {
- endOffset_ = file_pos;
+ lastRecord(file_id, file_pos);
return false;
}
deq_rec dr;
- uint16_t start_fid = getCurrentFileNumber(); // fid may increment in decode() if record folds over file boundary
- if (!decodeRecord(dr, cum_size_read, h, file_pos)) {
+ if (!decodeRecord(dr, cum_size_read, h, start_fid, file_pos)) {
return false;
}
if (dr.xid_size()) {
@@ -655,7 +683,7 @@ bool RecoveryManager::getNextRecordHeader()
} else {
uint64_t enq_fid;
if (enqueueMapRef_.get_remove_pfid(dr.deq_rid(), enq_fid, true) == enq_map::EMAP_OK) { // ignore not found error
- fileNumberMap_[enq_fid]->decrEnqueuedRecordCount();
+ fileNumberMap_[enq_fid]->journalFilePtr_->decrEnqueuedRecordCount();
}
}
}
@@ -664,11 +692,11 @@ bool RecoveryManager::getNextRecordHeader()
{
//std::cout << " 0x" << std::hex << file_pos << ".a.0x" << h._rid << std::dec << std::flush; // DEBUG
if (::rec_hdr_check(&h, QLS_TXA_MAGIC, QLS_JRNL_VERSION, currentSerial_) != 0) {
- endOffset_ = file_pos;
+ lastRecord(file_id, file_pos);
return false;
}
txn_rec ar;
- if (!decodeRecord(ar, cum_size_read, h, file_pos)) {
+ if (!decodeRecord(ar, cum_size_read, h, start_fid, file_pos)) {
return false;
}
// Delete this txn from tmap, unlock any locked records in emap
@@ -680,7 +708,7 @@ bool RecoveryManager::getNextRecordHeader()
txn_data_list_t tdl = transactionMapRef_.get_remove_tdata_list(xid); // tdl will be empty if xid not found
for (tdl_itr_t itr = tdl.begin(); itr != tdl.end(); itr++) {
if (itr->enq_flag_) {
- fileNumberMap_[itr->pfid_]->decrEnqueuedRecordCount();
+ fileNumberMap_[itr->pfid_]->journalFilePtr_->decrEnqueuedRecordCount();
} else {
enqueueMapRef_.unlock(itr->drid_); // ignore not found error
}
@@ -691,11 +719,11 @@ bool RecoveryManager::getNextRecordHeader()
{
//std::cout << " 0x" << std::hex << file_pos << ".c.0x" << h._rid << std::dec << std::flush; // DEBUG
if (::rec_hdr_check(&h, QLS_TXC_MAGIC, QLS_JRNL_VERSION, currentSerial_) != 0) {
- endOffset_ = file_pos;
+ lastRecord(file_id, file_pos);
return false;
}
txn_rec cr;
- if (!decodeRecord(cr, cum_size_read, h, file_pos)) {
+ if (!decodeRecord(cr, cum_size_read, h, start_fid, file_pos)) {
return false;
}
// Delete this txn from tmap, process records into emap
@@ -717,7 +745,7 @@ bool RecoveryManager::getNextRecordHeader()
} else { // txn dequeue
uint64_t enq_fid;
if (enqueueMapRef_.get_remove_pfid(itr->drid_, enq_fid, true) == enq_map::EMAP_OK) // ignore not found error
- fileNumberMap_[enq_fid]->decrEnqueuedRecordCount();
+ fileNumberMap_[enq_fid]->journalFilePtr_->decrEnqueuedRecordCount();
}
}
}
@@ -729,7 +757,9 @@ bool RecoveryManager::getNextRecordHeader()
inFileStream_.ignore(rec_dblks * QLS_DBLK_SIZE_BYTES - sizeof(::rec_hdr_t));
checkFileStreamOk(false);
if (needNextFile()) {
+ file_pos += rec_dblks * QLS_DBLK_SIZE_BYTES;
if (!getNextFile(false)) {
+ lastRecord(start_fid, file_pos);
return false;
}
}
@@ -737,17 +767,36 @@ bool RecoveryManager::getNextRecordHeader()
break;
case 0:
//std::cout << " 0x" << std::hex << file_pos << ".0" << std::dec << std::endl << std::flush; // DEBUG
- checkJournalAlignment(file_pos);
+ checkJournalAlignment(getCurrentFileNumber(), file_pos);
return false;
default:
//std::cout << " 0x" << std::hex << file_pos << ".?" << std::dec << std::endl << std::flush; // DEBUG
// Stop as this is the overwrite boundary.
- checkJournalAlignment(file_pos);
+ checkJournalAlignment(getCurrentFileNumber(), file_pos);
return false;
}
return true;
}
+void RecoveryManager::lastRecord(const uint64_t file_id, const std::streamoff endOffset) {
+ endOffset_ = endOffset;
+ initial_fid_ = file_id;
+ fileNumberMap_[file_id]->completedDblkCount_ = endOffset_ / QLS_DBLK_SIZE_BYTES;
+
+ // Remove any files in fileNumberMap_ beyond initial_fid_
+ fileNumberMapItr_t unwantedFirstItr = fileNumberMap_.find(file_id);
+ if (++unwantedFirstItr != fileNumberMap_.end()) {
+ fileNumberMapItr_t itr = unwantedFirstItr;
+ notNeededFilesList_.push_back(unwantedFirstItr->second->journalFilePtr_->getFqFileName());
+ while (++itr != fileNumberMap_.end()) {
+ notNeededFilesList_.push_back(itr->second->journalFilePtr_->getFqFileName());
+ delete itr->second->journalFilePtr_;
+ delete itr->second;
+ }
+ fileNumberMap_.erase(unwantedFirstItr, fileNumberMap_.end());
+ }
+}
+
bool RecoveryManager::needNextFile() {
if (inFileStream_.is_open()) {
return inFileStream_.eof() || inFileStream_.tellg() >= std::streampos(efpFileSize_kib_ * 1024);
@@ -820,7 +869,7 @@ bool RecoveryManager::readFileHeader() {
currentSerial_ = fhdr._rhdr._serial;
} else {
inFileStream_.close();
- if (currentJournalFileConstItr_ == fileNumberMap_.begin()) {
+ if (currentJournalFileItr_ == fileNumberMap_.begin()) {
journalEmptyFlag_ = true;
}
return false;
@@ -855,9 +904,11 @@ void RecoveryManager::readJournalFileHeader(const std::string& journalFileName,
}
void RecoveryManager::removeEmptyFiles(EmptyFilePool* emptyFilePoolPtr) {
- while (fileNumberMap_.begin()->second->getEnqueuedRecordCount() == 0 && fileNumberMap_.size() > 1) {
-//std::cout << "*** File " << i->first << ": " << i->second << " is empty." << std::endl; // DEBUG
- emptyFilePoolPtr->returnEmptyFile(fileNumberMap_.begin()->second->getFqFileName());
+ while (fileNumberMap_.begin()->second->journalFilePtr_->getEnqueuedRecordCount() == 0 && fileNumberMap_.size() > 1) {
+ RecoveredFileData_t* rfdp = fileNumberMap_.begin()->second;
+ emptyFilePoolPtr->returnEmptyFile(rfdp->journalFilePtr_->getFqFileName());
+ delete rfdp->journalFilePtr_;
+ delete rfdp;
fileNumberMap_.erase(fileNumberMap_.begin()->first);
}
}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.h b/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.h
index 997596938b..e19f92e305 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/RecoveryManager.h
@@ -51,15 +51,21 @@ struct RecoveredRecordData_t {
RecoveredRecordData_t(const uint64_t rid, const uint64_t fid, const std::streampos foffs, bool ptxn);
};
+struct RecoveredFileData_t {
+ JournalFile* journalFilePtr_;
+ uint32_t completedDblkCount_;
+ RecoveredFileData_t(JournalFile* journalFilePtr, const uint32_t completedDblkCount);
+};
+
bool recordIdListCompare(RecoveredRecordData_t a, RecoveredRecordData_t b);
class RecoveryManager
{
protected:
// Types
- typedef std::vector<std::string> directoryList_t;
- typedef directoryList_t::const_iterator directoryListConstItr_t;
- typedef std::map<uint64_t, JournalFile*> fileNumberMap_t;
+ typedef std::vector<std::string> stringList_t;
+ typedef stringList_t::const_iterator stringListConstItr_t;
+ typedef std::map<uint64_t, RecoveredFileData_t*> fileNumberMap_t;
typedef fileNumberMap_t::iterator fileNumberMapItr_t;
typedef fileNumberMap_t::const_iterator fileNumberMapConstItr_t;
typedef std::vector<RecoveredRecordData_t> recordIdList_t;
@@ -74,18 +80,20 @@ protected:
// Initial journal analysis data
fileNumberMap_t fileNumberMap_; ///< File number - JournalFilePtr map
+ stringList_t notNeededFilesList_; ///< Files not needed and to be returned to EFP
+ stringList_t uninitFileList_; ///< File name of uninitialized journal files found during header analysis
bool journalEmptyFlag_; ///< Journal data files empty
std::streamoff firstRecordOffset_; ///< First record offset in ffid
std::streamoff endOffset_; ///< End offset (first byte past last record)
uint64_t highestRecordId_; ///< Highest rid found
uint64_t highestFileNumber_; ///< Highest file number found
bool lastFileFullFlag_; ///< Last file is full
- std::string uninitializedJournal_; ///< File name of uninitialized journal found during header analysis
+ uint64_t initial_fid_; ///< File id where initial write after recovery will occur
// State for recovery of individual enqueued records
uint64_t currentSerial_;
uint32_t efpFileSize_kib_;
- fileNumberMapConstItr_t currentJournalFileConstItr_;
+ fileNumberMapConstItr_t currentJournalFileItr_;
std::string currentFileName_;
std::ifstream inFileStream_;
recordIdList_t recordIdList_;
@@ -121,16 +129,18 @@ public:
protected:
void analyzeJournalFileHeaders(efpIdentity_t& efpIdentity);
void checkFileStreamOk(bool checkEof);
- void checkJournalAlignment(const std::streampos recordPosition);
+ void checkJournalAlignment(const uint64_t start_fid, const std::streampos recordPosition);
bool decodeRecord(jrec& record,
std::size_t& cumulativeSizeRead,
::rec_hdr_t& recordHeader,
- std::streampos& fileOffset);
+ const uint64_t start_fid,
+ const std::streampos recordOffset);
std::string getCurrentFileName() const;
uint64_t getCurrentFileNumber() const;
bool getFile(const uint64_t fileNumber, bool jumpToFirstRecordOffsetFlag);
bool getNextFile(bool jumpToFirstRecordOffsetFlag);
bool getNextRecordHeader();
+ void lastRecord(const uint64_t file_id, const std::streamoff endOffset);
bool needNextFile();
void prepareRecordList();
bool readFileHeader();
diff --git a/qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp b/qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp
index a4882aaa9c..90ca27d082 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/deq_rec.cpp
@@ -181,7 +181,7 @@ deq_rec::encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Ch
}
bool
-deq_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs)
+deq_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start)
{
if (rec_offs == 0)
{
@@ -228,7 +228,7 @@ deq_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs)
assert(!ifsp->fail() && !ifsp->bad());
return false;
}
- check_rec_tail();
+ check_rec_tail(rec_start);
}
ifsp->ignore(rec_size_dblks() * QLS_DBLK_SIZE_BYTES - rec_size());
assert(!ifsp->fail() && !ifsp->bad());
@@ -274,7 +274,7 @@ deq_rec::rec_size() const
}
void
-deq_rec::check_rec_tail() const {
+deq_rec::check_rec_tail(const std::streampos rec_start) const {
Checksum checksum;
checksum.addData((const unsigned char*)&_deq_hdr, sizeof(::deq_hdr_t));
if (_deq_hdr._xidsize > 0) {
@@ -284,7 +284,7 @@ deq_rec::check_rec_tail() const {
uint16_t res = ::rec_tail_check(&_deq_tail, &_deq_hdr._rhdr, cs);
if (res != 0) {
std::stringstream oss;
- oss << std::hex;
+ oss << std::endl << " Record offset: 0x" << std::hex << rec_start;
if (res & ::REC_TAIL_MAGIC_ERR_MASK) {
oss << std::endl << " Magic: expected 0x" << ~_deq_hdr._rhdr._magic << "; found 0x" << _deq_tail._xmagic;
}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/deq_rec.h b/qpid/cpp/src/qpid/linearstore/journal/deq_rec.h
index ead0eed72a..9f55032e76 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/deq_rec.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/deq_rec.h
@@ -49,7 +49,7 @@ public:
void reset(const uint64_t serial, const uint64_t rid, const uint64_t drid, const void* const xidp,
const std::size_t xidlen, const bool txn_coml_commit);
uint32_t encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum);
- bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs);
+ bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start);
inline bool is_txn_coml_commit() const { return ::is_txn_coml_commit(&_deq_hdr); }
inline uint64_t rid() const { return _deq_hdr._rhdr._rid; }
@@ -59,7 +59,7 @@ public:
inline std::size_t data_size() const { return 0; } // This record never carries data
std::size_t xid_size() const;
std::size_t rec_size() const;
- void check_rec_tail() const;
+ void check_rec_tail(const std::streampos rec_start) const;
private:
virtual void clean();
diff --git a/qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp b/qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp
index f95a722308..0fecd90cbf 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/enq_rec.cpp
@@ -218,7 +218,7 @@ enq_rec::encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Ch
}
bool
-enq_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs)
+enq_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start)
{
if (rec_offs == 0)
{
@@ -291,7 +291,7 @@ enq_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs)
assert(!ifsp->fail() && !ifsp->bad());
return false;
}
- check_rec_tail();
+ check_rec_tail(rec_start);
}
ifsp->ignore(rec_size_dblks() * QLS_DBLK_SIZE_BYTES - rec_size());
assert(!ifsp->fail() && !ifsp->bad());
@@ -352,7 +352,7 @@ enq_rec::rec_size(const std::size_t xidsize, const std::size_t dsize, const bool
}
void
-enq_rec::check_rec_tail() const {
+enq_rec::check_rec_tail(const std::streampos rec_start) const {
Checksum checksum;
checksum.addData((const unsigned char*)&_enq_hdr, sizeof(::enq_hdr_t));
if (_enq_hdr._xidsize > 0) {
@@ -365,7 +365,7 @@ enq_rec::check_rec_tail() const {
uint16_t res = ::rec_tail_check(&_enq_tail, &_enq_hdr._rhdr, cs);
if (res != 0) {
std::stringstream oss;
- oss << std::hex;
+ oss << std::endl << " Record offset: 0x" << std::hex << rec_start;
if (res & ::REC_TAIL_MAGIC_ERR_MASK) {
oss << std::endl << " Magic: expected 0x" << ~_enq_hdr._rhdr._magic << "; found 0x" << _enq_tail._xmagic;
}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/enq_rec.h b/qpid/cpp/src/qpid/linearstore/journal/enq_rec.h
index 1655e2cc4d..d85cde42f5 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/enq_rec.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/enq_rec.h
@@ -51,7 +51,7 @@ public:
void reset(const uint64_t serial, const uint64_t rid, const void* const dbuf, const std::size_t dlen,
const void* const xidp, const std::size_t xidlen, const bool transient, const bool external);
uint32_t encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum);
- bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs);
+ bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start);
std::size_t get_xid(void** const xidpp);
std::size_t get_data(void** const datapp);
@@ -63,7 +63,7 @@ public:
std::size_t rec_size() const;
static std::size_t rec_size(const std::size_t xidsize, const std::size_t dsize, const bool external);
inline uint64_t rid() const { return _enq_hdr._rhdr._rid; }
- void check_rec_tail() const;
+ void check_rec_tail(const std::streampos rec_start) const;
private:
virtual void clean();
diff --git a/qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp b/qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp
index 55bac4a2e5..ab367754d5 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/jcntl.cpp
@@ -21,6 +21,7 @@
#include "qpid/linearstore/journal/jcntl.h"
+#include <iomanip>
#include "qpid/linearstore/journal/data_tok.h"
#include "qpid/linearstore/journal/JournalLog.h"
@@ -90,7 +91,7 @@ jcntl::initialize(EmptyFilePool* efpp,
_linearFileController.finalize();
_jdir.clear_dir(); // Clear any existing journal files
_linearFileController.initialize(_jdir.dirname(), efpp, 0ULL);
- _linearFileController.pullEmptyFileFromEfp();
+ _linearFileController.getNextJournalFile();
_wmgr.initialize(cbp, wcache_pgsize_sblks, wcache_num_pages, QLS_WMGR_MAXDTOKPP, QLS_WMGR_MAXWAITUS);
_init_flag = true;
}
@@ -120,6 +121,9 @@ jcntl::recover(EmptyFilePoolManager* efpmp,
_jrnl_log.log(/*LOG_DEBUG*/JournalLog::LOG_INFO, _jid, _recoveryManager.toLog(_jid, 5));
_linearFileController.initialize(_jdir.dirname(), _emptyFilePoolPtr, _recoveryManager.getHighestFileNumber());
_recoveryManager.setLinearFileControllerJournals(&qpid::linearstore::journal::LinearFileController::addJournalFile, &_linearFileController);
+ if (_recoveryManager.isLastFileFull()) {
+ _linearFileController.getNextJournalFile();
+ }
_wmgr.initialize(cbp, wcache_pgsize_sblks, wcache_num_pages, QLS_WMGR_MAXDTOKPP, QLS_WMGR_MAXWAITUS,
(_recoveryManager.isLastFileFull() ? 0 : _recoveryManager.getEndOffset()));
@@ -316,6 +320,20 @@ jcntl::getLinearFileControllerRef() {
return _linearFileController;
}
+// static
+std::string
+jcntl::str2hexnum(const std::string& str) {
+ if (str.empty()) {
+ return "<null>";
+ }
+ std::ostringstream oss;
+ oss << "(" << str.size() << ")0x" << std::hex;
+ for (unsigned i=str.size(); i>0; --i) {
+ oss << std::setfill('0') << std::setw(2) << (uint16_t)(uint8_t)str[i-1];
+ }
+ return oss.str();
+}
+
iores
jcntl::flush(const bool block_till_aio_cmpl)
{
diff --git a/qpid/cpp/src/qpid/linearstore/journal/jcntl.h b/qpid/cpp/src/qpid/linearstore/journal/jcntl.h
index 2db0e707a7..94c00d2fab 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/jcntl.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/jcntl.h
@@ -537,6 +537,8 @@ public:
inline virtual void instr_incr_outstanding_aio_cnt() {}
inline virtual void instr_decr_outstanding_aio_cnt() {}
+ static std::string str2hexnum(const std::string& str);
+
protected:
static bool _init;
static bool init_statics();
diff --git a/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp b/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp
index 01c432d37b..8765396b31 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/jerrno.cpp
@@ -167,8 +167,8 @@ jerrno::__init()
_err_map[JERR_LFCR_SEQNUMNOTFOUND] = "JERR_LFCR_SEQNUMNOTFOUND: File sequence number not found";
// class jrec, enq_rec, deq_rec, txn_rec
- _err_map[JERR_JREC_BADRECHDR] = "JERR_JREC_BADRECHDR: Invalid data record header.";
- _err_map[JERR_JREC_BADRECTAIL] = "JERR_JREC_BADRECTAIL: Invalid data record tail.";
+ _err_map[JERR_JREC_BADRECHDR] = "JERR_JREC_BADRECHDR: Invalid record header.";
+ _err_map[JERR_JREC_BADRECTAIL] = "JERR_JREC_BADRECTAIL: Invalid record tail.";
// class wmgr
_err_map[JERR_WMGR_BADPGSTATE] = "JERR_WMGR_BADPGSTATE: Page buffer in illegal state for operation.";
diff --git a/qpid/cpp/src/qpid/linearstore/journal/jrec.h b/qpid/cpp/src/qpid/linearstore/journal/jrec.h
index 7645e646f6..cad0e5d7a2 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/jrec.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/jrec.h
@@ -98,7 +98,7 @@ public:
* \returns Number of data-blocks encoded.
*/
virtual uint32_t encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum) = 0;
- virtual bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs) = 0;
+ virtual bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start) = 0;
virtual std::string& str(std::string& str) const = 0;
virtual std::size_t data_size() const = 0;
diff --git a/qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp b/qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp
index 1368fd4be2..298ab608b1 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/txn_rec.cpp
@@ -176,7 +176,7 @@ txn_rec::encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Ch
}
bool
-txn_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs)
+txn_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start)
{
if (rec_offs == 0)
{
@@ -218,7 +218,7 @@ txn_rec::decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs)
assert(!ifsp->fail() && !ifsp->bad());
return false;
}
- check_rec_tail();
+ check_rec_tail(rec_start);
}
ifsp->ignore(rec_size_dblks() * QLS_DBLK_SIZE_BYTES - rec_size());
assert(!ifsp->fail() && !ifsp->bad());
@@ -266,7 +266,7 @@ txn_rec::rec_size() const
}
void
-txn_rec::check_rec_tail() const {
+txn_rec::check_rec_tail(const std::streampos rec_start) const {
Checksum checksum;
checksum.addData((const unsigned char*)&_txn_hdr, sizeof(::txn_hdr_t));
if (_txn_hdr._xidsize > 0) {
@@ -276,7 +276,7 @@ txn_rec::check_rec_tail() const {
uint16_t res = ::rec_tail_check(&_txn_tail, &_txn_hdr._rhdr, cs);
if (res != 0) {
std::stringstream oss;
- oss << std::hex;
+ oss << std::endl << " Record offset: 0x" << std::hex << rec_start;
if (res & ::REC_TAIL_MAGIC_ERR_MASK) {
oss << std::endl << " Magic: expected 0x" << ~_txn_hdr._rhdr._magic << "; found 0x" << _txn_tail._xmagic;
}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/txn_rec.h b/qpid/cpp/src/qpid/linearstore/journal/txn_rec.h
index daca16d9d4..4552071595 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/txn_rec.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/txn_rec.h
@@ -49,7 +49,7 @@ public:
void reset(const bool commitFlag, const uint64_t serial, const uint64_t rid, const void* const xidp,
const std::size_t xidlen);
uint32_t encode(void* wptr, uint32_t rec_offs_dblks, uint32_t max_size_dblks, Checksum& checksum);
- bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs);
+ bool decode(::rec_hdr_t& h, std::ifstream* ifsp, std::size_t& rec_offs, const std::streampos rec_start);
std::size_t get_xid(void** const xidpp);
std::string& str(std::string& str) const;
@@ -57,7 +57,7 @@ public:
std::size_t xid_size() const;
std::size_t rec_size() const;
inline uint64_t rid() const { return _txn_hdr._rhdr._rid; }
- void check_rec_tail() const;
+ void check_rec_tail(const std::streampos rec_start) const;
private:
virtual void clean();
diff --git a/qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp b/qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp
index c246837a8d..7c590713f5 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp
+++ b/qpid/cpp/src/qpid/linearstore/journal/wmgr.cpp
@@ -30,8 +30,6 @@
#include "qpid/linearstore/journal/LinearFileController.h"
#include "qpid/linearstore/journal/utils/file_hdr.h"
-//#include <iostream> // DEBUG
-
namespace qpid {
namespace linearstore {
namespace journal {
@@ -49,7 +47,7 @@ wmgr::wmgr(jcntl* jc,
_deq_busy(false),
_abort_busy(false),
_commit_busy(false),
- _txn_pending_set()
+ _txn_pending_map()
{}
wmgr::wmgr(jcntl* jc,
@@ -67,7 +65,7 @@ wmgr::wmgr(jcntl* jc,
_deq_busy(false),
_abort_busy(false),
_commit_busy(false),
- _txn_pending_set()
+ _txn_pending_map()
{}
wmgr::~wmgr()
@@ -281,6 +279,7 @@ wmgr::dequeue(data_tok* dtokp,
_deq_busy = true;
}
//std::cout << "---+++ wmgr::dequeue() DEQ rid=0x" << std::hex << rid << " drid=0x" << dequeue_rid << " " << std::dec << std::flush; // DEBUG
+ std::string xid((const char*)xid_ptr, xid_len);
bool done = false;
Checksum checksum;
while (!done)
@@ -292,9 +291,27 @@ wmgr::dequeue(data_tok* dtokp,
uint32_t ret = _deq_rec.encode(wptr, data_offs_dblks,
(_cache_pgsize_sblks * QLS_SBLK_SIZE_DBLKS) - _pg_offset_dblks, checksum);
- // Remember fid which contains the record header in case record is split over several files
if (data_offs_dblks == 0) {
- dtokp->set_fid(_lfc.getCurrentFileSeqNum());
+ uint64_t fid;
+ short eres = _emap.get_pfid(dtokp->dequeue_rid(), fid);
+ if (eres == enq_map::EMAP_OK) {
+ dtokp->set_fid(fid);
+ } else if (xid_len > 0) {
+ txn_data_list_t tdl = _tmap.get_tdata_list(xid);
+ bool found = false;
+ for (tdl_const_itr_t i=tdl.begin(); i!=tdl.end() && !found; ++i) {
+ if (i->rid_ == dtokp->dequeue_rid()) {
+ found = true;
+ dtokp->set_fid(i->pfid_);
+ break;
+ }
+ }
+ if (!found) {
+ throw jexception("rid found in neither emap nor tmap, transactional");
+ }
+ } else {
+ throw jexception("rid not found in emap, non-transactional");
+ }
}
_pg_offset_dblks += ret;
_cached_offset_dblks += ret;
@@ -325,7 +342,7 @@ wmgr::dequeue(data_tok* dtokp,
if (eres == enq_map::EMAP_RID_NOT_FOUND)
{
std::ostringstream oss;
- oss << std::hex << "rid=0x" << rid;
+ oss << std::hex << "emap: rid=0x" << rid;
throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "dequeue");
}
if (eres == enq_map::EMAP_LOCKED)
@@ -335,10 +352,6 @@ wmgr::dequeue(data_tok* dtokp,
throw jexception(jerrno::JERR_MAP_LOCKED, oss.str(), "wmgr", "dequeue");
}
}
-//std::cout << "[0x" << std::hex << _lfc.getEnqueuedRecordCount(fid) << std::dec << std::flush; // DEBUG
-//try {
- _lfc.decrEnqueuedRecordCount(fid);
-//} catch (std::exception& e) { std::cout << "***OOPS*** " << e.what() << " cfid=" << _lfc.getCurrentFileSeqNum() << " fid=" << fid << std::flush; throw; }
}
done = true;
@@ -427,14 +440,16 @@ wmgr::abort(data_tok* dtokp,
// Delete this txn from tmap, unlock any locked records in emap
std::string xid((const char*)xid_ptr, xid_len);
txn_data_list_t tdl = _tmap.get_remove_tdata_list(xid); // tdl will be empty if xid not found
+ fidl_t fidl;
for (tdl_itr_t itr = tdl.begin(); itr != tdl.end(); itr++)
{
if (!itr->enq_flag_)
_emap.unlock(itr->drid_); // ignore rid not found error
- if (itr->enq_flag_)
- _lfc.decrEnqueuedRecordCount(itr->pfid_);
+ if (itr->enq_flag_) {
+ fidl.push_back(itr->pfid_);
+ }
}
- std::pair<std::set<std::string>::iterator, bool> res = _txn_pending_set.insert(xid);
+ std::pair<pending_txn_map_itr_t, bool> res = _txn_pending_map.insert(std::pair<std::string, fidl_t>(xid, fidl));
if (!res.second)
{
std::ostringstream oss;
@@ -526,6 +541,7 @@ wmgr::commit(data_tok* dtokp,
// Delete this txn from tmap, process records into emap
std::string xid((const char*)xid_ptr, xid_len);
txn_data_list_t tdl = _tmap.get_remove_tdata_list(xid); // tdl will be empty if xid not found
+ fidl_t fidl;
for (tdl_itr_t itr = tdl.begin(); itr != tdl.end(); itr++)
{
if (itr->enq_flag_) // txn enqueue
@@ -547,20 +563,20 @@ wmgr::commit(data_tok* dtokp,
if (eres == enq_map::EMAP_RID_NOT_FOUND)
{
std::ostringstream oss;
- oss << std::hex << "rid=0x" << rid;
- throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "dequeue");
+ oss << std::hex << "emap: rid=0x" << itr->drid_;
+ throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "commit");
}
if (eres == enq_map::EMAP_LOCKED)
{
std::ostringstream oss;
- oss << std::hex << "rid=0x" << rid;
- throw jexception(jerrno::JERR_MAP_LOCKED, oss.str(), "wmgr", "dequeue");
+ oss << std::hex << "rid=0x" << itr->drid_;
+ throw jexception(jerrno::JERR_MAP_LOCKED, oss.str(), "wmgr", "commit");
}
}
- _lfc.decrEnqueuedRecordCount(fid);
+ fidl.push_back(fid);
}
}
- std::pair<std::set<std::string>::iterator, bool> res = _txn_pending_set.insert(xid);
+ std::pair<pending_txn_map_itr_t, bool> res = _txn_pending_map.insert(std::pair<std::string, fidl_t>(xid, fidl));
if (!res.second)
{
std::ostringstream oss;
@@ -695,7 +711,7 @@ wmgr::get_next_file()
{
_pg_cntr = 0;
//std::cout << "&&&&& wmgr::get_next_file(): " << status_str() << std::flush << std::endl; // DEBUG
- _lfc.pullEmptyFileFromEfp();
+ _lfc.getNextJournalFile();
}
int32_t
@@ -757,7 +773,7 @@ wmgr::get_events(timespec* const timeout,
data_tok* dtokp = pcbp->_pdtokl->at(k);
if (dtokp->decr_pg_cnt() == 0)
{
- std::set<std::string>::iterator it;
+ pending_txn_map_itr_t it;
switch (dtokp->wstate())
{
case data_tok::ENQ_SUBM:
@@ -770,6 +786,9 @@ wmgr::get_events(timespec* const timeout,
_tmap.set_aio_compl(dtokp->xid(), dtokp->rid());
break;
case data_tok::DEQ_SUBM:
+ if (!dtokp->has_xid()) {
+ _lfc.decrEnqueuedRecordCount(dtokp->fid());
+ }
dtokl.push_back(dtokp);
tot_data_toks++;
dtokp->set_wstate(data_tok::DEQ);
@@ -781,31 +800,35 @@ wmgr::get_events(timespec* const timeout,
dtokl.push_back(dtokp);
tot_data_toks++;
dtokp->set_wstate(data_tok::ABORTED);
- it = _txn_pending_set.find(dtokp->xid());
- if (it == _txn_pending_set.end())
+ it = _txn_pending_map.find(dtokp->xid());
+ if (it == _txn_pending_map.end())
{
std::ostringstream oss;
- oss << std::hex << "_txn_pending_set: abort xid=\"";
- oss << dtokp->xid() << "\"";
- throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr",
- "get_events");
+ oss << std::hex << "_txn_pending_set: abort xid=\""
+ << qpid::linearstore::journal::jcntl::str2hexnum(dtokp->xid()) << "\"";
+ throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "get_events");
+ }
+ for (fidl_itr_t i=it->second.begin(); i!=it->second.end(); ++i) {
+ _lfc.decrEnqueuedRecordCount(*i);
}
- _txn_pending_set.erase(it);
+ _txn_pending_map.erase(it);
break;
case data_tok::COMMIT_SUBM:
dtokl.push_back(dtokp);
tot_data_toks++;
dtokp->set_wstate(data_tok::COMMITTED);
- it = _txn_pending_set.find(dtokp->xid());
- if (it == _txn_pending_set.end())
+ it = _txn_pending_map.find(dtokp->xid());
+ if (it == _txn_pending_map.end())
{
std::ostringstream oss;
- oss << std::hex << "_txn_pending_set: commit xid=\"";
- oss << dtokp->xid() << "\"";
- throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr",
- "get_events");
+ oss << std::hex << "_txn_pending_set: commit xid=\""
+ << qpid::linearstore::journal::jcntl::str2hexnum(dtokp->xid()) << "\"";
+ throw jexception(jerrno::JERR_MAP_NOTFOUND, oss.str(), "wmgr", "get_events");
+ }
+ for (fidl_itr_t i=it->second.begin(); i!=it->second.end(); ++i) {
+ _lfc.decrEnqueuedRecordCount(*i);
}
- _txn_pending_set.erase(it);
+ _txn_pending_map.erase(it);
break;
case data_tok::ENQ_PART:
case data_tok::DEQ_PART:
@@ -858,8 +881,8 @@ wmgr::is_txn_synced(const std::string& xid)
if (_tmap.is_txn_synced(xid) == txn_map::TMAP_NOT_SYNCED)
return false;
// Check for outstanding commit/aborts
- std::set<std::string>::iterator it = _txn_pending_set.find(xid);
- return it == _txn_pending_set.end();
+ pending_txn_map_itr_t it = _txn_pending_map.find(xid);
+ return it == _txn_pending_map.end();
}
void
@@ -871,7 +894,6 @@ wmgr::initialize(aio_callback* const cbp,
pmgr::initialize(cbp, wcache_pgsize_sblks, wcache_num_pages);
wmgr::clean();
_page_cb_arr[0]._state = IN_USE;
- _ddtokl.clear();
_cached_offset_dblks = 0;
_enq_busy = false;
}
diff --git a/qpid/cpp/src/qpid/linearstore/journal/wmgr.h b/qpid/cpp/src/qpid/linearstore/journal/wmgr.h
index 8837e51e97..8eaa2364ad 100644
--- a/qpid/cpp/src/qpid/linearstore/journal/wmgr.h
+++ b/qpid/cpp/src/qpid/linearstore/journal/wmgr.h
@@ -22,9 +22,11 @@
#ifndef QPID_LINEARSTORE_JOURNAL_WMGR_H
#define QPID_LINEARSTORE_JOURNAL_WMGR_H
+#include <deque>
+#include <map>
#include "qpid/linearstore/journal/enums.h"
#include "qpid/linearstore/journal/pmgr.h"
-#include <set>
+#include <vector>
namespace qpid {
namespace linearstore {
@@ -51,11 +53,15 @@ class LinearFileController;
class wmgr : public pmgr
{
private:
+ typedef std::vector<uint64_t> fidl_t;
+ typedef fidl_t::iterator fidl_itr_t;
+ typedef std::map<std::string, fidl_t> pending_txn_map_t;
+ typedef pending_txn_map_t::iterator pending_txn_map_itr_t;
+
LinearFileController& _lfc; ///< Linear File Controller ref
uint32_t _max_dtokpp; ///< Max data writes per page
uint32_t _max_io_wait_us; ///< Max wait in microseconds till submit
uint32_t _cached_offset_dblks; ///< Amount of unwritten data in page (dblocks)
- std::deque<data_tok*> _ddtokl; ///< Deferred dequeue data_tok list
// TODO: Convert _enq_busy etc into a proper threadsafe lock
// TODO: Convert to enum? Are these encodes mutually exclusive?
@@ -70,7 +76,7 @@ private:
enq_rec _enq_rec; ///< Enqueue record used for encoding/decoding
deq_rec _deq_rec; ///< Dequeue record used for encoding/decoding
txn_rec _txn_rec; ///< Transaction record used for encoding/decoding
- std::set<std::string> _txn_pending_set; ///< Set containing xids of pending commits/aborts
+ pending_txn_map_t _txn_pending_map; ///< Set containing xids of pending commits/aborts
public:
wmgr(jcntl* jc,
diff --git a/qpid/cpp/src/qpid/log/Logger.cpp b/qpid/cpp/src/qpid/log/Logger.cpp
index 8dd970c3b9..7b1e22f80c 100644
--- a/qpid/cpp/src/qpid/log/Logger.cpp
+++ b/qpid/cpp/src/qpid/log/Logger.cpp
@@ -106,7 +106,7 @@ void Logger::log(const Statement& s, const std::string& msg) {
os << s.file << ":";
if (flags&LINE)
os << dec << s.line << ":";
- if (flags&FUNCTION)
+ if ((flags&FUNCTION) && s.function)
os << s.function << ":";
if (flags & (FILE|LINE|FUNCTION))
os << " ";
diff --git a/qpid/cpp/src/qpid/log/Statement.cpp b/qpid/cpp/src/qpid/log/Statement.cpp
index e91756cb9a..86b069fd91 100644
--- a/qpid/cpp/src/qpid/log/Statement.cpp
+++ b/qpid/cpp/src/qpid/log/Statement.cpp
@@ -144,54 +144,33 @@ void Statement::log(const std::string& message) {
Statement::Initializer::Initializer(Statement& s) : statement(s) {
- // QPID-3891
+ // QPID-3891:
// From the given BOOST_CURRENT_FUNCTION name extract only the
// namespace-qualified-functionName, skipping return and calling args.
// Given:
// <possible return value type> qpid::name::space::Function(args)
// Return:
// "qpid::name::space::Function".
- if (s.function != NULL) {
- bool foundOParen(false);
- const char * opPtr;
- for (opPtr = s.function; *opPtr != '\0'; opPtr++) {
- if (*opPtr == '(') {
- foundOParen = true;
- break;
- }
- }
-
- if (foundOParen) {
- const char * bPtr = opPtr;
- for (bPtr = opPtr; bPtr > s.function; bPtr--) {
- if (bPtr[-1] == ' ') {
- break;
- }
- }
-
- size_t nStoreSize = opPtr - bPtr;
- if (nStoreSize > 0) {
- // Note: the struct into which this name is stored
- // is static and is never deleted.
- char * nStore = new char[nStoreSize + 1];
- std::copy (bPtr, opPtr, nStore);
- nStore[nStoreSize] = '\0';
-
- s.function = nStore;
- } else {
- // Ignore zero length name
- }
- } else {
- // No name found - do nothing
- }
- } else {
- // no function-name pointer to process
+ if (s.function) {
+ const char* end = s.function + strlen(s.function);
+ const char* fEnd = std::find(s.function, end, '(');
+ typedef std::reverse_iterator<const char*> Reverse;
+ const char* fBegin = find(Reverse(fEnd), Reverse(s.function), ' ').base();
+ size_t n = fEnd - fBegin;
+ char* name = new char[n+1];
+ std::copy(fBegin, fEnd, name);
+ name[n] = '\0';
+ s.function = name;
}
-
Statement::categorize(s);
Logger::instance().add(s);
}
+Statement::Initializer::~Initializer() {
+ delete[] const_cast<char*>(statement.function);
+ statement.function = 0;
+}
+
namespace {
const char* names[LevelTraits::COUNT] = {
diff --git a/qpid/cpp/src/qpid/log/Statement.h b/qpid/cpp/src/qpid/log/Statement.h
index 20fd3745b6..410ffaaa3d 100644
--- a/qpid/cpp/src/qpid/log/Statement.h
+++ b/qpid/cpp/src/qpid/log/Statement.h
@@ -114,6 +114,7 @@ struct Statement {
struct Initializer {
QPID_COMMON_EXTERN Initializer(Statement& s);
+ QPID_COMMON_EXTERN ~Initializer();
Statement& statement;
};
};
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
index 07367b8aa8..4230a0d644 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
@@ -819,6 +819,11 @@ qpid::sys::Codec& ConnectionContext::getCodec()
return *this;
}
+const qpid::messaging::ConnectionOptions* ConnectionContext::getOptions()
+{
+ return this;
+}
+
std::size_t ConnectionContext::decode(const char* buffer, std::size_t size)
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h
index 2b5e85a6f5..75afeba46a 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h
@@ -102,6 +102,7 @@ class ConnectionContext : public qpid::sys::ConnectionCodec, public qpid::messag
void activateOutput();
qpid::sys::Codec& getCodec();
+ const qpid::messaging::ConnectionOptions* getOptions();
//ConnectionCodec interface:
std::size_t decode(const char* buffer, std::size_t size);
std::size_t encode(char* buffer, std::size_t size);
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp b/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp
index a62a553d90..953e989f5f 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp
@@ -20,6 +20,7 @@
*/
#include "SslTransport.h"
#include "TransportContext.h"
+#include "qpid/messaging/ConnectionOptions.h"
#include "qpid/sys/ssl/SslSocket.h"
#include "qpid/sys/AsynchIO.h"
#include "qpid/sys/ConnectionCodec.h"
@@ -52,7 +53,14 @@ struct StaticInit
}
-SslTransport::SslTransport(TransportContext& c, boost::shared_ptr<Poller> p) : context(c), connector(0), aio(0), poller(p) {}
+SslTransport::SslTransport(TransportContext& c, boost::shared_ptr<Poller> p) : context(c), connector(0), aio(0), poller(p)
+{
+ const ConnectionOptions* options = context.getOptions();
+ if (options->sslCertName != "") {
+ QPID_LOG(debug, "ssl-cert-name = " << options->sslCertName);
+ socket.setCertName(options->sslCertName);
+ }
+}
void SslTransport::connect(const std::string& host, const std::string& port)
{
diff --git a/qpid/cpp/src/qpid/messaging/amqp/TransportContext.h b/qpid/cpp/src/qpid/messaging/amqp/TransportContext.h
index 57192b5976..3ff353c19c 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/TransportContext.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/TransportContext.h
@@ -26,6 +26,8 @@ namespace sys {
class Codec;
}
namespace messaging {
+class ConnectionOptions;
+
namespace amqp {
/**
@@ -38,6 +40,7 @@ class TransportContext
public:
virtual ~TransportContext() {}
virtual qpid::sys::Codec& getCodec() = 0;
+ virtual const qpid::messaging::ConnectionOptions* getOptions() = 0;
virtual void closed() = 0;
virtual void opened() = 0;
private:
diff --git a/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp b/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp
index a733ece74c..00fd96b6ef 100644
--- a/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp
+++ b/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp
@@ -182,15 +182,19 @@ void SslAsynchIO::notifyPendingWrite() {
}
void SslAsynchIO::queueWriteClose() {
- if (state == Negotiating) {
- // Never got going, so don't bother trying to close SSL down orderly.
+ {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ if (state == Negotiating) {
+ // Never got going, so don't bother trying to close SSL down orderly.
+ state = ShuttingDown;
+ aio->queueWriteClose();
+ return;
+ }
+ if (state == ShuttingDown)
+ return;
state = ShuttingDown;
- aio->queueWriteClose();
- return;
}
- state = ShuttingDown;
-
DWORD shutdown = SCHANNEL_SHUTDOWN;
SecBuffer shutBuff;
shutBuff.cbBuffer = sizeof(DWORD);
diff --git a/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h b/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h
index f80285c305..aab5c0021e 100644
--- a/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h
+++ b/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h
@@ -26,6 +26,7 @@
#include "qpid/sys/IntegerTypes.h"
#include "qpid/sys/Poller.h"
#include "qpid/CommonImportExport.h"
+#include "qpid/sys/Mutex.h"
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <windows.h>
@@ -86,6 +87,7 @@ protected:
// AsynchIO layer below that's actually doing the I/O
qpid::sys::AsynchIO *aio;
+ Mutex lock;
// Track what the state of the SSL session is. Have to know when it's
// time to notify the upper layer that the session is up, and also to
diff --git a/qpid/cpp/src/qpid/sys/windows/SslCredential.cpp b/qpid/cpp/src/qpid/sys/windows/SslCredential.cpp
new file mode 100644
index 0000000000..667f0f1ef0
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/windows/SslCredential.cpp
@@ -0,0 +1,273 @@
+/*
+ *
+ * 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 <string>
+#include <windows.h>
+#include "qpid/Msg.h"
+#include "qpid/log/Logger.h"
+#include "qpid/sys/windows/check.h"
+#include "qpid/sys/windows/util.h"
+#include "qpid/sys/windows/SslCredential.h"
+
+
+namespace qpid {
+namespace sys {
+namespace windows {
+
+
+SslCredential::SslCredential() : certStore(0), cert(0)
+{
+ SecInvalidateHandle(&credHandle);
+ memset(&cred, 0, sizeof(cred));
+ cred.dwVersion = SCHANNEL_CRED_VERSION;
+ cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS;
+}
+
+SslCredential::~SslCredential()
+{
+ if (SecIsValidHandle(&credHandle))
+ ::FreeCredentialsHandle(&credHandle);
+ if (cert)
+ ::CertFreeCertificateContext(cert);
+ if (certStore)
+ ::CertCloseStore(certStore, CERT_CLOSE_STORE_FORCE_FLAG);
+}
+
+bool SslCredential::load(const std::string& certName)
+{
+ cert = findCertificate(certName);
+ if (cert != NULL) {
+ // assign the certificate into the credentials
+ cred.paCred = &cert;
+ cred.cCreds = 1;
+ }
+
+ SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL,
+ UNISP_NAME,
+ SECPKG_CRED_OUTBOUND,
+ NULL,
+ &cred,
+ NULL,
+ NULL,
+ &credHandle,
+ &credExpiry);
+ if (status != SEC_E_OK)
+ throw QPID_WINDOWS_ERROR(status);
+
+ return (cert != NULL);
+}
+
+CredHandle SslCredential::handle()
+{
+ return credHandle;
+}
+
+std::string SslCredential::error()
+{
+ // Certificate needed after all. Return main error and log additional context
+ if (!loadError.logMessage.empty())
+ QPID_LOG(warning, loadError.logMessage);
+ return loadError.error;
+}
+
+void SslCredential::loadPrivCertStore()
+{
+ // Get a handle to the system store or pkcs#12 file
+ qpid::sys::ssl::SslOptions& opts = qpid::sys::ssl::SslOptions::global;
+ if (opts.certFilename.empty()) {
+ // opening a system store, names are not case sensitive
+ std::string store = opts.certStore.empty() ? "my" : opts.certStore;
+ std::transform(store.begin(), store.end(), store.begin(), ::tolower);
+ // map confusing GUI name to actual registry store name
+ if (store == "personal")
+ store = "my";
+ certStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, NULL,
+ CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG |
+ CERT_SYSTEM_STORE_CURRENT_USER, store.c_str());
+ if (!certStore) {
+ HRESULT status = GetLastError();
+ loadError.set(Msg() << "Could not open system certificate store: " << store, status);
+ return;
+ }
+ QPID_LOG(debug, "SslConnector using certifcates from system store: " << store);
+ } else {
+ // opening the store from file and populating it with a private key
+ HANDLE certFileHandle = NULL;
+ certFileHandle = CreateFile(opts.certFilename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (INVALID_HANDLE_VALUE == certFileHandle) {
+ HRESULT status = GetLastError();
+ loadError.set(Msg() << "Failed to open the file holding the private key: " << opts.certFilename, status);
+ return;
+ }
+ std::vector<BYTE> certEncoded;
+ DWORD certEncodedSize = 0L;
+ const DWORD fileSize = GetFileSize(certFileHandle, NULL);
+ if (INVALID_FILE_SIZE != fileSize) {
+ certEncoded.resize(fileSize);
+ bool result = false;
+ result = ReadFile(certFileHandle, &certEncoded[0],
+ fileSize,
+ &certEncodedSize,
+ NULL);
+ if (!result) {
+ // the read failed, return the error as an HRESULT
+ HRESULT status = GetLastError();
+ CloseHandle(certFileHandle);
+ loadError.set(Msg() << "Reading the private key from file failed " << opts.certFilename, status);
+ return;
+ }
+ }
+ else {
+ HRESULT status = GetLastError();
+ loadError.set(Msg() << "Unable to read the certificate file " << opts.certFilename, status);
+ return;
+ }
+ CloseHandle(certFileHandle);
+
+ CRYPT_DATA_BLOB blobData;
+ blobData.cbData = certEncodedSize;
+ blobData.pbData = &certEncoded[0];
+
+ // get passwd from file and convert to null terminated wchar_t (Windows UCS2)
+ std::string passwd = getPasswd(opts.certPasswordFile);
+ if (loadError.pending())
+ return;
+ int pwlen = passwd.length();
+ std::vector<wchar_t> pwUCS2(pwlen + 1, L'\0');
+ int nwc = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, passwd.data(), pwlen, &pwUCS2[0], pwlen);
+ if (!nwc) {
+ HRESULT status = GetLastError();
+ loadError.set("Error converting password from UTF8", status);
+ return;
+ }
+
+ certStore = PFXImportCertStore(&blobData, &pwUCS2[0], 0);
+ if (certStore == NULL) {
+ HRESULT status = GetLastError();
+ loadError.set("Failed to open the certificate store", status);
+ return;
+ }
+ QPID_LOG(debug, "SslConnector using certificate from pkcs#12 file: " << opts.certFilename);
+ }
+}
+
+
+PCCERT_CONTEXT SslCredential::findCertificate(const std::string& name)
+{
+ loadPrivCertStore();
+ if (loadError.pending())
+ return NULL;
+
+ // search for the certificate by Friendly Name
+ PCCERT_CONTEXT tmpctx = NULL;
+ while (tmpctx = CertEnumCertificatesInStore(certStore, tmpctx)) {
+ DWORD len = CertGetNameString(tmpctx, CERT_NAME_FRIENDLY_DISPLAY_TYPE,
+ 0, NULL, NULL, 0);
+ if (len == 1)
+ continue;
+ std::vector<char> ctxname(len);
+ CertGetNameString(tmpctx, CERT_NAME_FRIENDLY_DISPLAY_TYPE,
+ 0, NULL, &ctxname[0], len);
+ bool found = !name.compare(&ctxname[0]);
+ if (found)
+ break;
+ }
+
+ // verify whether some certificate has been found
+ if (tmpctx == NULL) {
+ loadError.set(Msg() << "Client SSL/TLS certificate not found in the certificate store for name " << name,
+ "client certificate not found");
+ }
+ return tmpctx;
+}
+
+
+std::string SslCredential::getPasswd(const std::string& filename)
+{
+ std::string passwd;
+ if (filename == "")
+ return passwd;
+
+ HANDLE pwfHandle = CreateFile(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (INVALID_HANDLE_VALUE == pwfHandle) {
+ HRESULT status = GetLastError();
+ loadError.set(Msg() << "Failed to open the password file: " << filename, status);
+ return passwd;
+ }
+
+ const DWORD fileSize = GetFileSize(pwfHandle, NULL);
+ if (fileSize == INVALID_FILE_SIZE) {
+ CloseHandle(pwfHandle);
+ loadError.set("", "Cannot read password file");
+ return passwd;
+ }
+
+ std::vector<char> pwbuf;
+ pwbuf.resize(fileSize);
+ DWORD nbytes = 0;
+ if (!ReadFile(pwfHandle, &pwbuf[0], fileSize, &nbytes, NULL)) {
+ HRESULT status = GetLastError();
+ CloseHandle(pwfHandle);
+ loadError.set("Error reading password file", status);
+ return passwd;
+ }
+ CloseHandle(pwfHandle);
+
+ if (nbytes == 0)
+ return passwd;
+
+ while (nbytes) {
+ if ((pwbuf[nbytes-1] == 012) || (pwbuf[nbytes-1] == 015))
+ nbytes--;
+ else
+ break;
+ }
+
+ if (nbytes)
+ passwd.assign(&pwbuf[0], nbytes);
+
+ return passwd;
+}
+
+void SslCredential::SavedError::set(const std::string &lm, const std::string es) {
+ logMessage = lm;
+ error = es;
+}
+
+void SslCredential::SavedError::set(const std::string &lm, int status) {
+ logMessage = lm;
+ error = qpid::sys::strError(status);
+}
+
+void SslCredential::SavedError::clear() {
+ logMessage.clear();
+ error.clear();
+}
+
+bool SslCredential::SavedError::pending() {
+ return !logMessage.empty() || !error.empty();
+}
+
+}}}
diff --git a/qpid/cpp/src/qpid/sys/windows/SslCredential.h b/qpid/cpp/src/qpid/sys/windows/SslCredential.h
new file mode 100644
index 0000000000..ba16dcdab5
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/windows/SslCredential.h
@@ -0,0 +1,81 @@
+#ifndef _sys_SslCredential
+#define _sys_SslCredential
+/*
+ *
+ * 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/CommonImportExport.h"
+
+#include <string.h>
+// security.h needs to see this to distinguish from kernel use.
+#define SECURITY_WIN32
+#include <security.h>
+#include <Schnlsp.h>
+#undef SECURITY_WIN32
+
+namespace qpid {
+namespace sys {
+namespace windows {
+
+/*
+ * Manage certificate data structures for SChannel.
+ *
+ * Note on client certificates: The Posix/NSS implementation performs a lazy
+ * client certificate search part way through the ssl handshake if the server
+ * requests one. Here, it is not known in advance if the server will
+ * request the certificate so the certificate is pre-loaded (even if never
+ * used). To match the Linux behavior, client certificate load problems are
+ * remembered and reported later if appropriate, but do not prevent the
+ * connection attempt.
+ */
+
+class SslCredential {
+public:
+ QPID_COMMON_EXTERN SslCredential();
+ QPID_COMMON_EXTERN ~SslCredential();
+ QPID_COMMON_EXTERN bool load(const std::string& certName);
+ QPID_COMMON_EXTERN CredHandle handle();
+ QPID_COMMON_EXTERN std::string error();
+
+private:
+ struct SavedError {
+ std::string logMessage;
+ std::string error;
+ void set(const std::string &lm, const std::string es);
+ void set(const std::string &lm, int status);
+ void clear();
+ bool pending();
+ };
+
+ HCERTSTORE certStore;
+ PCCERT_CONTEXT cert;
+ SCHANNEL_CRED cred;
+ CredHandle credHandle;
+ TimeStamp credExpiry;
+ SavedError loadError;
+
+ PCCERT_CONTEXT findCertificate(const std::string& name);
+ void loadPrivCertStore();
+ std::string getPasswd(const std::string& filename);
+};
+
+}}}
+
+#endif // _sys_SslCredential
diff --git a/qpid/cpp/src/tests/brokertest.py b/qpid/cpp/src/tests/brokertest.py
index c7fcf2c3af..4b6820e4fd 100644
--- a/qpid/cpp/src/tests/brokertest.py
+++ b/qpid/cpp/src/tests/brokertest.py
@@ -278,7 +278,7 @@ class Broker(Popen):
cmd += ["--log-to-stderr=no"]
# Add default --log-enable arguments unless args already has --log arguments.
- if not next((l for l in args if l.startswith("--log")), None):
+ if not [l for l in args if l.startswith("--log")]:
args += ["--log-enable=info+"]
if test_store: cmd += ["--load-module", BrokerTest.test_store_lib,
diff --git a/qpid/cpp/src/tests/ha_test.py b/qpid/cpp/src/tests/ha_test.py
index 4606fab746..748c8ef0c1 100755
--- a/qpid/cpp/src/tests/ha_test.py
+++ b/qpid/cpp/src/tests/ha_test.py
@@ -137,7 +137,7 @@ class HaBroker(Broker):
"--max-negotiate-time=1000",
"--ha-cluster=%s"%ha_cluster]
# Add default --log-enable arguments unless args already has --log arguments.
- if not next((l for l in args if l.startswith("--log")), None):
+ if not [l for l in args if l.startswith("--log")]:
args += ["--log-enable=info+", "--log-enable=debug+:ha::"]
if ha_replicate is not None:
args += [ "--ha-replicate=%s"%ha_replicate ]
diff --git a/qpid/cpp/src/tests/linearstore/tx-test-soak.sh b/qpid/cpp/src/tests/linearstore/tx-test-soak.sh
new file mode 100755
index 0000000000..fa05e0a4a8
--- /dev/null
+++ b/qpid/cpp/src/tests/linearstore/tx-test-soak.sh
@@ -0,0 +1,254 @@
+#! /bin/bash
+
+#
+# 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.
+#
+
+
+# tx-test-soak
+#
+# Basic test methodology:
+# 1. Start broker
+# 2. Run qpid-txtest against broker using randomly generated parameters
+# 3. After some time, kill the broker using SIGKILL
+# 4. Restart broker, recover messages
+# 5. Run qpid-txtest against broker in check mode, which checks that all expected messages are present.
+# 6. Wash, rinse, repeat... The number of runs is determined by ${NUM_RUNS}
+
+NUM_RUNS=1000
+BASE_DIR=${HOME}/RedHat
+CMAKE_BUILD_DIR=${BASE_DIR}/q.cm
+
+# Infrequently adjusted
+RESULT_BASE_DIR_PREFIX=${BASE_DIR}/results.tx-test-soak
+RECOVER_TIME_PER_QUEUE=1
+STORE_MODULE="linearstore.so"
+BROKER_LOG_LEVEL="info+"
+BROKER_MANAGEMENT="no" # "no" or "yes"
+TRUNCATE_INTERVAL=10
+MAX_DISK_PERC_USED=90
+
+# Consts (don't adjust these...)
+export BASE_DIR
+RELATIVE_BASE_DIR=`python -c "import os,os.path; print os.path.relpath(os.environ['BASE_DIR'], os.environ['PWD'])"`
+LOG_FILE_NAME=log.txt
+QPIDD_FN=qpidd
+QPIDD=${CMAKE_BUILD_DIR}/src/${QPIDD_FN}
+TXTEST=${CMAKE_BUILD_DIR}/src/tests/qpid-txtest
+QPIDD_BASE_ARGS="--load-module ${STORE_MODULE} -m ${BROKER_MANAGEMENT} --auth no --default-flow-stop-threshold 0 --default-flow-resume-threshold 0 --default-queue-limit 0 --store-dir ${BASE_DIR} --log-enable ${BROKER_LOG_LEVEL} --log-to-stderr no --log-to-stdout no"
+TXTEST_INIT_STR="--init yes --transfer no --check no"
+TXTEST_RUN_STR="--init no --transfer yes --check no"
+TXTEST_CHK_STR="--init no --transfer no --check yes"
+SUCCESS_MSG="All expected messages were retrieved."
+TIMESTAMP_FORMAT="+%Y-%m-%d_%H:%M:%S"
+ANSI_RED="\e[1;31m"
+ANSI_NONE="\e[0m"
+DEFAULT_EFP_DIR=2048k
+DEFAULT_EFP_SIZE=2101248
+SIG_KILL=-9
+SIG_TERM=-15
+
+# Creates a random number into the variable named in string $1 in the range [$2..$3] (both inclusive).
+# $1: variable name as string to which random value is assigned
+# $2: minimum inclusive range of random number
+# $3: maximum inclusive range of random number
+get_random() {
+ eval $1=`python -S -c "import random; print random.randint($2,$3)"`
+}
+
+# Uses anon-uniform distribution to set a random message size.
+# Most messages must be small (0 - 1k), but we need a few medium (10k) and large (100k) ones also.
+# Sets message size into var ${MSG_SIZE}
+set_message_size() {
+ local key=0
+ get_random "key" 1 10
+ if (( "${key}" == "10" )); then # 1 out of 10 - very large
+ get_random "MSG_SIZE" 100000 1000000
+ FILE_SIZE_MULTIPLIER=3
+ elif (( "${key}" >= "8" )); then # 2 out of 10 - large
+ get_random "MSG_SIZE" 10000 100000
+ FILE_SIZE_MULTIPLIER=2
+ elif (( "${key}" >= "6" )); then # 2 out of 10 - medium
+ get_random "MSG_SIZE" 1000 10000
+ FILE_SIZE_MULTIPLIER=1
+ else # 5 out of 10 - small
+ get_random "MSG_SIZE" 10 1000
+ FILE_SIZE_MULTIPLIER=1
+ fi
+}
+
+# Start or restart broker
+# $1: Log suffix: either "A" or "B". If "A", broker is started with truncation, otherwise broker is restarted with recovery.
+# $2: Truncate flag - only used if Log suffix is "A": if true, then truncate store
+# The PID of the broker is returned in ${QPIDD_PID}
+start_broker() {
+ local truncate_val
+ local truncate_str
+ if [[ "$1" == "A" ]]; then
+ if [[ $2 == true ]]; then
+ truncate_val="yes"
+ truncate_str="(Store truncated)"
+ if [[ -e ${BASE_DIR}/qls/p001/efp/${DEFAULT_EFP_DIR} ]]; then
+ for f in ${BASE_DIR}/qls/p001/efp/${DEFAULT_EFP_DIR}/*; do
+ local filesize=`stat -c%s "${f}"`
+ if (( ${filesize} != ${DEFAULT_EFP_SIZE} )); then
+ rm ${f}
+ fi
+ done
+ fi
+ else
+ truncate_val="no"
+ fi
+ else
+ truncate_val="no"
+ fi
+ echo "${QPIDD} ${QPIDD_BASE_ARGS} --truncate ${truncate_val} --log-to-file ${RESULT_DIR}/qpidd.$1.log &" > ${RESULT_DIR}/qpidd.$1.cmd
+ ${QPIDD} ${QPIDD_BASE_ARGS} --truncate ${truncate_val} --log-to-file ${RESULT_DIR}/qpidd.$1.log &
+ QPIDD_PID=$!
+ echo "Broker PID=${QPIDD_PID} ${truncate_str}" | tee -a ${LOG_FILE}
+}
+
+# Start or evaluate results of transaction test client
+# $1: Log suffix flag: either "A" or "B". If "A", client is started in test mode, otherwise client evaluates recovery.
+start_tx_test() {
+ local tx_test_params="--messages-per-tx ${MSGS_PER_TX} --tx-count 1000000 --total-messages ${TOT_MSGS} --size ${MSG_SIZE} --queues ${NUM_QUEUES}"
+ if [[ "$1" == "A" ]]; then
+ # Run in background
+ echo "${TXTEST##*/} parameters: ${tx_test_params}" | tee -a ${LOG_FILE}
+ echo "${TXTEST} ${tx_test_params} ${TXTEST_INIT_STR} &> ${RESULT_DIR}/txtest.$1.log" > ${RESULT_DIR}/txtest.$1.cmd
+ ${TXTEST} ${tx_test_params} ${TXTEST_INIT_STR} &> ${RESULT_DIR}/txtest.$1.log
+ echo "${TXTEST} ${tx_test_params} ${TXTEST_RUN_STR} &> ${RESULT_DIR}/txtest.$1.log &" >> ${RESULT_DIR}/txtest.$1.cmd
+ ${TXTEST} ${tx_test_params} ${TXTEST_RUN_STR} &> ${RESULT_DIR}/txtest.$1.log &
+ else
+ # Run in foreground
+ #echo "${TXTEST##*/} ${tx_test_params} ${TXTEST_CHK_STR}" | tee -a ${LOG_FILE}
+ echo "${TXTEST} ${tx_test_params} ${TXTEST_CHK_STR} &> ${RESULT_DIR}/txtest.$1.log" > ${RESULT_DIR}/txtest.$1.cmd
+ ${TXTEST} ${tx_test_params} ${TXTEST_CHK_STR} &> ${RESULT_DIR}/txtest.$1.log
+ fi
+}
+
+# Search for the presence of core.* files, move them into the current result directory and run gdb against them.
+# No params
+process_core_files() {
+ ls core.* &> /dev/null
+ if (( "$?" == "0" )); then
+ for cf in core.*; do
+ gdb --batch --quiet -ex "thread apply all bt" -ex "quit" ${QPIDD} ${cf} &> ${RESULT_DIR}/${cf##*/}.gdb.txt
+ gdb --batch --quiet -ex "thread apply all bt full" -ex "quit" ${QPIDD} ${cf} &> ${RESULT_DIR}/${cf##*/}.gdb-full.txt
+ cat ${RESULT_DIR}/${cf##*/}.gdb.txt
+ mv ${cf} ${RESULT_DIR}/
+ echo "Core file ${cf##*/} found and recovered"
+ done
+ fi
+}
+
+# Kill a process quietly
+# $1: Signal
+# $2: PID
+kill_process() {
+ kill ${1} ${2} &>> ${LOG_FILE}
+ wait ${2} &>> ${LOG_FILE}
+}
+
+# Check that test can run: No other copy of qpidd running, enough disk space
+check_ready_to_run() {
+ # Check no copy of qpidd is running
+ PID=`pgrep ${QPIDD_FN}`
+ if [[ "$?" == "0" ]]; then
+ echo "ERROR: qpidd running as pid ${PID}"
+ exit 1
+ fi
+ # Check disk is < 90% full
+ local perc_full=`df -h ${HOME} | tail -1 | awk '{print substr($5,0, length($5)-1)}'`
+ if (( ${perc_full} >= ${MAX_DISK_PERC_USED} )); then
+ echo "ERROR: Disk is too close to full (${perc_full}%)"
+ exit 2
+ fi
+}
+
+ulimit -c unlimited # Allow core files to be created
+
+RESULT_BASE_DIR_SUFFIX=`date "${TIMESTAMP_FORMAT}"`
+RESULT_BASE_DIR="${RESULT_BASE_DIR_PREFIX}.${RESULT_BASE_DIR_SUFFIX}"
+LOG_FILE=${RESULT_BASE_DIR}/${LOG_FILE_NAME}
+if [[ -n "${RESULT_BASE_DIR}" ]]; then
+ rm -rf ${RESULT_BASE_DIR}
+fi
+
+mkdir -p ${RESULT_BASE_DIR}
+for rn in `seq ${NUM_RUNS}`; do
+ # === Prepare result dir, check ready to run test, set run vars ===
+ RESULT_DIR=${RESULT_BASE_DIR}/run_${rn}
+ mkdir -p ${RESULT_DIR}
+ check_ready_to_run
+ if (( (${rn} - 1) % ${TRUNCATE_INTERVAL} == 0 )) || [[ -n ${ERROR_FLAG} ]]; then
+ TRUNCATE_FLAG=true
+ else
+ TRUNCATE_FLAG=false
+ fi
+ set_message_size
+ get_random "MSGS_PER_TX" 1 20
+ get_random "TOT_MSGS" 100 1000
+ get_random "NUM_QUEUES" 2 15
+ MIN_RUNTIME=$(( 20 * ${FILE_SIZE_MULTIPLIER} ))
+ MAX_RUNTIME=$(( 120 * ${FILE_SIZE_MULTIPLIER} ))
+ get_random "RUN_TIME" ${MIN_RUNTIME} ${MAX_RUNTIME}
+ RECOVER_TIME=$(( ${NUM_QUEUES} * ${RECOVER_TIME_PER_QUEUE} * ${FILE_SIZE_MULTIPLIER} ))
+ echo "Run ${rn} of ${NUM_RUNS} ==============" | tee -a ${LOG_FILE}
+
+ # === PART A: Initial run of qpid-txtest ===
+ start_broker "A" ${TRUNCATE_FLAG}
+ sleep ${RECOVER_TIME} # Need a way to test if broker has started here
+ start_tx_test "A"
+ echo "Running for ${RUN_TIME} secs..." | tee -a ${LOG_FILE}
+ sleep ${RUN_TIME}
+ kill_process ${SIG_KILL} ${QPIDD_PID}
+ sleep 2
+ tar -czf ${RESULT_DIR}/qls_B.tar.gz ${RELATIVE_BASE_DIR}/qls
+
+ # === PART B: Recovery and check ===
+ start_broker "B"
+ echo "Recover time=${RECOVER_TIME} secs..." | tee -a ${LOG_FILE}
+ sleep ${RECOVER_TIME} # Need a way to test if broker has started here
+ start_tx_test "B"
+ sleep 1
+ kill_process ${SIG_TERM} ${QPIDD_PID}
+ sleep 2
+ PID=`pgrep ${QPIDD_FN}`
+ if [[ "$?" == "0" ]]; then
+ kill_process ${SIG_KILL} ${PID}
+ sleep 2
+ fi
+ tar -czf ${RESULT_DIR}/qls_C.tar.gz ${RELATIVE_BASE_DIR}/qls
+
+ # === Check for errors, cores and exceptions in logs ===
+ grep -Hn "jexception" ${RESULT_DIR}/qpidd.A.log | tee -a ${LOG_FILE}
+ grep -Hn "jexception" ${RESULT_DIR}/qpidd.B.log | tee -a ${LOG_FILE}
+ grep "${SUCCESS_MSG}" ${RESULT_DIR}/txtest.B.log &> /dev/null
+ if [[ "$?" != "0" ]]; then
+ echo "ERROR in run ${rn}" >> ${LOG_FILE}
+ echo -e "${ANSI_RED}ERROR${ANSI_NONE} in run ${rn}"
+ ERROR_FLAG=true
+ else
+ unset ERROR_FLAG
+ fi
+ sleep 2
+ process_core_files
+ echo | tee -a ${LOG_FILE}
+done
+
diff --git a/qpid/doc/book/src/programming/Programming-In-Apache-Qpid.xml b/qpid/doc/book/src/programming/Programming-In-Apache-Qpid.xml
index d5527850c8..735995cd22 100644
--- a/qpid/doc/book/src/programming/Programming-In-Apache-Qpid.xml
+++ b/qpid/doc/book/src/programming/Programming-In-Apache-Qpid.xml
@@ -1627,242 +1627,295 @@ spout - -content "$(cat rdu.xml | sed -e 's/70/45/')" xml/weather
</section>
- <section id="connection-options">
- <title>Connection Options</title>
-
+ <section id="connections">
+ <title>Connections</title>
+
<para>
- Aspects of the connections behaviour can be controlled through
- specifying connection options. For example, connections can be
- configured to automatically reconnect if the connection to a
- broker is lost.
+ Messaging connections are created by specifying a broker or a list of brokers, and
+ an optional set of connection options. The constructor prototypes for Connections
+ are:
</para>
- <example>
- <title>Specifying Connection Options in C++, Python, and .NET</title>
-
- <para>In C++, these options can be set using <function>Connection::setOption()</function> or by passing in a set of options to the constructor. The options can be passed in as a map or in string form:</para>
+ <programlisting><![CDATA[
+ Connection connection();
+ Connection connection(const string url);
+ Connection connection(const string url, const string& options);
+ Connection connection(const string url, const Variant::Map& options);
+ ]]></programlisting>
- <programlisting><![CDATA[
- Connection connection("localhost:5672", "{reconnect: true}");
- try {
- connection.open();
- !!! SNIP !!!
- ]]></programlisting>
+ <para>
+ Messaging connection URLs specify only the network host address(es). Connection
+ options are specified separately as an options string or map. This is different
+ from JMS Connection URLs that combine the network address and connection properties
+ in a single string.
+ </para>
- <para>or</para>
+ <section id="connection-url">
+ <title>Connection URLs</title>
+ <para>
+ Connection URLs describe the broker or set of brokers to which the connection
+ is to attach. The format of the Connection URL is defined by AMQP 0.10
+ Domain:connection.amqp-host-url.
+ </para>
<programlisting><![CDATA[
- Connection connection("localhost:5672");
- connection.setOption("reconnect", true);
- try {
- connection.open();
- !!! SNIP !!!
- ]]></programlisting>
+ amqp_url = "amqp:" prot_addr_list
+ prot_addr_list = [prot_addr ","]* prot_addr
+ prot_addr = tcp_prot_addr | tls_prot_addr
+
+ tcp_prot_addr = tcp_id tcp_addr
+ tcp_id = "tcp:" | ""
+ tcp_addr = [host [":" port] ]
+ host = <as per http://www.ietf.org/rfc/rfc3986.txt>
+ port = number ]]></programlisting>
- <para>In Python, these options can be set as attributes of the connection or using named arguments in
- the <function>Connection</function> constructor:</para>
+ <para>
+ Examples of Messaging Connection URLs
+ </para>
<programlisting><![CDATA[
- connection = Connection("localhost:5672", reconnect=True)
- try:
- connection.open()
- !!! SNIP !!!
+ localhost
+ localhost:5672
+ localhost:9999
+ 192.168.1.2:5672
+ mybroker.example.com:5672
+ amqp:tcp:localhost:5672
+ tcp:locahost:5672,localhost:5800
]]></programlisting>
- <para>or</para>
+ </section>
- <programlisting><![CDATA[
- connection = Connection("localhost:5672")
- connection.reconnect = True
- try:
- connection.open()
- !!! SNIP !!!
- ]]></programlisting>
+ <section id="connection-options">
+ <title>Connection Options</title>
+
<para>
- In .NET, these options can be set using <function>Connection.SetOption()</function> or by passing in a set of options to the constructor. The options can be passed in as a map or in string form:
+ Aspects of the connections behaviour can be controlled through
+ specifying connection options. For example, connections can be
+ configured to automatically reconnect if the connection to a
+ broker is lost.
</para>
-
- <programlisting>
- Connection connection= new Connection(&#34;localhost:5672&#34;, &#34;{reconnect: true}&#34;);
+
+ <example>
+ <title>Specifying Connection Options in C++, Python, and .NET</title>
+
+ <para>In C++, these options can be set using <function>Connection::setOption()</function> or by passing in a set of options to the constructor. The options can be passed in as a map or in string form:</para>
+
+
+ <para>or</para>
+
+ <programlisting><![CDATA[
+ Connection connection("localhost:5672");
+ connection.setOption("reconnect", true);
try {
- connection.Open();
+ connection.open();
!!! SNIP !!!
- </programlisting>
- <para>
- or
- </para>
-
- <programlisting>
- Connection connection = new Connection(&#34;localhost:5672&#34;);
- connection.SetOption(&#34;reconnect&#34;, true);
- try {
- connection.Open();
+ ]]></programlisting>
+
+ <para>In Python, these options can be set as attributes of the connection or using named arguments in
+ the <function>Connection</function> constructor:</para>
+
+ <programlisting><![CDATA[
+ connection = Connection("localhost:5672", reconnect=True)
+ try:
+ connection.open()
!!! SNIP !!!
- </programlisting>
-
- <para>See the reference documentation for details in each language.</para>
- </example>
-
- <para>The following table lists the supported connection options.</para>
-
- <table pgwide="1">
- <title>Connection Options</title>
- <tgroup cols="3">
- <thead>
- <colspec colnum="1" colwidth="1*"/>
- <colspec colnum="2" colwidth="1*"/>
- <colspec colnum="3" colwidth="3*"/>
- <row>
- <entry>option name</entry>
- <entry>value type</entry>
- <entry>semantics</entry>
- </row>
- </thead>
- <tbody>
-
- <row>
- <entry>
- <literal>username</literal>
- </entry>
- <entry>
- string
- </entry>
- <entry>
- The username to use when authenticating to the broker.
- </entry>
- </row>
- <row>
- <entry>
- <literal>password</literal>
- </entry>
- <entry>
- string
- </entry>
- <entry>
- The password to use when authenticating to the broker.
- </entry>
- </row>
- <row>
- <entry>
- <literal>sasl_mechanisms</literal>
- </entry>
- <entry>
- string
- </entry>
- <entry>
- The specific SASL mechanisms to use with the python
- client when authenticating to the broker. The value
- is a space separated list.
- </entry>
- </row>
-
-
- <row>
- <entry>
- <literal>reconnect</literal>
- </entry>
- <entry>
- boolean
- </entry>
- <entry>
- Transparently reconnect if the connection is lost.
- </entry>
- </row>
- <row>
- <entry>
- <literal>reconnect_timeout</literal>
- </entry>
- <entry>
- integer
- </entry>
- <entry>
- Total number of seconds to continue reconnection attempts before giving up and raising an exception.
- </entry>
- </row>
- <row>
- <entry>
- <literal>reconnect_limit</literal>
- </entry>
- <entry>
- integer
- </entry>
- <entry>
- Maximum number of reconnection attempts before giving up and raising an exception.
- </entry>
- </row>
- <row>
- <entry>
- <literal>reconnect_interval_min</literal>
- </entry>
- <entry>
- integer representing time in seconds
- </entry>
- <entry>
- Minimum number of seconds between reconnection attempts. The first reconnection attempt is made immediately; if that fails, the first reconnection delay is set to the value of <literal>reconnect_interval_min</literal>; if that attempt fails, the reconnect interval increases exponentially until a reconnection attempt succeeds or <literal>reconnect_interval_max</literal> is reached.
- </entry>
- </row>
- <row>
- <entry>
- <literal>reconnect_interval_max</literal>
- </entry>
- <entry>
- integer representing time in seconds
- </entry>
- <entry>
- Maximum reconnect interval.
- </entry>
- </row>
- <row>
- <entry>
- <literal>reconnect_interval</literal>
- </entry>
- <entry>
- integer representing time in seconds
- </entry>
- <entry>
- Sets both <literal>reconnection_interval_min</literal> and <literal>reconnection_interval_max</literal> to the same value.
- </entry>
- </row>
-
- <row>
- <entry>
- <literal>heartbeat</literal>
- </entry>
- <entry>
- integer representing time in seconds
- </entry>
- <entry>
- Requests that heartbeats be sent every N seconds. If two
- successive heartbeats are missed the connection is
- considered to be lost.
- </entry>
- </row>
- <row>
- <entry>
- <literal>protocol</literal>
- </entry>
- <entry>
- string
- </entry>
- <entry>
- Sets the underlying protocol used. The default option is 'tcp'. To enable ssl, set to 'ssl'. The C++ client additionally supports 'rdma'.
- </entry>
- </row>
- <row>
- <entry>
- <literal>tcp-nodelay</literal>
- </entry>
- <entry>
- boolean
- </entry>
- <entry>
- Set tcp no-delay, i.e. disable Nagle algorithm. [C++ only]
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
+ ]]></programlisting>
+
+ <para>or</para>
+
+ <programlisting><![CDATA[
+ connection = Connection("localhost:5672")
+ connection.reconnect = True
+ try:
+ connection.open()
+ !!! SNIP !!!
+ ]]></programlisting>
+ <para>
+ In .NET, these options can be set using <function>Connection.SetOption()</function> or by passing in a set of options to the constructor. The options can be passed in as a map or in string form:
+ </para>
+
+ <programlisting>
+ Connection connection= new Connection(&#34;localhost:5672&#34;, &#34;{reconnect: true}&#34;);
+ try {
+ connection.Open();
+ !!! SNIP !!!
+ </programlisting>
+ <para>
+ or
+ </para>
+
+ <programlisting>
+ Connection connection = new Connection(&#34;localhost:5672&#34;);
+ connection.SetOption(&#34;reconnect&#34;, true);
+ try {
+ connection.Open();
+ !!! SNIP !!!
+ </programlisting>
+
+ <para>See the reference documentation for details in each language.</para>
+ </example>
+
+ <para>The following table lists the supported connection options.</para>
+
+ <table pgwide="1">
+ <title>Connection Options</title>
+ <tgroup cols="3">
+ <thead>
+ <colspec colnum="1" colwidth="1*"/>
+ <colspec colnum="2" colwidth="1*"/>
+ <colspec colnum="3" colwidth="3*"/>
+ <row>
+ <entry>option name</entry>
+ <entry>value type</entry>
+ <entry>semantics</entry>
+ </row>
+ </thead>
+ <tbody>
+
+ <row>
+ <entry>
+ <literal>username</literal>
+ </entry>
+ <entry>
+ string
+ </entry>
+ <entry>
+ The username to use when authenticating to the broker.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>password</literal>
+ </entry>
+ <entry>
+ string
+ </entry>
+ <entry>
+ The password to use when authenticating to the broker.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>sasl_mechanisms</literal>
+ </entry>
+ <entry>
+ string
+ </entry>
+ <entry>
+ The specific SASL mechanisms to use with the python
+ client when authenticating to the broker. The value
+ is a space separated list.
+ </entry>
+ </row>
+
+
+ <row>
+ <entry>
+ <literal>reconnect</literal>
+ </entry>
+ <entry>
+ boolean
+ </entry>
+ <entry>
+ Transparently reconnect if the connection is lost.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>reconnect_timeout</literal>
+ </entry>
+ <entry>
+ integer
+ </entry>
+ <entry>
+ Total number of seconds to continue reconnection attempts before giving up and raising an exception.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>reconnect_limit</literal>
+ </entry>
+ <entry>
+ integer
+ </entry>
+ <entry>
+ Maximum number of reconnection attempts before giving up and raising an exception.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>reconnect_interval_min</literal>
+ </entry>
+ <entry>
+ integer representing time in seconds
+ </entry>
+ <entry>
+ Minimum number of seconds between reconnection attempts. The first reconnection attempt is made immediately; if that fails, the first reconnection delay is set to the value of <literal>reconnect_interval_min</literal>; if that attempt fails, the reconnect interval increases exponentially until a reconnection attempt succeeds or <literal>reconnect_interval_max</literal> is reached.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>reconnect_interval_max</literal>
+ </entry>
+ <entry>
+ integer representing time in seconds
+ </entry>
+ <entry>
+ Maximum reconnect interval.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>reconnect_interval</literal>
+ </entry>
+ <entry>
+ integer representing time in seconds
+ </entry>
+ <entry>
+ Sets both <literal>reconnection_interval_min</literal> and <literal>reconnection_interval_max</literal> to the same value.
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <literal>heartbeat</literal>
+ </entry>
+ <entry>
+ integer representing time in seconds
+ </entry>
+ <entry>
+ Requests that heartbeats be sent every N seconds. If two
+ successive heartbeats are missed the connection is
+ considered to be lost.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>protocol</literal>
+ </entry>
+ <entry>
+ string
+ </entry>
+ <entry>
+ Sets the underlying protocol used. The default option is 'tcp'. To enable ssl, set to 'ssl'. The C++ client additionally supports 'rdma'.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>tcp-nodelay</literal>
+ </entry>
+ <entry>
+ boolean
+ </entry>
+ <entry>
+ Set tcp no-delay, i.e. disable Nagle algorithm. [C++ only]
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </section>
</section>
<section id="section-Maps">
diff --git a/qpid/java/amqp-1-0-client-jms/pom.xml b/qpid/java/amqp-1-0-client-jms/pom.xml
index ffcfd223ae..2b73700eed 100644
--- a/qpid/java/amqp-1-0-client-jms/pom.xml
+++ b/qpid/java/amqp-1-0-client-jms/pom.xml
@@ -16,34 +16,35 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-amqp-1-0-client-jms</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 1.0 Client JMS</name>
+ <description>AMQP 1.0 compliant JMS module</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-amqp-1-0-client</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-amqp-1-0-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
- <version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java
index 924c5b9857..9f39d2c94f 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java
@@ -24,6 +24,7 @@ import org.apache.qpid.amqp_1_0.jms.Queue;
import org.apache.qpid.amqp_1_0.jms.Topic;
import javax.jms.JMSException;
+import java.util.UUID;
import java.util.WeakHashMap;
public class DestinationImpl implements Destination, Queue, Topic
@@ -32,6 +33,7 @@ public class DestinationImpl implements Destination, Queue, Topic
new WeakHashMap<String, DestinationImpl>();
private final String _address;
+ private String _localTerminus;
protected DestinationImpl(String address)
{
@@ -62,13 +64,24 @@ public class DestinationImpl implements Destination, Queue, Topic
&& _address.equals(((DestinationImpl)obj)._address);
}
- public static synchronized DestinationImpl createDestination(final String address)
+ public static synchronized DestinationImpl createDestination(String address)
{
- DestinationImpl destination = DESTINATION_CACHE.get(address);
- if(destination == null)
+ DestinationImpl destination;
+ if (address.endsWith("!!"))
{
+ address = address.substring(0, address.length() - 2);
+ String localTerminusName = UUID.randomUUID().toString();
destination = new DestinationImpl(address);
- DESTINATION_CACHE.put(address, destination);
+ destination.setLocalTerminus(localTerminusName);
+ }
+ else
+ {
+ destination = DESTINATION_CACHE.get(address);
+ if (destination == null)
+ {
+ destination = new DestinationImpl(address);
+ DESTINATION_CACHE.put(address, destination);
+ }
}
return destination;
}
@@ -82,4 +95,14 @@ public class DestinationImpl implements Destination, Queue, Topic
{
return getAddress();
}
+
+ void setLocalTerminus(final String localTerminus)
+ {
+ _localTerminus = localTerminus;
+ }
+
+ String getLocalTerminus()
+ {
+ return _localTerminus;
+ }
}
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java
index 96ee1e984d..d7bb546d7a 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.IllegalStateException;
@@ -159,7 +160,8 @@ public class MessageConsumerImpl implements MessageConsumer, QueueReceiver, Topi
{
try
{
- return _session.getClientSession().createReceiver(_session.toAddress(_destination), AcknowledgeMode.ALO,
+ String targetAddr = _destination.getLocalTerminus() != null ? _destination.getLocalTerminus() : UUID.randomUUID().toString();
+ return _session.getClientSession().createReceiver(_session.toAddress(_destination), targetAddr, AcknowledgeMode.ALO,
_linkName, _durable, getFilters(), null);
}
catch (ConnectionErrorException e)
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java
index fed9b5904f..f2d0cb5b18 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java
@@ -75,6 +75,7 @@ public abstract class MessageImpl implements Message
private boolean _isFromQueue;
private boolean _isFromTopic;
private long _expiration;
+ private DestinationImpl _replyTo;
protected MessageImpl(Header header,
MessageAnnotations messageAnnotations,
@@ -182,11 +183,12 @@ public abstract class MessageImpl implements Message
public DestinationImpl getJMSReplyTo() throws JMSException
{
- return toDestination(getReplyTo(), splitCommaSeparateSet((String) getMessageAnnotation(REPLY_TO_TYPE)));
+ return _replyTo != null ? _replyTo : toDestination(getReplyTo(), splitCommaSeparateSet((String) getMessageAnnotation(REPLY_TO_TYPE)));
}
public void setJMSReplyTo(Destination destination) throws NonAMQPDestinationException
{
+ _replyTo = (DestinationImpl) destination;
if( destination==null )
{
setReplyTo(null);
@@ -194,9 +196,16 @@ public abstract class MessageImpl implements Message
}
else
{
- DecodedDestination dd = toDecodedDestination(destination);
- setReplyTo(dd.getAddress());
- messageAnnotationMap().put(REPLY_TO_TYPE, join(",", dd.getAttributes()));
+ if(_replyTo.getLocalTerminus() != null)
+ {
+ setReplyTo(_replyTo.getLocalTerminus());
+ }
+ else
+ {
+ DecodedDestination dd = toDecodedDestination(destination);
+ setReplyTo(dd.getAddress());
+ messageAnnotationMap().put(REPLY_TO_TYPE, join(",", dd.getAttributes()));
+ }
}
}
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java
index e459575974..b12540d597 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java
@@ -77,7 +77,11 @@ public class MessageProducerImpl implements MessageProducer, QueueSender, TopicP
{
try
{
- _sender = _session.getClientSession().createSender(_session.toAddress(_destination), new Session.SourceConfigurator()
+ final String sourceName = _destination.getLocalTerminus() != null
+ ? _destination.getLocalTerminus()
+ : UUID.randomUUID().toString();
+
+ _sender = _session.getClientSession().createSender(sourceName, _session.toAddress(_destination), new Session.SourceConfigurator()
{
public void configureSource(final Source source)
{
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java
index cb56843a72..589ee5204f 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java
@@ -20,6 +20,7 @@ package org.apache.qpid.amqp_1_0.jms.impl;
import org.apache.qpid.amqp_1_0.jms.Queue;
+import java.util.UUID;
import java.util.WeakHashMap;
public class QueueImpl extends DestinationImpl implements Queue
@@ -37,13 +38,24 @@ public class QueueImpl extends DestinationImpl implements Queue
return getAddress();
}
- public static synchronized QueueImpl createQueue(final String address)
+ public static synchronized QueueImpl createQueue(String address)
{
- QueueImpl queue = QUEUE_CACHE.get(address);
- if(queue == null)
+ QueueImpl queue;
+ if (address.endsWith("!!"))
{
+ address = address.substring(0, address.length() - 2);
+ String localTerminusName = UUID.randomUUID().toString();
queue = new QueueImpl(address);
- QUEUE_CACHE.put(address, queue);
+ queue.setLocalTerminus(localTerminusName);
+ }
+ else
+ {
+ queue = QUEUE_CACHE.get(address);
+ if(queue == null)
+ {
+ queue = new QueueImpl(address);
+ QUEUE_CACHE.put(address, queue);
+ }
}
return queue;
}
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java
index 4e9e9d6a39..21161ff83f 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java
@@ -24,6 +24,8 @@ import org.apache.qpid.amqp_1_0.client.Receiver;
import org.apache.qpid.amqp_1_0.jms.Queue;
import org.apache.qpid.amqp_1_0.jms.QueueReceiver;
+import java.util.UUID;
+
public class QueueReceiverImpl extends MessageConsumerImpl implements QueueReceiver
{
QueueReceiverImpl(final QueueImpl destination,
@@ -40,7 +42,11 @@ public class QueueReceiverImpl extends MessageConsumerImpl implements QueueRecei
{
try
{
- return getSession().getClientSession().createMovingReceiver(getSession().toAddress(getDestination()));
+ final String targetAddr =
+ getDestination().getLocalTerminus() != null ? getDestination().getLocalTerminus() : UUID
+ .randomUUID().toString();
+ return getSession().getClientSession().createMovingReceiver(getSession().toAddress(getDestination()),
+ targetAddr);
}
catch (ConnectionErrorException e)
{
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java
index 2318b8ba9b..bd67ff681a 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java
@@ -460,7 +460,7 @@ public class SessionImpl implements Session, QueueSession, TopicSession
{
checkClosed();
checkNotTopicSession();
- return new QueueImpl(s);
+ return QueueImpl.valueOf(s);
}
public QueueReceiver createReceiver(final Queue queue) throws JMSException
@@ -488,7 +488,7 @@ public class SessionImpl implements Session, QueueSession, TopicSession
{
checkClosed();
checkNotQueueSession();
- return new TopicImpl(s);
+ return TopicImpl.valueOf(s);
}
public TopicSubscriber createSubscriber(final Topic topic) throws JMSException
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java
index 5292944075..edc583e233 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java
@@ -20,6 +20,7 @@ package org.apache.qpid.amqp_1_0.jms.impl;
import org.apache.qpid.amqp_1_0.jms.Topic;
+import java.util.UUID;
import java.util.WeakHashMap;
public class TopicImpl extends DestinationImpl implements Topic
@@ -38,13 +39,24 @@ public class TopicImpl extends DestinationImpl implements Topic
return getAddress();
}
- public static synchronized TopicImpl createTopic(final String address)
+ public static synchronized TopicImpl createTopic(String address)
{
- TopicImpl topic = TOPIC_CACHE.get(address);
- if(topic == null)
+ TopicImpl topic;
+ if (address.endsWith("!!"))
{
+ address = address.substring(0, address.length() - 2);
+ String localTerminusName = UUID.randomUUID().toString();
topic = new TopicImpl(address);
- TOPIC_CACHE.put(address, topic);
+ topic.setLocalTerminus(localTerminusName);
+ }
+ else
+ {
+ topic = TOPIC_CACHE.get(address);
+ if(topic == null)
+ {
+ topic = new TopicImpl(address);
+ TOPIC_CACHE.put(address, topic);
+ }
}
return topic;
}
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java
index 69e07f30a1..b89025a27b 100644
--- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java
+++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java
@@ -19,6 +19,7 @@
package org.apache.qpid.amqp_1_0.jms.impl;
import java.util.Map;
+import java.util.UUID;
import javax.jms.InvalidSelectorException;
import javax.jms.JMSException;
import org.apache.qpid.amqp_1_0.client.AcknowledgeMode;
@@ -67,7 +68,9 @@ public class TopicSubscriberImpl extends MessageConsumerImpl implements TopicSub
try
{
String address = getSession().toAddress(getDestination());
- Receiver receiver = getSession().getClientSession().createReceiver(address,
+ String targetAddress = getDestination().getLocalTerminus() != null ? getDestination().getLocalTerminus() : UUID.randomUUID().toString();
+
+ Receiver receiver = getSession().getClientSession().createReceiver(address, targetAddress,
StdDistMode.COPY, AcknowledgeMode.ALO,
getLinkName(), isDurable(), getFilters(),
null);
diff --git a/qpid/java/amqp-1-0-client-websocket/pom.xml b/qpid/java/amqp-1-0-client-websocket/pom.xml
index 3862fb0fc5..78da6d3b9e 100644
--- a/qpid/java/amqp-1-0-client-websocket/pom.xml
+++ b/qpid/java/amqp-1-0-client-websocket/pom.xml
@@ -16,145 +16,41 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-amqp-1-0-client-websocket</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 1.0 Client WebSocket</name>
+ <description>AMQP 1.0 compliant WebSocket module</description>
<dependencies>
-
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-amqp-1-0-client</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-amqp-1-0-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-servlet_3.0_spec</artifactId>
+ </dependency>
- <dependency>
- <groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-servlet_3.0_spec</artifactId>
- <version>1.0</version>
- <scope>compile</scope>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty.orbit</groupId>
- <artifactId>javax.servlet</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-continuation</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-continuation</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-security</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-servlet</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-security</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-websocket</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git a/qpid/java/amqp-1-0-client/pom.xml b/qpid/java/amqp-1-0-client/pom.xml
index 1d6a444d6d..2bee6b43d1 100644
--- a/qpid/java/amqp-1-0-client/pom.xml
+++ b/qpid/java/amqp-1-0-client/pom.xml
@@ -16,21 +16,24 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-amqp-1-0-client</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 1.0 Client</name>
+ <description>AMQP 1.0 compliant client module</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-amqp-1-0-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
</dependencies>
diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java
index cac4775b54..290895df60 100644
--- a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java
+++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java
@@ -78,8 +78,14 @@ public class Session
public Sender createSender(final String targetName, final SourceConfigurator configurator)
throws Sender.SenderCreationException, ConnectionClosedException
{
-
final String sourceName = UUID.randomUUID().toString();
+ return createSender(sourceName, targetName, configurator);
+ }
+
+ public Sender createSender(final String sourceName, final String targetName, final SourceConfigurator configurator)
+ throws Sender.SenderCreationException, ConnectionClosedException
+ {
+
return new Sender(this, targetName +"<-"+sourceName, targetName, sourceName, false)
{
@Override
@@ -150,93 +156,118 @@ public class Session
public Receiver createReceiver(final String sourceAddr) throws ConnectionErrorException
{
- return createReceiver(sourceAddr, null, AcknowledgeMode.ALO);
+ return createReceiver(sourceAddr, UUID.randomUUID().toString(), null, AcknowledgeMode.ALO);
}
public Receiver createReceiver(final String queue, final AcknowledgeMode mode)
throws ConnectionErrorException
{
- return createReceiver(queue, null, mode);
+ return createReceiver(queue, UUID.randomUUID().toString(), null, mode);
}
public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName)
throws ConnectionErrorException
{
- return createReceiver(queue, null, mode, linkName);
+ return createReceiver(queue, UUID.randomUUID().toString(), null, mode, linkName);
}
public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName, boolean isDurable)
throws ConnectionErrorException
{
- return createReceiver(queue, null, mode, linkName, isDurable);
+ return createReceiver(queue, UUID.randomUUID().toString(), null, mode, linkName, isDurable);
}
public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName, boolean isDurable,
Map<Symbol, Filter> filters, Map<Binary, Outcome> unsettled)
throws ConnectionErrorException
{
- return createReceiver(queue, null, mode, linkName, isDurable, filters, unsettled);
+ return createReceiver(queue, (DistributionMode) null, mode, linkName, isDurable, filters, unsettled);
}
-
- public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName,
- boolean isDurable, Map<Binary, Outcome> unsettled)
+ public Receiver createReceiver(final String queue, String targetName, final AcknowledgeMode mode, String linkName, boolean isDurable,
+ Map<Symbol, Filter> filters, Map<Binary, Outcome> unsettled)
throws ConnectionErrorException
{
- return createReceiver(queue, null, mode, linkName, isDurable, unsettled);
+ return createReceiver(queue, targetName, null, mode, linkName, isDurable, filters, unsettled);
}
- private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode)
+ public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName,
+ boolean isDurable, Map<Binary, Outcome> unsettled)
throws ConnectionErrorException
{
- return createReceiver(sourceAddr, mode, AcknowledgeMode.ALO);
+ return createReceiver(queue, UUID.randomUUID().toString(), null, mode, linkName, isDurable, unsettled);
}
- private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode, String linkName)
+
+ private synchronized Receiver createReceiver(final String sourceAddr,
+ final String targetAddr,
+ DistributionMode mode)
throws ConnectionErrorException
{
- return createReceiver(sourceAddr, mode, AcknowledgeMode.ALO, linkName);
+ return createReceiver(sourceAddr, targetAddr, mode, AcknowledgeMode.ALO);
}
- private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode,
- final AcknowledgeMode ackMode)
+ private synchronized Receiver createReceiver(final String sourceAddr,
+ final String targetAddr,
+ DistributionMode mode,
+ final AcknowledgeMode ackMode)
throws ConnectionErrorException
{
- return createReceiver(sourceAddr, mode, ackMode, null);
+ return createReceiver(sourceAddr, targetAddr, mode, ackMode, null);
}
- private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode,
- final AcknowledgeMode ackMode, String linkName)
+ private synchronized Receiver createReceiver(final String sourceAddr,
+ final String targetAddr,
+ DistributionMode mode,
+ final AcknowledgeMode ackMode,
+ String linkName)
throws ConnectionErrorException
{
- return createReceiver(sourceAddr,mode, ackMode, linkName, false);
+ return createReceiver(sourceAddr, targetAddr, mode, ackMode, linkName, false);
}
- private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode,
- final AcknowledgeMode ackMode, String linkName, boolean isDurable)
+ private synchronized Receiver createReceiver(final String sourceAddr,
+ final String targetAddr,
+ DistributionMode mode,
+ final AcknowledgeMode ackMode,
+ String linkName,
+ boolean isDurable)
throws ConnectionErrorException
{
- return createReceiver(sourceAddr, mode, ackMode, linkName, isDurable, null);
+ return createReceiver(sourceAddr, targetAddr, mode, ackMode, linkName, isDurable, null);
}
- private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode,
- final AcknowledgeMode ackMode, String linkName, boolean isDurable,
- Map<Binary, Outcome> unsettled)
+ private synchronized Receiver createReceiver(final String sourceAddr,
+ final String targetAddr,
+ DistributionMode mode,
+ final AcknowledgeMode ackMode,
+ String linkName,
+ boolean isDurable,
+ Map<Binary, Outcome> unsettled)
throws ConnectionErrorException
{
return createReceiver(sourceAddr,mode,ackMode, linkName, isDurable, null, unsettled);
}
public synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode,
+ final AcknowledgeMode ackMode, String linkName, boolean isDurable,
+ Map<Symbol, Filter> filters, Map<Binary, Outcome> unsettled)
+ throws ConnectionErrorException
+ {
+ return createReceiver(sourceAddr, UUID.randomUUID().toString(), mode, ackMode, linkName, isDurable, filters, unsettled);
+ }
+
+ public synchronized Receiver createReceiver(final String sourceAddr, String targetAddr, DistributionMode mode,
final AcknowledgeMode ackMode, String linkName, boolean isDurable,
Map<Symbol, Filter> filters, Map<Binary, Outcome> unsettled)
throws ConnectionErrorException
{
final Target target = new Target();
+ target.setAddress(targetAddr);
final Source source = new Source();
source.setAddress(sourceAddr);
source.setDistributionMode(mode);
@@ -258,12 +289,17 @@ public class Session
public synchronized Receiver createCopyingReceiver(final String sourceAddr) throws ConnectionErrorException
{
- return createReceiver(sourceAddr, StdDistMode.COPY);
+ return createReceiver(sourceAddr, UUID.randomUUID().toString(), StdDistMode.COPY);
}
public synchronized Receiver createMovingReceiver(final String sourceAddr) throws ConnectionErrorException
{
- return createReceiver(sourceAddr, StdDistMode.MOVE);
+ return createReceiver(sourceAddr, UUID.randomUUID().toString(), StdDistMode.MOVE);
+ }
+
+ public synchronized Receiver createMovingReceiver(final String sourceAddr, final String targetAddr) throws ConnectionErrorException
+ {
+ return createReceiver(sourceAddr, UUID.randomUUID().toString(), StdDistMode.MOVE);
}
public Receiver createTemporaryQueueReceiver() throws AmqpErrorException, ConnectionErrorException
diff --git a/qpid/java/amqp-1-0-common/pom.xml b/qpid/java/amqp-1-0-common/pom.xml
index d771d58ab1..7b01caa5b0 100644
--- a/qpid/java/amqp-1-0-common/pom.xml
+++ b/qpid/java/amqp-1-0-common/pom.xml
@@ -16,14 +16,18 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-amqp-1-0-common</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 1.0 Common</name>
+ <description>AMQP 1.0 compliant common module</description>
<build>
</build>
diff --git a/qpid/java/bdbstore/jmx/pom.xml b/qpid/java/bdbstore/jmx/pom.xml
index 82ece2c66f..626f80b9ab 100644
--- a/qpid/java/bdbstore/jmx/pom.xml
+++ b/qpid/java/bdbstore/jmx/pom.xml
@@ -16,49 +16,48 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-bdbstore-jmx</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid BDB Message Store JMX</name>
+ <description>BDB message store JMX implementation</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-management-jmx</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-bdbstore</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sleepycat</groupId>
<artifactId>je</artifactId>
- <version>5.0.84</version>
<scope>provided</scope>
</dependency>
@@ -66,14 +65,14 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
diff --git a/qpid/java/bdbstore/pom.xml b/qpid/java/bdbstore/pom.xml
index ec71547038..60abfcb5cd 100644
--- a/qpid/java/bdbstore/pom.xml
+++ b/qpid/java/bdbstore/pom.xml
@@ -16,41 +16,41 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-bdbstore</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid BDB Message Store</name>
+ <description>BDB message store implementation using Oracle Berkeley DB Java Edition</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-8-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sleepycat</groupId>
<artifactId>je</artifactId>
- <version>5.0.97</version>
<scope>provided</scope>
</dependency>
@@ -58,14 +58,14 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
@@ -73,21 +73,20 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-10-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
- <version>1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-client</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java
index 6925c9ee2b..e0a79fa1c1 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java
@@ -69,7 +69,7 @@ public class MessageMetaDataBinding extends TupleBinding<StorableMessageMetaData
buf.position(1);
buf = buf.slice();
- metaData.writeToBuffer(0, buf);
+ metaData.writeToBuffer(buf);
tupleOutput.writeInt(bodySize);
tupleOutput.writeFast(underlying);
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/PreparedTransactionBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/PreparedTransactionBinding.java
index e543cfb719..8fb011152c 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/PreparedTransactionBinding.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/PreparedTransactionBinding.java
@@ -73,7 +73,7 @@ public class PreparedTransactionBinding extends TupleBinding<PreparedTransaction
output.writeInt(records.length);
for(Transaction.Record record : records)
{
- UUID id = record.getQueue().getId();
+ UUID id = record.getResource().getId();
output.writeLong(id.getMostSignificantBits());
output.writeLong(id.getLeastSignificantBits());
output.writeLong(record.getMessage().getMessageNumber());
@@ -93,7 +93,7 @@ public class PreparedTransactionBinding extends TupleBinding<PreparedTransaction
_queueId = queueId;
}
- public TransactionLogResource getQueue()
+ public TransactionLogResource getResource()
{
return this;
}
@@ -119,9 +119,21 @@ public class PreparedTransactionBinding extends TupleBinding<PreparedTransaction
}
@Override
+ public String getName()
+ {
+ return _queueId.toString();
+ }
+
+ @Override
public UUID getId()
{
return _queueId;
}
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
}
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java
index 9d52241c4c..14793cbfd3 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java
@@ -741,7 +741,7 @@ public class UpgradeFrom4To5 extends AbstractStoreUpgrade
buf.position(1);
buf = buf.slice();
- metaData.writeToBuffer(0, buf);
+ metaData.writeToBuffer(buf);
output.writeInt(bodySize);
output.writeFast(underlying);
}
diff --git a/qpid/java/bdbstore/systests/pom.xml b/qpid/java/bdbstore/systests/pom.xml
index 5cf42e8b35..c25470bf6d 100644
--- a/qpid/java/bdbstore/systests/pom.xml
+++ b/qpid/java/bdbstore/systests/pom.xml
@@ -16,15 +16,19 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-bdbstore-systests</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid BDB Store System Tests</name>
+ <description>BDB message store system tests</description>
<properties>
<broker.home.dir>target${file.separator}qpid-broker${file.separator}${project.version}</broker.home.dir>
@@ -37,7 +41,6 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>${junit-version}</version>
<scope>compile</scope>
</dependency>
@@ -51,50 +54,40 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-systests</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
- <version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-bdbstore</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-bdbstore-jmx</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.sleepycat</groupId>
<artifactId>je</artifactId>
- <version>5.0.84</version>
- <scope>compile</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
index 1bf156384c..bd57edfaa8 100644
--- a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
+++ b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
@@ -425,10 +425,22 @@ public class BDBMessageStoreTest extends MessageStoreTest
TransactionLogResource mockQueue = new TransactionLogResource()
{
@Override
+ public String getName()
+ {
+ return getId().toString();
+ }
+
+ @Override
public UUID getId()
{
return mockQueueId;
}
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
};
Transaction txn = log.newTransaction();
@@ -463,10 +475,22 @@ public class BDBMessageStoreTest extends MessageStoreTest
TransactionLogResource mockQueue = new TransactionLogResource()
{
@Override
+ public String getName()
+ {
+ return getId().toString();
+ }
+
+ @Override
public UUID getId()
{
return mockQueueId;
}
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
};
Transaction txn = log.newTransaction();
@@ -520,10 +544,22 @@ public class BDBMessageStoreTest extends MessageStoreTest
TransactionLogResource mockQueue = new TransactionLogResource()
{
@Override
+ public String getName()
+ {
+ return getId().toString();
+ }
+
+ @Override
public UUID getId()
{
return mockQueueId;
}
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
};
Transaction txn = log.newTransaction();
diff --git a/qpid/java/broker-core/pom.xml b/qpid/java/broker-core/pom.xml
index 7254de0251..4621a8df75 100644
--- a/qpid/java/broker-core/pom.xml
+++ b/qpid/java/broker-core/pom.xml
@@ -16,14 +16,18 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-core</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Java Broker Core</name>
+ <description>Broker core functionality and initial configuration</description>
<properties>
<generated-logmessages-dir>${basedir}/src/main/java</generated-logmessages-dir>
@@ -33,50 +37,38 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-management-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.1.1</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
- <version>2.7.0</version>
- <scope>compile</scope>
<exclusions>
<exclusion>
<groupId>xml-apis</groupId>
@@ -88,15 +80,11 @@
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils-core</artifactId>
- <version>1.8.3</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
- <version>1.8.1</version>
- <scope>compile</scope>
<exclusions>
<exclusion>
<groupId>commons-beanutils</groupId>
@@ -108,50 +96,36 @@
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
- <version>1.6</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
- <version>2.6</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
- <version>3.2.1</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
- <version>1.8</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
- <version>1.9.0</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
- <version>1.9.0</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.bcel</groupId>
<artifactId>bcel</artifactId>
- <version>5.2</version>
- <scope>compile</scope>
<exclusions>
<exclusion>
<!-- Qpid doesn't require BCEL InstructionFinder, so does not need jakarta-regexp. -->
@@ -165,7 +139,7 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
@@ -261,12 +235,12 @@
<dependency>
<groupId>velocity</groupId>
<artifactId>velocity</artifactId>
- <version>1.4</version>
+ <version>${velocity-version}</version>
</dependency>
<dependency>
<groupId>velocity</groupId>
<artifactId>velocity-dep</artifactId>
- <version>1.4</version>
+ <version>${velocity-version}</version>
</dependency>
</dependencies>
</plugin>
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java
new file mode 100644
index 0000000000..aa721e598a
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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.consumer;
+
+import org.apache.qpid.server.util.StateChangeListener;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+public abstract class AbstractConsumerTarget implements ConsumerTarget
+{
+
+ private final AtomicReference<State> _state;
+ private final AtomicReference<StateChangeListener<ConsumerTarget, State>> _stateListener =
+ new AtomicReference<StateChangeListener<ConsumerTarget, State>>();
+
+ protected AbstractConsumerTarget(final State initialState)
+ {
+ _state = new AtomicReference<State>(initialState);
+ }
+
+
+ public final State getState()
+ {
+ return _state.get();
+ }
+
+ protected final boolean updateState(State from, State to)
+ {
+ if(_state.compareAndSet(from, to))
+ {
+ StateChangeListener<ConsumerTarget, State> listener = _stateListener.get();
+ if(listener != null)
+ {
+ listener.stateChanged(this, from, to);
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ public final void setStateListener(StateChangeListener<ConsumerTarget, State> listener)
+ {
+ _stateListener.set(listener);
+ }
+
+ public final StateChangeListener<ConsumerTarget, State> getStateListener()
+ {
+ return _stateListener.get();
+ }
+
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/Consumer.java
index fde3d3809c..e082d6eee4 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/Subscription.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/Consumer.java
@@ -18,22 +18,29 @@
* under the License.
*
*/
-package org.apache.qpid.server.subscription;
+package org.apache.qpid.server.consumer;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.protocol.AMQSessionModel;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.util.StateChangeListener;
-public interface Subscription
+public interface Consumer
{
AtomicLong SUB_ID_GENERATOR = new AtomicLong(0);
- LogActor getLogActor();
+ void externalStateChange();
- boolean isTransient();
+ enum Option
+ {
+ ACQUIRES,
+ SEES_REQUEUES,
+ TRANSIENT,
+ EXCLUSIVE,
+ NO_LOCAL
+ }
long getBytesOut();
@@ -43,49 +50,21 @@ public interface Subscription
long getUnacknowledgedMessages();
- public static enum State
- {
- ACTIVE,
- SUSPENDED,
- CLOSED
- }
-
- public static interface StateListener
- {
- public void stateChange(Subscription sub, State oldState, State newState);
- }
-
- AMQQueue getQueue();
AMQSessionModel getSessionModel();
- QueueEntry.SubscriptionAcquiredState getOwningState();
-
- void setQueue(AMQQueue queue, boolean exclusive);
-
void setNoLocal(boolean noLocal);
- long getSubscriptionID();
+ long getId();
boolean isSuspended();
- boolean hasInterest(QueueEntry msg);
-
boolean isClosed();
boolean acquires();
boolean seesRequeues();
- void close();
-
- void send(QueueEntry entry, boolean batch) throws AMQException;
-
- void flushBatched();
-
- void queueDeleted(AMQQueue queue);
-
-
- boolean wouldSuspend(QueueEntry msg);
+ void close() throws AMQException;
boolean trySendLock();
@@ -94,30 +73,9 @@ public interface Subscription
void releaseSendLock();
- void releaseQueueEntry(final QueueEntry queueEntryImpl);
-
- void onDequeue(final QueueEntry queueEntry);
-
- void restoreCredit(final QueueEntry queueEntry);
-
- void setStateListener(final StateListener listener);
-
- public State getState();
-
- AMQQueue.Context getQueueContext();
-
- void setQueueContext(AMQQueue.Context queueContext);
-
-
boolean isActive();
- public void set(String key, Object value);
-
- public Object get(String key);
-
- boolean isSessionTransactional();
-
- void queueEmpty() throws AMQException;
+ String getName();
- String getConsumerName();
+ void flush() throws AMQException;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java
new file mode 100644
index 0000000000..92579475ed
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java
@@ -0,0 +1,67 @@
+/*
+ *
+ * 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.consumer;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.util.StateChangeListener;
+
+public interface ConsumerTarget
+{
+
+
+ enum State
+ {
+ ACTIVE, SUSPENDED, CLOSED
+ }
+
+ State getState();
+
+ void consumerAdded(Consumer sub);
+
+ void consumerRemoved(Consumer sub);
+
+ void setStateListener(StateChangeListener<ConsumerTarget, State> listener);
+
+ long getUnacknowledgedBytes();
+
+ long getUnacknowledgedMessages();
+
+ AMQSessionModel getSessionModel();
+
+ void send(MessageInstance entry, boolean batch) throws AMQException;
+
+ void flushBatched();
+
+ void queueDeleted();
+
+ void queueEmpty() throws AMQException;
+
+ boolean allocateCredit(ServerMessage msg);
+
+ void restoreCredit(ServerMessage queueEntry);
+
+ boolean isSuspended();
+
+ boolean close();
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index 6a959df440..600c60bdb3 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -26,6 +26,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.AMQInternalException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.BindingMessages;
@@ -33,14 +34,18 @@ import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.logging.subjects.BindingLogSubject;
import org.apache.qpid.server.logging.subjects.ExchangeLogSubject;
import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.plugin.ExchangeType;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.store.DurableConfigurationStoreHelper;
+import org.apache.qpid.server.store.StorableMessageMetaData;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collection;
@@ -66,7 +71,7 @@ public abstract class AbstractExchange implements Exchange
private VirtualHost _virtualHost;
- private final List<Task> _closeTaskList = new CopyOnWriteArrayList<Task>();
+ private final List<Action<Exchange>> _closeTaskList = new CopyOnWriteArrayList<Action<Exchange>>();
/**
* Whether the exchange is automatically deleted once all queues have detached from it
@@ -138,6 +143,12 @@ public abstract class AbstractExchange implements Exchange
if(_closed.compareAndSet(false,true))
{
+ List<Binding> bindings = new ArrayList<Binding>(_bindings);
+ for(Binding binding : bindings)
+ {
+ removeBinding(binding);
+ }
+
if(_alternateExchange != null)
{
_alternateExchange.removeReference(this);
@@ -145,9 +156,9 @@ public abstract class AbstractExchange implements Exchange
CurrentActor.get().message(_logSubject, ExchangeMessages.DELETED());
- for(Task task : _closeTaskList)
+ for(Action<Exchange> task : _closeTaskList)
{
- task.onClose(this);
+ task.performAction(this);
}
_closeTaskList.clear();
}
@@ -300,12 +311,12 @@ public abstract class AbstractExchange implements Exchange
return !_referrers.isEmpty();
}
- public void addCloseTask(final Task task)
+ public void addCloseTask(final Action<Exchange> task)
{
_closeTaskList.add(task);
}
- public void removeCloseTask(final Task task)
+ public void removeCloseTask(final Action<Exchange> task)
{
_closeTaskList.remove(task);
}
@@ -418,10 +429,10 @@ public abstract class AbstractExchange implements Exchange
return queues;
}
- public final int send(final ServerMessage message,
+ public final <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final BaseQueue.PostEnqueueAction postEnqueueAction)
+ final Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction)
{
List<? extends BaseQueue> queues = route(message, instanceProperties);
@@ -579,8 +590,6 @@ public abstract class AbstractExchange implements Exchange
{
doRemoveBinding(b);
queue.removeBinding(b);
- removeCloseTask(b);
- queue.removeQueueDeleteTask(b);
if (b.isDurable())
{
@@ -659,8 +668,6 @@ public abstract class AbstractExchange implements Exchange
DurableConfigurationStoreHelper.createBinding(_virtualHost.getDurableConfigurationStore(), b);
}
- queue.addQueueDeleteTask(b);
- addCloseTask(b);
queue.addBinding(b);
doAddBinding(b);
b.logCreation();
@@ -673,7 +680,7 @@ public abstract class AbstractExchange implements Exchange
}
}
- private final class BindingImpl extends Binding implements AMQQueue.Task, Task
+ private final class BindingImpl extends Binding
{
private final BindingLogSubject _logSubject;
//TODO : persist creation time
@@ -689,12 +696,6 @@ public abstract class AbstractExchange implements Exchange
}
-
- public void doTask(final AMQQueue queue) throws AMQException
- {
- removeBinding(this);
- }
-
public void onClose(final Exchange exchange) throws AMQSecurityException, AMQInternalException
{
removeBinding(this);
@@ -729,11 +730,6 @@ public abstract class AbstractExchange implements Exchange
}
- public static interface Task
- {
- public void onClose(Exchange exchange) throws AMQSecurityException, AMQInternalException;
- }
-
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java
index 71d0f8b4dd..78b9664cd3 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java
@@ -32,18 +32,23 @@ import org.apache.qpid.AMQInternalException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.plugin.ExchangeType;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.store.StorableMessageMetaData;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
public class DefaultExchange implements Exchange
@@ -331,10 +336,10 @@ public class DefaultExchange implements Exchange
return _id;
}
- public final int send(final ServerMessage message,
+ public final <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final BaseQueue.PostEnqueueAction postEnqueueAction)
+ final Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction)
{
final AMQQueue q = _virtualHost.getQueue(message.getRoutingKey());
if(q == null)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/Exchange.java
index 18e912e972..6d83fdb2a1 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/Exchange.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/Exchange.java
@@ -24,20 +24,16 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.AMQInternalException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.server.binding.Binding;
-import org.apache.qpid.server.message.InstanceProperties;
-import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.MessageDestination;
import org.apache.qpid.server.plugin.ExchangeType;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.BaseQueue;
-import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collection;
-import java.util.List;
import java.util.Map;
import java.util.UUID;
-public interface Exchange extends ExchangeReferrer
+public interface Exchange extends ExchangeReferrer, MessageDestination
{
void initialise(UUID id, VirtualHost host, String name, boolean durable, boolean autoDelete)
throws AMQException;
@@ -95,19 +91,6 @@ public interface Exchange extends ExchangeReferrer
void close() throws AMQException;
/**
- * Routes a message
- * @param message the message to be routed
- * @param instanceProperties the instance properties
- * @param txn the transaction to enqueue within
- * @param postEnqueueAction action to perform on the result of every enqueue (may be null)
- * @return the number of queues in which the message was enqueued performed
- */
- int send(ServerMessage message,
- InstanceProperties instanceProperties,
- ServerTransaction txn,
- BaseQueue.PostEnqueueAction postEnqueueAction);
-
- /**
* Determines whether a message would be isBound to a particular queue using a specific routing key and arguments
* @param bindingKey
* @param arguments
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/filter/FilterSupport.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/filter/FilterSupport.java
index b50424868a..efefec58fd 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/filter/FilterSupport.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/filter/FilterSupport.java
@@ -30,6 +30,7 @@ import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.filter.SelectorParsingException;
import org.apache.qpid.filter.selector.ParseException;
import org.apache.qpid.filter.selector.TokenMgrError;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
@@ -118,11 +119,11 @@ public class FilterSupport
}
}
- static final class NoLocalFilter implements MessageFilter
+ public static final class NoLocalFilter implements MessageFilter
{
- private final AMQQueue _queue;
+ private final MessageSource _queue;
- public NoLocalFilter(AMQQueue queue)
+ public NoLocalFilter(MessageSource queue)
{
_queue = queue;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java
index 6251471139..91d9ef7dbc 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java
@@ -35,7 +35,6 @@ import org.apache.qpid.server.logging.LogSubject;
* 2) We can set new actors at the point we have enough information. i.e.
* - Set a low level ConnectionActor when processing bytes from the wire.
* - Set a ChannelActor when we are processing the frame
- * - Set a SubscriptionActor when we are handling the subscription.
* <p/>
* The code performing the logging need not worry about what type of actor is
* currently set so can perform its logging. The resulting log entry though will
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/GenericActor.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/GenericActor.java
index 0e418a95e2..4cf2bd4508 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/GenericActor.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/GenericActor.java
@@ -42,6 +42,24 @@ public class GenericActor extends AbstractActor
_defaultMessageLogger = defaultMessageLogger;
}
+ public GenericActor(final String logSubject)
+ {
+ this(new LogSubject()
+ {
+ @Override
+ public String toLogString()
+ {
+ return logSubject;
+ }
+ });
+ }
+
+
+ public GenericActor(LogSubject logSubject)
+ {
+ this(logSubject, CurrentActor.get().getRootMessageLogger());
+ }
+
public GenericActor(LogSubject logSubject, RootMessageLogger rootLogger)
{
super(rootLogger);
@@ -53,6 +71,11 @@ public class GenericActor extends AbstractActor
return _logSubject.toLogString();
}
+ public LogSubject getLogSubject()
+ {
+ return _logSubject;
+ }
+
public static LogActor getInstance(final String logMessage, RootMessageLogger rootLogger)
{
return new GenericActor(new LogSubject()
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubject.java
deleted file mode 100644
index 0292fe3506..0000000000
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubject.java
+++ /dev/null
@@ -1,55 +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.server.logging.subjects;
-
-import org.apache.qpid.server.subscription.Subscription;
-
-import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SUBSCRIPTION_FORMAT;
-
-import java.text.MessageFormat;
-
-public class SubscriptionLogSubject extends AbstractLogSubject
-{
-
- /**
- * Create an QueueLogSubject that Logs in the following format.
- *
- * @param subscription
- */
- public SubscriptionLogSubject(Subscription subscription)
- {
- // Delegate the formatting of the Queue to the QueueLogSubject. So final
- // log string format is:
- // [ sub:<id>(vh(<vhost>)/qu(<queue>)) ]
-
- String queueString = new QueueLogSubject(subscription.getQueue()).toLogString();
-
- setLogString("[" + MessageFormat.format(SUBSCRIPTION_FORMAT,
- subscription.getSubscriptionID())
- + "("
- // queueString is [vh(/{0})/qu({1}) ] so need to trim
- // ^ ^^
- + queueString.substring(1,queueString.length() - 3)
- + ")"
- + "] ");
-
- }
-}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java
new file mode 100644
index 0000000000..62f5b3634b
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java
@@ -0,0 +1,45 @@
+/*
+ *
+ * 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.message;
+
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.store.StorableMessageMetaData;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
+
+public interface MessageDestination extends MessageNode
+{
+
+ public String getName();
+
+ /**
+ * Routes a message
+ * @param message the message to be routed
+ * @param instanceProperties the instance properties
+ * @param txn the transaction to enqueue within
+ * @param postEnqueueAction action to perform on the result of every enqueue (may be null)
+ * @return the number of queues in which the message was enqueued performed
+ */
+ <M extends ServerMessage<? extends StorableMessageMetaData>> int send(M message,
+ InstanceProperties instanceProperties,
+ ServerTransaction txn,
+ Action<? super MessageInstance<?,? extends Consumer>> postEnqueueAction);
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java
index afd7ff0269..49969ce3c1 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java
@@ -21,9 +21,178 @@
package org.apache.qpid.server.message;
-public interface MessageInstance
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.filter.Filterable;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.util.StateChangeListener;
+
+public interface MessageInstance<M extends MessageInstance<M,C>, C extends Consumer>
{
+
+ /**
+ * Number of times this queue entry has been delivered.
+ *
+ * @return delivery count
+ */
+ int getDeliveryCount();
+
+ void incrementDeliveryCount();
+
+ void decrementDeliveryCount();
+
+ void addStateChangeListener(StateChangeListener<? super M,State> listener);
+
+ boolean removeStateChangeListener(StateChangeListener<? super M, State> listener);
+
+ boolean acquiredByConsumer();
+
+ boolean isAcquiredBy(C consumer);
+
+ void setRedelivered();
+
+ boolean isRedelivered();
+
+ C getDeliveredConsumer();
+
+ void reject();
+
+ boolean isRejectedBy(C consumer);
+
+ boolean getDeliveredToConsumer();
+
+ boolean expired() throws AMQException;
+
+ boolean acquire(C sub);
+
+ int getMaximumDeliveryCount();
+
+ int routeToAlternate(Action<? super MessageInstance<?, ? extends Consumer>> action, ServerTransaction txn);
+
+ Filterable asFilterable();
+
+ public static enum State
+ {
+ AVAILABLE,
+ ACQUIRED,
+ DEQUEUED,
+ DELETED
+ }
+
+ public abstract class EntryState
+ {
+ private EntryState()
+ {
+ }
+
+ public abstract State getState();
+
+ /**
+ * Returns true if state is either DEQUEUED or DELETED.
+ *
+ * @return true if state is either DEQUEUED or DELETED.
+ */
+ public boolean isDispensed()
+ {
+ State currentState = getState();
+ return currentState == State.DEQUEUED || currentState == State.DELETED;
+ }
+ }
+
+
+ public final class AvailableState extends EntryState
+ {
+
+ public State getState()
+ {
+ return State.AVAILABLE;
+ }
+
+ public String toString()
+ {
+ return getState().name();
+ }
+ }
+
+
+ public final class DequeuedState extends EntryState
+ {
+
+ public State getState()
+ {
+ return State.DEQUEUED;
+ }
+
+ public String toString()
+ {
+ return getState().name();
+ }
+ }
+
+
+ public final class DeletedState extends EntryState
+ {
+
+ public State getState()
+ {
+ return State.DELETED;
+ }
+
+ public String toString()
+ {
+ return getState().name();
+ }
+ }
+
+ public final class NonConsumerAcquiredState extends EntryState
+ {
+ public State getState()
+ {
+ return State.ACQUIRED;
+ }
+
+ public String toString()
+ {
+ return getState().name();
+ }
+ }
+
+ public final class ConsumerAcquiredState<C extends Consumer> extends EntryState
+ {
+ private final C _consumer;
+
+ public ConsumerAcquiredState(C consumer)
+ {
+ _consumer = consumer;
+ }
+
+
+ public State getState()
+ {
+ return State.ACQUIRED;
+ }
+
+ public C getConsumer()
+ {
+ return _consumer;
+ }
+
+ public String toString()
+ {
+ return "{" + getState().name() + " : " + _consumer +"}";
+ }
+ }
+
+
+ final static EntryState AVAILABLE_STATE = new AvailableState();
+ final static EntryState DELETED_STATE = new DeletedState();
+ final static EntryState DEQUEUED_STATE = new DequeuedState();
+ final static EntryState NON_CONSUMER_ACQUIRED_STATE = new NonConsumerAcquiredState();
+
boolean isAvailable();
boolean acquire();
@@ -32,6 +201,8 @@ public interface MessageInstance
void release();
+ boolean resend() throws AMQException;
+
void delete();
boolean isDeleted();
@@ -39,4 +210,6 @@ public interface MessageInstance
ServerMessage getMessage();
InstanceProperties getInstanceProperties();
+
+ TransactionLogResource getOwningResource();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageNode.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageNode.java
new file mode 100644
index 0000000000..f4b751d2fd
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageNode.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.message;
+
+public interface MessageNode
+{
+ String getName();
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java
new file mode 100644
index 0000000000..1996c73222
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java
@@ -0,0 +1,105 @@
+/*
+ *
+ * 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.message;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.filter.FilterManager;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.security.AuthorizationHolder;
+import org.apache.qpid.server.store.TransactionLogResource;
+
+import java.util.Collection;
+import java.util.EnumSet;
+
+public interface MessageSource<C extends Consumer, S extends MessageSource<C,S>> extends TransactionLogResource, MessageNode
+{
+ <T extends ConsumerTarget> C addConsumer(T target, FilterManager filters,
+ Class<? extends ServerMessage> messageClass,
+ String consumerName, EnumSet<Consumer.Option> options) throws AMQException;
+
+ Collection<C> getConsumers();
+
+ void addConsumerRegistrationListener(ConsumerRegistrationListener<S> listener);
+
+ void removeConsumerRegistrationListener(ConsumerRegistrationListener<S> listener);
+
+ AuthorizationHolder getAuthorizationHolder();
+
+ void setAuthorizationHolder(AuthorizationHolder principalHolder);
+
+ void setExclusiveOwningSession(AMQSessionModel owner);
+
+ AMQSessionModel getExclusiveOwningSession();
+
+ boolean isExclusive();
+
+ interface ConsumerRegistrationListener<Q extends MessageSource<? extends Consumer,?>>
+ {
+ void consumerAdded(Q source, Consumer consumer);
+ void consumerRemoved(Q queue, Consumer consumer);
+ }
+
+ /**
+ * ExistingExclusiveConsumer signals a failure to create a consumer, because an exclusive consumer
+ * already exists.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represent failure to create a consumer, because an exclusive consumer already exists.
+ * </table>
+ *
+ * @todo Not an AMQP exception as no status code.
+ *
+ * @todo Move to top level, used outside this class.
+ */
+ static final class ExistingExclusiveConsumer extends AMQException
+ {
+
+ public ExistingExclusiveConsumer()
+ {
+ super("");
+ }
+ }
+
+ /**
+ * ExistingConsumerPreventsExclusive signals a failure to create an exclusive consumer, as a consumer
+ * already exists.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represent failure to create an exclusive consumer, as a consumer already exists.
+ * </table>
+ *
+ * @todo Not an AMQP exception as no status code.
+ *
+ * @todo Move to top level, used outside this class.
+ */
+ static final class ExistingConsumerPreventsExclusive extends AMQException
+ {
+ public ExistingConsumerPreventsExclusive()
+ {
+ super("");
+ }
+ }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java
new file mode 100644
index 0000000000..1584cf3029
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java
@@ -0,0 +1,259 @@
+/*
+ *
+ * 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.message.internal;
+
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.AbstractServerMessageImpl;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.util.ByteBufferInputStream;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class InternalMessage extends AbstractServerMessageImpl<InternalMessage, InternalMessageMetaData>
+{
+ private final Object _messageBody;
+ private final int _contentSize;
+ private InternalMessageHeader _header;
+
+
+ InternalMessage(final StoredMessage<InternalMessageMetaData> handle,
+ final InternalMessageHeader header,
+ final Object messageBody)
+ {
+ super(handle, null);
+ _header = header;
+ _messageBody = messageBody;
+ _contentSize = handle.getMetaData().getContentSize();
+ }
+
+ InternalMessage(final StoredMessage<InternalMessageMetaData> msg)
+ {
+ super(msg, null);
+ _contentSize = msg.getMetaData().getContentSize();
+ ByteBuffer buf = msg.getContent(0, _contentSize);
+
+ try
+ {
+ ObjectInputStream is = new ObjectInputStream(new ByteBufferInputStream(buf));
+ _messageBody = is.readObject();
+
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public String getRoutingKey()
+ {
+ return null;
+ }
+
+ @Override
+ public InternalMessageHeader getMessageHeader()
+ {
+ return _header;
+ }
+
+ @Override
+ public long getSize()
+ {
+ return _contentSize;
+ }
+
+ @Override
+ public long getExpiration()
+ {
+ return _header.getExpiration();
+ }
+
+ @Override
+ public long getArrivalTime()
+ {
+ return _header.getArrivalTime();
+ }
+
+ public Object getMessageBody()
+ {
+ return _messageBody;
+ }
+
+ private static InternalMessage createMessage(final MessageStore store,
+ final AMQMessageHeader header,
+ final Serializable bodyObject, final boolean persistent)
+ {
+ InternalMessageHeader internalHeader;
+ if(header instanceof InternalMessageHeader)
+ {
+ internalHeader = (InternalMessageHeader) header;
+ }
+ else
+ {
+ internalHeader = new InternalMessageHeader(header);
+ }
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ try
+ {
+ ObjectOutputStream os = new ObjectOutputStream(bytesOut);
+ os.writeObject(bodyObject);
+ byte[] bytes = bytesOut.toByteArray();
+
+
+ final InternalMessageMetaData metaData = InternalMessageMetaData.create(persistent, internalHeader, bytes.length);
+ StoredMessage<InternalMessageMetaData> handle =
+ store.addMessage(metaData);
+ handle.addContent(0, ByteBuffer.wrap(bytes));
+
+ return new InternalMessage(handle, internalHeader, bodyObject);
+ }
+ catch(AMQStoreException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static InternalMessage createStringMessage(MessageStore store, AMQMessageHeader header, String messageBody)
+ {
+ return createMessage(store, header, messageBody, false);
+ }
+
+ public static InternalMessage createMapMessage(MessageStore store, AMQMessageHeader header, Map<? extends Object,? extends Object> messageBody)
+ {
+ return createMessage(store, header, new LinkedHashMap<Object,Object>(messageBody), false);
+ }
+
+ public static InternalMessage createListMessage(MessageStore store, AMQMessageHeader header, List<? extends Object> messageBody)
+ {
+ return createMessage(store, header, new ArrayList<Object>(messageBody), false);
+ }
+
+ public static InternalMessage createBytesMessage(MessageStore store, AMQMessageHeader header, byte[] messageBody)
+ {
+ return createMessage(store, header, messageBody, false);
+ }
+
+ public static InternalMessage convert(long messageNumber, boolean persistent, AMQMessageHeader header, Object messageBody)
+ {
+ InternalMessageHeader convertedHeader = new InternalMessageHeader(header);
+ StoredMessage<InternalMessageMetaData> handle = createReadOnlyHandle(messageNumber, persistent, convertedHeader, messageBody);
+ return new InternalMessage(handle, convertedHeader, messageBody);
+ }
+
+ private static StoredMessage<InternalMessageMetaData> createReadOnlyHandle(final long messageNumber,
+ final boolean persistent,
+ final InternalMessageHeader header,
+ final Object messageBody)
+ {
+
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ try
+ {
+ ObjectOutputStream os = new ObjectOutputStream(bytesOut);
+ os.writeObject(messageBody);
+ final byte[] bytes = bytesOut.toByteArray();
+
+
+ final InternalMessageMetaData metaData = InternalMessageMetaData.create(persistent, header, bytes.length);
+
+
+ return new StoredMessage<InternalMessageMetaData>()
+ {
+ @Override
+ public InternalMessageMetaData getMetaData()
+ {
+ return metaData;
+ }
+
+ @Override
+ public long getMessageNumber()
+ {
+ return messageNumber;
+ }
+
+ @Override
+ public void addContent(final int offsetInMessage, final ByteBuffer src)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getContent(final int offsetInMessage, final ByteBuffer dst)
+ {
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ buffer.position(offsetInMessage);
+ buffer = buffer.slice();
+ if(dst.remaining() < buffer.remaining())
+ {
+ buffer.limit(dst.remaining());
+ }
+ int pos = dst.position();
+ dst.put(buffer);
+ return dst.position()-pos;
+ }
+
+ @Override
+ public ByteBuffer getContent(final int offsetInMessage, final int size)
+ {
+ return ByteBuffer.wrap(bytes,offsetInMessage,size);
+ }
+
+ @Override
+ public StoreFuture flushToStore()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageHeader.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageHeader.java
new file mode 100644
index 0000000000..75c5a414f4
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageHeader.java
@@ -0,0 +1,197 @@
+/*
+ *
+ * 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.message.internal;
+
+import org.apache.qpid.server.message.AMQMessageHeader;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+public final class InternalMessageHeader implements AMQMessageHeader, Serializable
+{
+ private static final long serialVersionUID = 7219183903302678948L;
+
+ private final LinkedHashMap<String, Object> _headers;
+ private final String _correlationId;
+ private final long _expiration;
+ private final String _userId;
+ private final String _appId;
+ private final String _messageId;
+ private final String _mimeType;
+ private final String _encoding;
+ private final byte _priority;
+ private final long _timestamp;
+ private final String _type;
+ private final String _replyTo;
+ private long _arrivalTime;
+
+ public InternalMessageHeader(final Map<String, Object> headers,
+ final String correlationId,
+ final long expiration,
+ final String userId,
+ final String appId,
+ final String messageId,
+ final String mimeType,
+ final String encoding,
+ final byte priority, final long timestamp, final String type, final String replyTo)
+ {
+ _headers = headers == null ? new LinkedHashMap<String, Object>()
+ : new LinkedHashMap<String, Object>(headers);
+
+ _correlationId = correlationId;
+ _expiration = expiration;
+ _userId = userId;
+ _appId = appId;
+ _messageId = messageId;
+ _mimeType = mimeType;
+ _encoding = encoding;
+ _priority = priority;
+ _timestamp = timestamp;
+ _type = type;
+ _replyTo = replyTo;
+ _arrivalTime = System.currentTimeMillis();
+ }
+
+ public InternalMessageHeader(final AMQMessageHeader header)
+ {
+ _correlationId = header.getCorrelationId();
+ _expiration = header.getExpiration();
+ _userId = header.getUserId();
+ _appId = header.getAppId();
+ _messageId = header.getMessageId();
+ _mimeType = header.getMimeType();
+ _encoding = header.getEncoding();
+ _priority = header.getPriority();
+ _timestamp = header.getTimestamp();
+ _type = header.getType();
+ _replyTo = header.getReplyTo();
+ _headers = new LinkedHashMap<String, Object>();
+ for(String headerName : header.getHeaderNames())
+ {
+ _headers.put(headerName, header.getHeader(headerName));
+ }
+ _arrivalTime = System.currentTimeMillis();
+ }
+
+ @Override
+ public String getCorrelationId()
+ {
+ return _correlationId;
+ }
+
+ @Override
+ public long getExpiration()
+ {
+ return _expiration;
+ }
+
+ @Override
+ public String getUserId()
+ {
+ return _userId;
+ }
+
+ @Override
+ public String getAppId()
+ {
+ return _appId;
+ }
+
+ @Override
+ public String getMessageId()
+ {
+ return _messageId;
+ }
+
+ @Override
+ public String getMimeType()
+ {
+ return _mimeType;
+ }
+
+ @Override
+ public String getEncoding()
+ {
+ return _encoding;
+ }
+
+ @Override
+ public byte getPriority()
+ {
+ return _priority;
+ }
+
+ @Override
+ public long getTimestamp()
+ {
+ return _timestamp;
+ }
+
+ @Override
+ public String getType()
+ {
+ return _type;
+ }
+
+ @Override
+ public String getReplyTo()
+ {
+ return _replyTo;
+ }
+
+ @Override
+ public Object getHeader(final String name)
+ {
+ return _headers.get(name);
+ }
+
+ @Override
+ public boolean containsHeaders(final Set<String> names)
+ {
+ return _headers.keySet().containsAll(names);
+ }
+
+ @Override
+ public boolean containsHeader(final String name)
+ {
+ return _headers.keySet().contains(name);
+ }
+
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ return Collections.unmodifiableCollection(_headers.keySet());
+ }
+
+ long getArrivalTime()
+ {
+ return _arrivalTime;
+ }
+
+ public Map<String,Object> getHeaderMap()
+ {
+ return Collections.unmodifiableMap(new LinkedHashMap<String, Object>(_headers));
+ }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java
new file mode 100644
index 0000000000..d7772657a2
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java
@@ -0,0 +1,95 @@
+/*
+ *
+ * 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.message.internal;
+
+import org.apache.qpid.server.store.StorableMessageMetaData;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.nio.ByteBuffer;
+
+public class InternalMessageMetaData implements StorableMessageMetaData
+{
+
+
+ private boolean _isPersistent;
+ private byte[] _headerBytes;
+ private int _contentSize;
+
+ public InternalMessageMetaData(final boolean isPersistent, final byte[] headerBytes, final int contentSize)
+ {
+ _isPersistent = isPersistent;
+ _headerBytes = headerBytes;
+ _contentSize = contentSize;
+ }
+
+ @Override
+ public InternalMessageMetaDataType getType()
+ {
+ return InternalMessageMetaDataType.INSTANCE;
+ }
+
+ @Override
+ public int getStorableSize()
+ {
+ return _headerBytes.length;
+ }
+
+ @Override
+ public int writeToBuffer(final ByteBuffer dest)
+ {
+ dest.put(_headerBytes);
+ return _headerBytes.length;
+ }
+
+ @Override
+ public int getContentSize()
+ {
+ return _contentSize;
+ }
+
+ @Override
+ public boolean isPersistent()
+ {
+ return _isPersistent;
+ }
+
+ static InternalMessageMetaData create(boolean persistent, final InternalMessageHeader header, int contentSize)
+ {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ try
+ {
+ ObjectOutputStream os = new ObjectOutputStream(bytesOut);
+ os.writeObject(header);
+ byte[] bytes = bytesOut.toByteArray();
+
+ return new InternalMessageMetaData(persistent, bytes, contentSize);
+
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaDataType.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaDataType.java
new file mode 100644
index 0000000000..eb90599aef
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaDataType.java
@@ -0,0 +1,76 @@
+/*
+ *
+ * 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.message.internal;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.plugin.MessageMetaDataType;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.util.ByteBufferInputStream;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.nio.ByteBuffer;
+
+public class InternalMessageMetaDataType implements MessageMetaDataType<InternalMessageMetaData>
+{
+ public static final int INTERNAL_ORDINAL = 999;
+ public static final String TYPE = "INTERNAL";
+
+ @Override
+ public int ordinal()
+ {
+ return INTERNAL_ORDINAL;
+ }
+
+ @Override
+ public InternalMessageMetaData createMetaData(final ByteBuffer buf)
+ {
+ try
+ {
+ ObjectInputStream is = new ObjectInputStream(new ByteBufferInputStream(buf));
+ InternalMessageMetaData metaData = (InternalMessageMetaData) is.readObject();
+ return metaData;
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Cannot decode message header");
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ @Override
+ public ServerMessage<InternalMessageMetaData> createMessage(final StoredMessage<InternalMessageMetaData> msg)
+ {
+ return new InternalMessage(msg);
+ }
+
+ @Override
+ public String getType()
+ {
+ return TYPE;
+ }
+
+ public static final InternalMessageMetaDataType INSTANCE = new InternalMessageMetaDataType();
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java
index d96bef0463..20d0166c9d 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java
@@ -27,9 +27,7 @@ import org.apache.qpid.server.security.AccessControl;
public interface AccessControlProvider extends ConfiguredObject
{
- public static final String ID = "id";
public static final String DESCRIPTION = "description";
- public static final String NAME = "name";
public static final String STATE = "state";
public static final String DURABLE = "durable";
public static final String LIFETIME_POLICY = "lifetimePolicy";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AmqpManagement.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AmqpManagement.java
new file mode 100644
index 0000000000..43b77bfe1d
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AmqpManagement.java
@@ -0,0 +1,35 @@
+/*
+ *
+ * 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.model;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+
+public @interface AmqpManagement
+{
+ String[] attributes();
+ String[] operations();
+ boolean managesChildren() default false; // for objects that manage children, a management node needs to be created
+ boolean creatable() default true;
+ String defaultImplementation() default ""; // in this case the class/interface itself is to be used
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
index f75d0211cb..c111f40cc8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
@@ -29,9 +29,7 @@ import org.apache.qpid.server.security.SubjectCreator;
public interface AuthenticationProvider extends ConfiguredObject
{
- public static final String ID = "id";
public static final String DESCRIPTION = "description";
- public static final String NAME = "name";
public static final String STATE = "state";
public static final String DURABLE = "durable";
public static final String LIFETIME_POLICY = "lifetimePolicy";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java
index fdb009386c..d5f833e393 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java
@@ -43,9 +43,7 @@ public interface Binding extends ConfiguredObject
public String ARGUMENTS = "arguments";
public String CREATED = "created";
public String DURABLE = "durable";
- public String ID = "id";
public String LIFETIME_POLICY = "lifetimePolicy";
- public String NAME = "name";
public String STATE = "state";
public String TIME_TO_LIVE = "timeToLive";
public String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
index 8ff1ca198a..28881ff9a6 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
@@ -48,9 +48,7 @@ public interface Broker extends ConfiguredObject
String SUPPORTED_PREFERENCES_PROVIDERS_TYPES = "supportedPreferencesProviderTypes";
String CREATED = "created";
String DURABLE = "durable";
- String ID = "id";
String LIFETIME_POLICY = "lifetimePolicy";
- String NAME = "name";
String STATE = "state";
String TIME_TO_LIVE = "timeToLive";
String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
index fa6d53a546..3bd9441f87 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
@@ -25,6 +25,14 @@ import java.util.Collection;
import java.util.Map;
import java.util.UUID;
+@AmqpManagement(
+ attributes = {
+ ConfiguredObject.ID,
+ ConfiguredObject.NAME
+ },
+ operations = {},
+ creatable = false
+)
/**
* An object that can be "managed" (eg via the web interface) and usually read from configuration.
*/
@@ -32,6 +40,9 @@ public interface ConfiguredObject
{
final String DESIRED_STATE = "desiredState";
+ public static final String ID = "id";
+ public static final String NAME = "name";
+// public static final String TYPE = "type";
/**
* Get the universally unique identifier for the object
*
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java
index 31d40c7c3e..a7350f528c 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java
@@ -24,6 +24,32 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+@AmqpManagement(
+ attributes = {
+ Connection.ID,
+ Connection.NAME,
+ Connection.STATE,
+ Connection.DURABLE,
+ Connection.LIFETIME_POLICY,
+ Connection.TIME_TO_LIVE,
+ Connection.CREATED,
+ Connection.UPDATED,
+ Connection.CLIENT_ID,
+ Connection.CLIENT_VERSION,
+ Connection.INCOMING,
+ Connection.LOCAL_ADDRESS,
+ Connection.PRINCIPAL,
+ Connection.PROPERTIES,
+ Connection.REMOTE_ADDRESS,
+ Connection.REMOTE_PROCESS_NAME,
+ Connection.REMOTE_PROCESS_PID,
+ Connection.SESSION_COUNT_LIMIT,
+ Connection.TRANSPORT,
+ Connection.PORT
+ },
+ operations = {},
+ creatable = false
+)
public interface Connection extends ConfiguredObject
{
@@ -59,8 +85,6 @@ public interface Connection extends ConfiguredObject
// Attributes
- public static final String ID = "id";
- public static final String NAME = "name";
public static final String STATE = "state";
public static final String DURABLE = "durable";
public static final String LIFETIME_POLICY = "lifetimePolicy";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java
index 958177e713..6f8726d0c8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java
@@ -33,9 +33,7 @@ public interface Consumer extends ConfiguredObject
public String SETTLEMENT_MODE = "settlementMode";
public String CREATED = "created";
public String DURABLE = "durable";
- public String ID = "id";
public String LIFETIME_POLICY = "lifetimePolicy";
- public String NAME = "name";
public String STATE = "state";
public String TIME_TO_LIVE = "timeToLive";
public String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java
index e63c71e955..c4575a7359 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java
@@ -25,6 +25,22 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
+@AmqpManagement(
+ attributes = {
+ Exchange.ID,
+ Exchange.NAME,
+ Exchange.STATE,
+ Exchange.DURABLE,
+ Exchange.LIFETIME_POLICY,
+ Exchange.TIME_TO_LIVE,
+ Exchange.CREATED,
+ Exchange.UPDATED,
+ Exchange.ALTERNATE_EXCHANGE,
+ Exchange.TYPE
+ },
+ operations = {}
+)
+
public interface Exchange extends ConfiguredObject
{
String BINDING_COUNT = "bindingCount";
@@ -47,9 +63,7 @@ public interface Exchange extends ConfiguredObject
String CREATED = "created";
String DURABLE = "durable";
- String ID = "id";
String LIFETIME_POLICY = "lifetimePolicy";
- String NAME = "name";
String STATE = "state";
String TIME_TO_LIVE = "timeToLive";
String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java
index aacd515107..e62949708d 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java
@@ -27,9 +27,7 @@ public interface Group extends ConfiguredObject
{
String CREATED = "created";
String DURABLE = "durable";
- String ID = "id";
String LIFETIME_POLICY = "lifetimePolicy";
- String NAME = "name";
String STATE = "state";
String TIME_TO_LIVE = "timeToLive";
String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java
index 6832cc6fa6..46dd6ec3e2 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java
@@ -27,9 +27,7 @@ public interface GroupMember extends ConfiguredObject
{
String CREATED = "created";
String DURABLE = "durable";
- String ID = "id";
String LIFETIME_POLICY = "lifetimePolicy";
- String NAME = "name";
String STATE = "state";
String TIME_TO_LIVE = "timeToLive";
String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupProvider.java
index 9016f97927..e5c64ec882 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupProvider.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupProvider.java
@@ -27,9 +27,7 @@ import java.util.Set;
public interface GroupProvider extends ConfiguredObject
{
- public static final String ID = "id";
public static final String DESCRIPTION = "description";
- public static final String NAME = "name";
public static final String STATE = "state";
public static final String DURABLE = "durable";
public static final String LIFETIME_POLICY = "lifetimePolicy";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java
index ab909390bd..1e1cbb7cef 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java
@@ -28,8 +28,6 @@ import javax.net.ssl.KeyManager;
public interface KeyStore extends ConfiguredObject
{
- String ID = "id";
- String NAME = "name";
String DURABLE = "durable";
String LIFETIME_POLICY = "lifetimePolicy";
String STATE = "state";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Plugin.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Plugin.java
index b9503a5841..7cdea9d12c 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Plugin.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Plugin.java
@@ -29,9 +29,7 @@ public interface Plugin extends ConfiguredObject
//Hack, using it for the class name only for consistency with the other things.
String CREATED = "created";
String DURABLE = "durable";
- String ID = "id";
String LIFETIME_POLICY = "lifetimePolicy";
- String NAME = "name";
String STATE = "state";
String TIME_TO_LIVE = "timeToLive";
String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
index 60d62e3f27..9458ac4120 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
@@ -29,9 +29,7 @@ public interface Port extends ConfiguredObject
{
String CREATED = "created";
String DURABLE = "durable";
- String ID = "id";
String LIFETIME_POLICY = "lifetimePolicy";
- String NAME = "name";
String STATE = "state";
String TIME_TO_LIVE = "timeToLive";
String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java
index fadd036a58..c895ce36f8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java
@@ -29,8 +29,6 @@ import java.util.Set;
public interface PreferencesProvider extends ConfiguredObject
{
- String ID = "id";
- String NAME = "name";
String TYPE = "type";
String CREATED = "created";
String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
index ae2031bd71..dc65c6ef81 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
@@ -25,6 +25,40 @@ import java.util.Collection;
import java.util.Collections;
import org.apache.qpid.server.queue.QueueEntryVisitor;
+@AmqpManagement(
+ attributes = {
+ Queue.ID,
+ Queue.NAME,
+ Queue.DESCRIPTION,
+ Queue.STATE,
+ Queue.DURABLE,
+ Queue.LIFETIME_POLICY,
+ Queue.TIME_TO_LIVE,
+ Queue.CREATED,
+ Queue.UPDATED,
+ Queue.QUEUE_TYPE,
+ Queue.ALTERNATE_EXCHANGE,
+ Queue.EXCLUSIVE,
+ Queue.OWNER,
+ Queue.NO_LOCAL,
+ Queue.LVQ_KEY,
+ Queue.SORT_KEY,
+ Queue.MESSAGE_GROUP_KEY,
+ Queue.MESSAGE_GROUP_SHARED_GROUPS,
+ Queue.MAXIMUM_DELIVERY_ATTEMPTS,
+ Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES,
+ Queue.QUEUE_FLOW_RESUME_SIZE_BYTES,
+ Queue.QUEUE_FLOW_STOPPED,
+ Queue.ALERT_THRESHOLD_MESSAGE_AGE,
+ Queue.ALERT_THRESHOLD_MESSAGE_SIZE,
+ Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES,
+ Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES,
+ Queue.ALERT_REPEAT_GAP,
+ Queue.PRIORITIES
+ },
+ operations = {}
+)
+
public interface Queue extends ConfiguredObject
{
public static final String BINDING_COUNT = "bindingCount";
@@ -69,9 +103,7 @@ public interface Queue extends ConfiguredObject
- public static final String ID = "id";
public static final String DESCRIPTION = "description";
- public static final String NAME = "name";
public static final String STATE = "state";
public static final String DURABLE = "durable";
public static final String LIFETIME_POLICY = "lifetimePolicy";
@@ -98,7 +130,7 @@ public interface Queue extends ConfiguredObject
public static final String QUEUE_FLOW_RESUME_SIZE_BYTES = "queueFlowResumeSizeBytes";
public static final String QUEUE_FLOW_STOPPED = "queueFlowStopped";
public static final String SORT_KEY = "sortKey";
- public static final String TYPE = "type";
+ public static final String QUEUE_TYPE = "queueType";
public static final String PRIORITIES = "priorities";
public static final String CREATE_DLQ_ON_CREATION = "x-qpid-dlq-enabled"; // TODO - this value should change
@@ -118,7 +150,7 @@ public interface Queue extends ConfiguredObject
TIME_TO_LIVE,
CREATED,
UPDATED,
- TYPE,
+ QUEUE_TYPE,
ALTERNATE_EXCHANGE,
EXCLUSIVE,
OWNER,
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ReplicationNode.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ReplicationNode.java
index 71002d9f72..0771908a5a 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ReplicationNode.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ReplicationNode.java
@@ -26,8 +26,6 @@ import java.util.Collections;
public interface ReplicationNode extends ConfiguredObject
{
- String ID = "id";
- String NAME = "name";
String STATE = "state";
String CREATED = "created";
String DURABLE = "durable";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java
index e813d0c129..40ff3ef686 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java
@@ -51,8 +51,6 @@ public interface Session extends ConfiguredObject
XA_TRANSACTION_BRANCH_SUSPENDS));
- public static final String ID = "id";
- public static final String NAME = "name";
public static final String STATE = "state";
public static final String DURABLE = "durable";
public static final String LIFETIME_POLICY = "lifetimePolicy";
@@ -77,6 +75,6 @@ public interface Session extends ConfiguredObject
CHANNEL_ID,
PRODUCER_FLOW_BLOCKED));
- Collection<Consumer> getSubscriptions();
+ Collection<Consumer> getConsumers();
Collection<Publisher> getPublishers();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/TrustStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/TrustStore.java
index d313e1832f..e4eac98bc0 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/TrustStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/TrustStore.java
@@ -28,8 +28,6 @@ import javax.net.ssl.TrustManager;
public interface TrustStore extends ConfiguredObject
{
- String ID = "id";
- String NAME = "name";
String DURABLE = "durable";
String LIFETIME_POLICY = "lifetimePolicy";
String STATE = "state";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/User.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/User.java
index cf1a688634..9d7dd7c0cd 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/User.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/User.java
@@ -30,9 +30,7 @@ public interface User extends ConfiguredObject
{
String CREATED = "created";
String DURABLE = "durable";
- String ID = "id";
String LIFETIME_POLICY = "lifetimePolicy";
- String NAME = "name";
String STATE = "state";
String TIME_TO_LIVE = "timeToLive";
String UPDATED = "updated";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
index 5cf39a6a30..81ceb88c79 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.model;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.store.MessageStore;
@@ -31,6 +32,43 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
+@AmqpManagement(
+ attributes = {
+ VirtualHost.ID,
+ VirtualHost.NAME,
+ VirtualHost.TYPE,
+ VirtualHost.STATE,
+ VirtualHost.DURABLE,
+ VirtualHost.LIFETIME_POLICY,
+ VirtualHost.TIME_TO_LIVE,
+ VirtualHost.CREATED,
+ VirtualHost.UPDATED,
+ VirtualHost.SUPPORTED_EXCHANGE_TYPES,
+ VirtualHost.SUPPORTED_QUEUE_TYPES,
+ VirtualHost.QUEUE_DEAD_LETTER_QUEUE_ENABLED,
+ VirtualHost.HOUSEKEEPING_CHECK_PERIOD,
+ VirtualHost.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS,
+ VirtualHost.QUEUE_FLOW_CONTROL_SIZE_BYTES,
+ VirtualHost.QUEUE_FLOW_RESUME_SIZE_BYTES,
+ VirtualHost.CONFIG_STORE_TYPE,
+ VirtualHost.CONFIG_STORE_PATH,
+ VirtualHost.STORE_TYPE,
+ VirtualHost.STORE_PATH,
+ VirtualHost.STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE,
+ VirtualHost.STORE_TRANSACTION_IDLE_TIMEOUT_WARN,
+ VirtualHost.STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE,
+ VirtualHost.STORE_TRANSACTION_OPEN_TIMEOUT_WARN,
+ VirtualHost.QUEUE_ALERT_REPEAT_GAP,
+ VirtualHost.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE,
+ VirtualHost.QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE,
+ VirtualHost.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES,
+ VirtualHost.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES,
+ VirtualHost.CONFIG_PATH
+ },
+ operations = {},
+ managesChildren = true
+)
+
public interface VirtualHost extends ConfiguredObject
{
// Statistics
@@ -81,9 +119,7 @@ public interface VirtualHost extends ConfiguredObject
String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes";
String CREATED = "created";
String DURABLE = "durable";
- String ID = "id";
String LIFETIME_POLICY = "lifetimePolicy";
- String NAME = "name";
String STATE = "state";
String TIME_TO_LIVE = "timeToLive";
String TYPE = "type";
@@ -152,11 +188,11 @@ public interface VirtualHost extends ConfiguredObject
public static interface Transaction
{
- void dequeue(QueueEntry entry);
+ void dequeue(MessageInstance entry);
- void copy(QueueEntry entry, Queue queue);
+ void copy(MessageInstance entry, Queue queue);
- void move(QueueEntry entry, Queue queue);
+ void move(MessageInstance entry, Queue queue);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java
index 696c59783e..cf6874030b 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java
@@ -22,33 +22,32 @@ package org.apache.qpid.server.model.adapter;
import java.util.Map;
import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.Consumer;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.Statistics;
import org.apache.qpid.server.model.UUIDGenerator;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.consumer.Consumer;
import java.security.AccessControlException;
import java.util.Collection;
import java.util.Collections;
-public class ConsumerAdapter extends AbstractAdapter implements Consumer
+public class ConsumerAdapter extends AbstractAdapter implements org.apache.qpid.server.model.Consumer
{
- private final Subscription _subscription;
+ private final Consumer _consumer;
private final QueueAdapter _queue;
private final SessionAdapter _session;
private final ConsumerStatistics _statistics;
public ConsumerAdapter(final QueueAdapter queueAdapter, final SessionAdapter sessionAdapter,
- final Subscription subscription)
+ final Consumer consumer)
{
super(UUIDGenerator.generateConsumerUUID(queueAdapter.getVirtualHost().getName(),
queueAdapter.getName(),
- subscription.getSessionModel().getConnectionModel().getRemoteAddressString(),
- String.valueOf(subscription.getSessionModel().getChannelId()),
- subscription.getConsumerName()), queueAdapter.getTaskExecutor());
- _subscription = subscription;
+ consumer.getSessionModel().getConnectionModel().getRemoteAddressString(),
+ String.valueOf(consumer.getSessionModel().getChannelId()),
+ consumer.getName()), queueAdapter.getTaskExecutor());
+ _consumer = consumer;
_queue = queueAdapter;
_session = sessionAdapter;
_statistics = new ConsumerStatistics();
@@ -57,7 +56,7 @@ public class ConsumerAdapter extends AbstractAdapter implements Consumer
public String getName()
{
- return _subscription.getConsumerName();
+ return _consumer.getName();
}
public String setName(final String currentName, final String desiredName)
@@ -107,7 +106,7 @@ public class ConsumerAdapter extends AbstractAdapter implements Consumer
@Override
public Collection<String> getAttributeNames()
{
- return Consumer.AVAILABLE_ATTRIBUTES;
+ return org.apache.qpid.server.model.Consumer.AVAILABLE_ATTRIBUTES;
}
@Override
@@ -147,7 +146,7 @@ public class ConsumerAdapter extends AbstractAdapter implements Consumer
}
else if(DISTRIBUTION_MODE.equals(name))
{
- return _subscription.acquires() ? "MOVE" : "COPY";
+ return _consumer.acquires() ? "MOVE" : "COPY";
}
else if(SETTLEMENT_MODE.equals(name))
{
@@ -197,11 +196,11 @@ public class ConsumerAdapter extends AbstractAdapter implements Consumer
{
if(name.equals(BYTES_OUT))
{
- return _subscription.getBytesOut();
+ return _consumer.getBytesOut();
}
else if(name.equals(MESSAGES_OUT))
{
- return _subscription.getMessagesOut();
+ return _consumer.getMessagesOut();
}
else if(name.equals(STATE_CHANGED))
{
@@ -209,11 +208,11 @@ public class ConsumerAdapter extends AbstractAdapter implements Consumer
}
else if(name.equals(UNACKNOWLEDGED_BYTES))
{
- return _subscription.getUnacknowledgedBytes();
+ return _consumer.getUnacknowledgedBytes();
}
else if(name.equals(UNACKNOWLEDGED_MESSAGES))
{
- return _subscription.getUnacknowledgedMessages();
+ return _consumer.getUnacknowledgedMessages();
}
return null; // TODO - Implement
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java
index 074f7c243b..e2c29ede51 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java
@@ -26,16 +26,15 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQStoreException;
import org.apache.qpid.server.binding.Binding;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObjectFinder;
-import org.apache.qpid.server.model.Consumer;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.IllegalStateTransitionException;
import org.apache.qpid.server.model.LifetimePolicy;
@@ -47,10 +46,12 @@ import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.*;
import org.apache.qpid.server.store.DurableConfigurationStoreHelper;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.util.MapValueConverter;
-final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.SubscriptionRegistrationListener, AMQQueue.NotificationListener
+final class QueueAdapter<Q extends AMQQueue<?,Q,?>> extends AbstractAdapter implements Queue,
+ MessageSource.ConsumerRegistrationListener<Q>,
+ AMQQueue.NotificationListener
{
@SuppressWarnings("serial")
static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{
@@ -66,25 +67,26 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
put(DESCRIPTION, String.class);
}});
- private final AMQQueue _queue;
+ private final AMQQueue<?,Q,?> _queue;
+
private final Map<Binding, BindingAdapter> _bindingAdapters =
new HashMap<Binding, BindingAdapter>();
- private Map<org.apache.qpid.server.subscription.Subscription, ConsumerAdapter> _consumerAdapters =
- new HashMap<org.apache.qpid.server.subscription.Subscription, ConsumerAdapter>();
+ private final Map<Consumer, ConsumerAdapter> _consumerAdapters =
+ new HashMap<Consumer, ConsumerAdapter>();
private final VirtualHostAdapter _vhost;
private QueueStatisticsAdapter _statistics;
private QueueNotificationListener _queueNotificationListener;
- public QueueAdapter(final VirtualHostAdapter virtualHostAdapter, final AMQQueue queue)
+ public QueueAdapter(final VirtualHostAdapter virtualHostAdapter, final AMQQueue<?,Q,?> queue)
{
super(queue.getId(), virtualHostAdapter.getTaskExecutor());
_vhost = virtualHostAdapter;
addParent(org.apache.qpid.server.model.VirtualHost.class, virtualHostAdapter);
_queue = queue;
- _queue.addSubscriptionRegistrationListener(this);
+ _queue.addConsumerRegistrationListener(this);
populateConsumers();
_statistics = new QueueStatisticsAdapter(queue);
_queue.setNotificationListener(this);
@@ -124,21 +126,20 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
private void populateConsumers()
{
- Collection<org.apache.qpid.server.subscription.Subscription> actualSubscriptions = _queue.getConsumers();
+ Collection<? extends Consumer> actualConsumers = _queue.getConsumers();
synchronized (_consumerAdapters)
{
- Iterator<org.apache.qpid.server.subscription.Subscription> iter = _consumerAdapters.keySet().iterator();
- for(org.apache.qpid.server.subscription.Subscription subscription : actualSubscriptions)
+ for(Consumer consumer : actualConsumers)
{
- if(!_consumerAdapters.containsKey(subscription))
+ if(!_consumerAdapters.containsKey(consumer))
{
- SessionAdapter sessionAdapter = getSessionAdapter(subscription.getSessionModel());
- ConsumerAdapter adapter = new ConsumerAdapter(this, sessionAdapter, subscription);
- _consumerAdapters.put(subscription, adapter);
+ SessionAdapter sessionAdapter = getSessionAdapter(consumer.getSessionModel());
+ ConsumerAdapter adapter = new ConsumerAdapter(this, sessionAdapter, consumer);
+ _consumerAdapters.put(consumer, adapter);
if (sessionAdapter != null)
{ // Register ConsumerAdapter with the SessionAdapter.
- sessionAdapter.subscriptionRegistered(subscription, adapter);
+ sessionAdapter.consumerRegistered(consumer, adapter);
}
}
}
@@ -153,11 +154,11 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
}
}
- public Collection<Consumer> getConsumers()
+ public Collection<org.apache.qpid.server.model.Consumer> getConsumers()
{
synchronized (_consumerAdapters)
{
- return new ArrayList<Consumer>(_consumerAdapters.values());
+ return new ArrayList<org.apache.qpid.server.model.Consumer>(_consumerAdapters.values());
}
}
@@ -321,7 +322,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
{
// TODO
}
- else if(TYPE.equals(name))
+ else if(QUEUE_TYPE.equals(name))
{
// TODO
}
@@ -396,9 +397,10 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
}
else if(LVQ_KEY.equals(name))
{
- if(_queue instanceof ConflationQueue)
+ AMQQueue queue = _queue;
+ if(queue instanceof ConflationQueue)
{
- return ((ConflationQueue)_queue).getConflationKey();
+ return ((ConflationQueue)queue).getConflationKey();
}
}
else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name))
@@ -427,22 +429,24 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
}
else if(SORT_KEY.equals(name))
{
- if(_queue instanceof SortedQueue)
+ AMQQueue queue = _queue;
+ if(queue instanceof SortedQueue)
{
- return ((SortedQueue)_queue).getSortedPropertyName();
+ return ((SortedQueue)queue).getSortedPropertyName();
}
}
- else if(TYPE.equals(name))
+ else if(QUEUE_TYPE.equals(name))
{
- if(_queue instanceof SortedQueue)
+ AMQQueue queue = _queue;
+ if(queue instanceof SortedQueue)
{
return "sorted";
}
- if(_queue instanceof ConflationQueue)
+ if(queue instanceof ConflationQueue)
{
return "lvq";
}
- if(_queue instanceof AMQPriorityQueue)
+ if(queue instanceof PriorityQueue)
{
return "priority";
}
@@ -486,9 +490,10 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
}
else if(PRIORITIES.equals(name))
{
- if(_queue instanceof AMQPriorityQueue)
+ AMQQueue queue = _queue;
+ if(queue instanceof PriorityQueue)
{
- return ((AMQPriorityQueue)_queue).getPriorities();
+ return ((PriorityQueue)queue).getPriorities();
}
}
return super.getAttribute(name);
@@ -502,7 +507,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
@Override
public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
{
- if(clazz == Consumer.class)
+ if(clazz == org.apache.qpid.server.model.Consumer.class)
{
return (Collection<C>) getConsumers();
}
@@ -587,19 +592,19 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
return _queue;
}
- public void subscriptionRegistered(final AMQQueue queue, final Subscription subscription)
+ public void consumerAdded(final AMQQueue queue, final Consumer consumer)
{
ConsumerAdapter adapter = null;
synchronized (_consumerAdapters)
{
- if(!_consumerAdapters.containsKey(subscription))
+ if(!_consumerAdapters.containsKey(consumer))
{
- SessionAdapter sessionAdapter = getSessionAdapter(subscription.getSessionModel());
- adapter = new ConsumerAdapter(this, sessionAdapter, subscription);
- _consumerAdapters.put(subscription, adapter);
+ SessionAdapter sessionAdapter = getSessionAdapter(consumer.getSessionModel());
+ adapter = new ConsumerAdapter(this, sessionAdapter, consumer);
+ _consumerAdapters.put(consumer, adapter);
if (sessionAdapter != null)
{ // Register ConsumerAdapter with the SessionAdapter.
- sessionAdapter.subscriptionRegistered(subscription, adapter);
+ sessionAdapter.consumerRegistered(consumer, adapter);
}
}
}
@@ -609,20 +614,20 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
}
}
- public void subscriptionUnregistered(final AMQQueue queue, final Subscription subscription)
+ public void consumerRemoved(final AMQQueue queue, final Consumer consumer)
{
ConsumerAdapter adapter = null;
synchronized (_consumerAdapters)
{
- adapter = _consumerAdapters.remove(subscription);
+ adapter = _consumerAdapters.remove(consumer);
}
if(adapter != null)
{
- SessionAdapter sessionAdapter = getSessionAdapter(subscription.getSessionModel());
+ SessionAdapter sessionAdapter = getSessionAdapter(consumer.getSessionModel());
if (sessionAdapter != null)
{ // Unregister ConsumerAdapter with the SessionAdapter.
- sessionAdapter.subscriptionUnregistered(subscription);
+ sessionAdapter.consumerUnregistered(consumer);
}
childRemoved(adapter);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
index 31ce7e56fd..6b76eeefa0 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
@@ -34,9 +34,8 @@ import org.apache.qpid.server.model.Publisher;
import org.apache.qpid.server.model.Session;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.Statistics;
-import org.apache.qpid.server.model.Consumer;
import org.apache.qpid.server.model.UUIDGenerator;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.protocol.AMQSessionModel;
@@ -47,7 +46,7 @@ final class SessionAdapter extends AbstractAdapter implements Session
private AMQSessionModel _session;
private SessionStatistics _statistics;
- private Map<Subscription, ConsumerAdapter> _consumerAdapters = new HashMap<Subscription, ConsumerAdapter>();
+ private Map<Consumer, ConsumerAdapter> _consumerAdapters = new HashMap<Consumer, ConsumerAdapter>();
public SessionAdapter(final AMQSessionModel session, TaskExecutor taskExecutor)
{
@@ -56,11 +55,11 @@ final class SessionAdapter extends AbstractAdapter implements Session
_statistics = new SessionStatistics();
}
- public Collection<Consumer> getSubscriptions()
+ public Collection<org.apache.qpid.server.model.Consumer> getConsumers()
{
synchronized (_consumerAdapters)
{
- return new ArrayList<Consumer>(_consumerAdapters.values());
+ return new ArrayList<org.apache.qpid.server.model.Consumer>(_consumerAdapters.values());
}
}
@@ -119,29 +118,29 @@ final class SessionAdapter extends AbstractAdapter implements Session
}
/**
- * Register a ConsumerAdapter (Subscription) with this Session keyed by the Subscription.
- * @param subscription the org.apache.qpid.server.subscription.Subscription used to key the ConsumerAdapter.
+ * Register a ConsumerAdapter with this Session keyed by the Consumer.
+ * @param consumer the org.apache.qpid.server.consumer.Consumer used to key the ConsumerAdapter.
* @param adapter the registered ConsumerAdapter.
*/
- void subscriptionRegistered(Subscription subscription, ConsumerAdapter adapter)
+ void consumerRegistered(Consumer consumer, ConsumerAdapter adapter)
{
synchronized (_consumerAdapters)
{
- _consumerAdapters.put(subscription, adapter);
+ _consumerAdapters.put(consumer, adapter);
}
childAdded(adapter);
}
/**
- * Unregister a ConsumerAdapter (Subscription) with this Session keyed by the Subscription.
- * @param subscription the org.apache.qpid.server.subscription.Subscription used to key the ConsumerAdapter.
+ * Unregister a ConsumerAdapter with this Session keyed by the Consumer.
+ * @param consumer the org.apache.qpid.server.consumer.Consumer used to key the ConsumerAdapter.
*/
- void subscriptionUnregistered(Subscription subscription)
+ void consumerUnregistered(Consumer consumer)
{
ConsumerAdapter adapter = null;
synchronized (_consumerAdapters)
{
- adapter = _consumerAdapters.remove(subscription);
+ adapter = _consumerAdapters.remove(consumer);
}
if (adapter != null)
{
@@ -188,9 +187,9 @@ final class SessionAdapter extends AbstractAdapter implements Session
@Override
public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
{
- if(clazz == Consumer.class)
+ if(clazz == org.apache.qpid.server.model.Consumer.class)
{
- return (Collection<C>) getSubscriptions();
+ return (Collection<C>) getConsumers();
}
else if(clazz == Publisher.class)
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
index bda110c114..9016c2ac66 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
@@ -50,6 +50,7 @@ import org.apache.qpid.server.configuration.XmlConfigurationUtilities.MyConfigur
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.actors.BrokerActor;
import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
@@ -73,7 +74,6 @@ import org.apache.qpid.server.plugin.VirtualHostFactory;
import org.apache.qpid.server.protocol.AMQConnectionModel;
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.replication.ReplicationGroupListener;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.access.Operation;
@@ -203,7 +203,10 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
{
if(!_exchangeAdapters.containsKey(exchange))
{
- _exchangeAdapters.put(exchange, new ExchangeAdapter(this,exchange));
+ final ExchangeAdapter adapter = new ExchangeAdapter(this, exchange);
+ _exchangeAdapters.put(exchange, adapter);
+ childAdded(adapter);
+
}
}
}
@@ -221,7 +224,9 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
{
if(!_queueAdapters.containsKey(queue))
{
- _queueAdapters.put(queue, new QueueAdapter(this, queue));
+ final QueueAdapter adapter = new QueueAdapter(this, queue);
+ _queueAdapters.put(queue, adapter);
+ childAdded(adapter);
}
}
}
@@ -403,9 +408,9 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
{
attributes = new HashMap<String, Object>(attributes);
- if (attributes.containsKey(Queue.TYPE))
+ if (attributes.containsKey(Queue.QUEUE_TYPE))
{
- String typeAttribute = MapValueConverter.getStringAttribute(Queue.TYPE, attributes, null);
+ String typeAttribute = MapValueConverter.getStringAttribute(Queue.QUEUE_TYPE, attributes, null);
QueueType queueType = null;
try
{
@@ -791,11 +796,11 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
op.withinTransaction(new Transaction()
{
- public void dequeue(final QueueEntry entry)
+ public void dequeue(final MessageInstance entry)
{
if(entry.acquire())
{
- txn.dequeue(entry.getQueue(), entry.getMessage(), new ServerTransaction.Action()
+ txn.dequeue(entry.getOwningResource(), entry.getMessage(), new ServerTransaction.Action()
{
public void postCommit()
{
@@ -809,7 +814,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
}
}
- public void copy(QueueEntry entry, Queue queue)
+ public void copy(MessageInstance entry, Queue queue)
{
final ServerMessage message = entry.getMessage();
final AMQQueue toQueue = ((QueueAdapter)queue).getAMQQueue();
@@ -820,7 +825,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
{
try
{
- toQueue.enqueue(message);
+ toQueue.enqueue(message, null);
}
catch(AMQException e)
{
@@ -835,7 +840,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
}
- public void move(final QueueEntry entry, Queue queue)
+ public void move(final MessageInstance entry, Queue queue)
{
final ServerMessage message = entry.getMessage();
final AMQQueue toQueue = ((QueueAdapter)queue).getAMQQueue();
@@ -849,7 +854,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
{
try
{
- toQueue.enqueue(message);
+ toQueue.enqueue(message, null);
}
catch (AMQException e)
{
@@ -862,7 +867,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
entry.release();
}
});
- txn.dequeue(entry.getQueue(), message,
+ txn.dequeue(entry.getOwningResource(), message,
new ServerTransaction.Action()
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/MessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemNodeCreator.java
index 8ce4ce3344..5b371c0851 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/MessageGroupManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemNodeCreator.java
@@ -18,24 +18,21 @@
* under the License.
*
*/
-package org.apache.qpid.server.subscription;
+package org.apache.qpid.server.plugin;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.MessageNode;
+import org.apache.qpid.server.virtualhost.VirtualHost;
-public interface MessageGroupManager
+public interface SystemNodeCreator extends Pluggable
{
- public interface SubscriptionResetHelper
+ interface SystemNodeRegistry
{
- public void resetSubPointersForGroups(Subscription subscription, boolean clearAssignments);
+ void registerSystemNode(MessageNode node);
+ void removeSystemNode(MessageNode node);
- boolean isEntryAheadOfSubscription(QueueEntry entry, Subscription sub);
+ VirtualHost getVirtualHost();
+ org.apache.qpid.server.model.VirtualHost getVirtualHostModel();
}
- Subscription getAssignedSubscription(QueueEntry entry);
-
- boolean acceptMessage(Subscription sub, QueueEntry entry);
-
- QueueEntry findEarliestAssignedAvailableEntry(Subscription sub);
-
- void clearAssignments(Subscription sub);
+ void register(SystemNodeRegistry registry);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
index 75994f6d81..28fadd4162 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
@@ -27,12 +27,11 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
/**
* Session model interface.
* Extends {@link Comparable} to allow objects to be inserted into a {@link ConcurrentSkipListSet}
- * when monitoring the blocking and blocking of queues/sessions in {@link SimpleAMQQueue}.
+ * when monitoring the blocking and blocking of queues/sessions in {@link AMQQueue}.
*/
public interface AMQSessionModel extends Comparable<AMQSessionModel>
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/CapacityChecker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/CapacityChecker.java
new file mode 100644
index 0000000000..0ba3095243
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/CapacityChecker.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.protocol;
+
+public interface CapacityChecker
+{
+ void checkCapacity(AMQSessionModel channel);
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
index 0cddd1ed3b..76477a0a9b 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
@@ -26,19 +26,20 @@ import org.apache.qpid.server.configuration.QueueConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeReferrer;
import org.apache.qpid.server.logging.LogSubject;
-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.message.MessageDestination;
+import org.apache.qpid.server.message.MessageSource;
+import org.apache.qpid.server.protocol.CapacityChecker;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collection;
import java.util.List;
import java.util.Set;
-public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource, BaseQueue
+public interface AMQQueue<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, C extends Consumer>
+ extends Comparable<Q>, ExchangeReferrer, BaseQueue<C>, MessageSource<C,Q>, CapacityChecker, MessageDestination
{
- String getName();
public interface NotificationListener
{
@@ -65,45 +66,20 @@ public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, Transa
long getTotalEnqueueCount();
- public interface Context
- {
- QueueEntry getLastSeenEntry();
- }
-
void setNoLocal(boolean b);
boolean isAutoDelete();
String getOwner();
- AuthorizationHolder getAuthorizationHolder();
- void setAuthorizationHolder(AuthorizationHolder principalHolder);
-
- void setExclusiveOwningSession(AMQSessionModel owner);
- AMQSessionModel getExclusiveOwningSession();
VirtualHost getVirtualHost();
- void registerSubscription(final Subscription subscription, final boolean exclusive) throws AMQException;
-
- void unregisterSubscription(final Subscription subscription) throws AMQException;
-
- Collection<Subscription> getConsumers();
-
- interface SubscriptionRegistrationListener
- {
- void subscriptionRegistered(AMQQueue queue, Subscription subscription);
- void subscriptionUnregistered(AMQQueue queue, Subscription subscription);
- }
-
- void addSubscriptionRegistrationListener(SubscriptionRegistrationListener listener);
- void removeSubscriptionRegistrationListener(SubscriptionRegistrationListener listener);
-
int getConsumerCount();
int getActiveConsumerCount();
- boolean hasExclusiveSubscriber();
+ boolean hasExclusiveConsumer();
boolean isUnused();
@@ -111,41 +87,35 @@ public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, Transa
int getMessageCount();
- int getUndeliveredMessageCount();
-
long getQueueDepth();
- long getReceivedMessageCount();
-
long getOldestMessageArrivalTime();
boolean isDeleted();
int delete() throws AMQException;
- void requeue(QueueEntry entry);
+ void requeue(E entry);
- void dequeue(QueueEntry entry, Subscription sub);
+ void dequeue(E entry);
- void decrementUnackedMsgCount(QueueEntry queueEntry);
+ void decrementUnackedMsgCount(E queueEntry);
- boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException;
+ boolean resend(final E entry, final C consumer) throws AMQException;
- void addQueueDeleteTask(final Task task);
- void removeQueueDeleteTask(final Task task);
+ void addQueueDeleteTask(Action<AMQQueue> task);
+ void removeQueueDeleteTask(Action<AMQQueue> task);
- List<QueueEntry> getMessagesOnTheQueue();
-
- List<QueueEntry> getMessagesOnTheQueue(long fromMessageId, long toMessageId);
+ List<E> getMessagesOnTheQueue();
List<Long> getMessagesOnTheQueue(int num);
List<Long> getMessagesOnTheQueue(int num, int offset);
- QueueEntry getMessageOnTheQueue(long messageId);
+ E getMessageOnTheQueue(long messageId);
/**
* Returns a list of QueEntries from a given range of queue positions, eg messages 5 to 10 on the queue.
@@ -156,9 +126,9 @@ public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, Transa
* @param toPosition
* @return
*/
- public List<QueueEntry> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition);
+ public List<E> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition);
- void visit(QueueEntryVisitor visitor);
+ void visit(QueueEntryVisitor<E> visitor);
long getMaximumMessageSize();
@@ -209,16 +179,10 @@ public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, Transa
Set<NotificationCheck> getNotificationChecks();
- void flushSubscription(final Subscription sub) throws AMQException;
-
- void deliverAsync(final Subscription sub);
-
void deliverAsync();
void stop();
- boolean isExclusive();
-
Exchange getAlternateExchange();
void setAlternateExchange(Exchange exchange);
@@ -226,56 +190,6 @@ public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, Transa
Collection<String> getAvailableAttributes();
Object getAttribute(String attrName);
- void checkCapacity(AMQSessionModel channel);
-
- /**
- * ExistingExclusiveSubscription signals a failure to create a subscription, because an exclusive subscription
- * already exists.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represent failure to create a subscription, because an exclusive subscription already exists.
- * </table>
- *
- * @todo Not an AMQP exception as no status code.
- *
- * @todo Move to top level, used outside this class.
- */
- static final class ExistingExclusiveSubscription extends AMQException
- {
-
- public ExistingExclusiveSubscription()
- {
- super("");
- }
- }
-
- /**
- * ExistingSubscriptionPreventsExclusive signals a failure to create an exclusive subscription, as a subscription
- * already exists.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represent failure to create an exclusive subscription, as a subscription already exists.
- * </table>
- *
- * @todo Not an AMQP exception as no status code.
- *
- * @todo Move to top level, used outside this class.
- */
- static final class ExistingSubscriptionPreventsExclusive extends AMQException
- {
- public ExistingSubscriptionPreventsExclusive()
- {
- super("");
- }
- }
-
- static interface Task
- {
- public void doTask(AMQQueue queue) throws AMQException;
- }
-
void configure(QueueConfiguration config);
void setExclusive(boolean exclusive);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
index 38c205bc00..4e0a9048e1 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
@@ -288,11 +288,11 @@ public class AMQQueueFactory implements QueueFactory
}
else if(priorities > 1)
{
- q = new AMQPriorityQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments, priorities);
+ q = new PriorityQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments, priorities);
}
else
{
- q = new SimpleAMQQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments);
+ q = new StandardQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments);
}
q.setDeleteOnNoConsumers(deleteOnNoConsumer);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AssignedConsumerMessageGroupManager.java
index ae7e11afa4..efc82c0ab4 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AssignedConsumerMessageGroupManager.java
@@ -18,28 +18,26 @@
* under the License.
*
*/
-package org.apache.qpid.server.subscription;
+package org.apache.qpid.server.queue;
-import org.apache.qpid.server.queue.QueueEntryVisitor;
+import org.apache.qpid.server.consumer.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.server.queue.QueueEntry;
-
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
-public class AssignedSubscriptionMessageGroupManager implements MessageGroupManager
+public class AssignedConsumerMessageGroupManager<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements MessageGroupManager<E,Q,L>
{
- private static final Logger _logger = LoggerFactory.getLogger(AssignedSubscriptionMessageGroupManager.class);
+ private static final Logger _logger = LoggerFactory.getLogger(AssignedConsumerMessageGroupManager.class);
private final String _groupId;
- private final ConcurrentHashMap<Integer, Subscription> _groupMap = new ConcurrentHashMap<Integer, Subscription>();
+ private final ConcurrentHashMap<Integer, QueueConsumer> _groupMap = new ConcurrentHashMap<Integer, QueueConsumer>();
private final int _groupMask;
- public AssignedSubscriptionMessageGroupManager(final String groupId, final int maxGroups)
+ public AssignedConsumerMessageGroupManager(final String groupId, final int maxGroups)
{
_groupId = groupId;
_groupMask = pow2(maxGroups)-1;
@@ -55,25 +53,18 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
return val;
}
- public Subscription getAssignedSubscription(final QueueEntry entry)
+ public QueueConsumer getAssignedConsumer(final E entry)
{
Object groupVal = entry.getMessage().getMessageHeader().getHeader(_groupId);
return groupVal == null ? null : _groupMap.get(groupVal.hashCode() & _groupMask);
}
- public boolean acceptMessage(Subscription sub, QueueEntry entry)
+ public boolean acceptMessage(QueueConsumer<?,E,Q,L> sub, E entry)
{
- if(assignMessage(sub, entry))
- {
- return entry.acquire(sub);
- }
- else
- {
- return false;
- }
+ return assignMessage(sub, entry) && entry.acquire(sub);
}
- private boolean assignMessage(Subscription sub, QueueEntry entry)
+ private boolean assignMessage(QueueConsumer sub, E entry)
{
Object groupVal = entry.getMessage().getMessageHeader().getHeader(_groupId);
if(groupVal == null)
@@ -83,7 +74,7 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
else
{
Integer group = groupVal.hashCode() & _groupMask;
- Subscription assignedSub = _groupMap.get(group);
+ QueueConsumer assignedSub = _groupMap.get(group);
if(assignedSub == sub)
{
return true;
@@ -107,24 +98,24 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
}
}
- public QueueEntry findEarliestAssignedAvailableEntry(Subscription sub)
+ public E findEarliestAssignedAvailableEntry(QueueConsumer sub)
{
EntryFinder visitor = new EntryFinder(sub);
sub.getQueue().visit(visitor);
return visitor.getEntry();
}
- private class EntryFinder implements QueueEntryVisitor
+ private class EntryFinder implements QueueEntryVisitor<E>
{
- private QueueEntry _entry;
- private Subscription _sub;
+ private E _entry;
+ private QueueConsumer _sub;
- public EntryFinder(final Subscription sub)
+ public EntryFinder(final QueueConsumer sub)
{
_sub = sub;
}
- public boolean visit(final QueueEntry entry)
+ public boolean visit(final E entry)
{
if(!entry.isAvailable())
{
@@ -138,7 +129,7 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
}
Integer group = groupId.hashCode() & _groupMask;
- Subscription assignedSub = _groupMap.get(group);
+ Consumer assignedSub = _groupMap.get(group);
if(assignedSub == _sub)
{
_entry = entry;
@@ -150,15 +141,15 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
}
}
- public QueueEntry getEntry()
+ public E getEntry()
{
return _entry;
}
}
- public void clearAssignments(Subscription sub)
+ public void clearAssignments(QueueConsumer sub)
{
- Iterator<Subscription> subIter = _groupMap.values().iterator();
+ Iterator<QueueConsumer> subIter = _groupMap.values().iterator();
while(subIter.hasNext())
{
if(subIter.next() == sub)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java
index 7aba1a2342..31c54dcdd2 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java
@@ -22,19 +22,15 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.util.Action;
-public interface BaseQueue extends TransactionLogResource
+public interface BaseQueue<C extends Consumer> extends TransactionLogResource
{
- public static interface PostEnqueueAction
- {
- public void onEnqueue(QueueEntry entry);
- }
-
- void enqueue(ServerMessage message) throws AMQException;
- void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException;
- void enqueue(ServerMessage message, boolean transactional, PostEnqueueAction action) throws AMQException;
+ void enqueue(ServerMessage message, Action<? super MessageInstance<?,C>> action) throws AMQException;
boolean isDurable();
boolean isDeleted();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java
index c2813bb7a5..a1ff51959c 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java
@@ -26,7 +26,7 @@ import java.util.UUID;
import org.apache.qpid.server.virtualhost.VirtualHost;
-public class ConflationQueue extends SimpleAMQQueue
+public class ConflationQueue extends SimpleAMQQueue<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList>
{
protected ConflationQueue(UUID id,
String name,
@@ -42,7 +42,7 @@ public class ConflationQueue extends SimpleAMQQueue
public String getConflationKey()
{
- return ((ConflationQueueList) getEntries()).getConflationKey();
+ return getEntries().getConflationKey();
}
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java
index e4725e0e2a..a98a4ac144 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java
@@ -32,23 +32,38 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
-public class ConflationQueueList extends SimpleQueueEntryList
+public class ConflationQueueList extends OrderedQueueEntryList<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList>
{
private static final Logger LOGGER = LoggerFactory.getLogger(ConflationQueueList.class);
+ private static final HeadCreator<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList> HEAD_CREATOR = new HeadCreator<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList>()
+ {
+
+ @Override
+ public ConflationQueueEntry createHead(final ConflationQueueList list)
+ {
+ return list.createHead();
+ }
+ };
+
private final String _conflationKey;
- private final ConcurrentHashMap<Object, AtomicReference<QueueEntry>> _latestValuesMap =
- new ConcurrentHashMap<Object, AtomicReference<QueueEntry>>();
+ private final ConcurrentHashMap<Object, AtomicReference<ConflationQueueEntry>> _latestValuesMap =
+ new ConcurrentHashMap<Object, AtomicReference<ConflationQueueEntry>>();
- private final QueueEntry _deleteInProgress = new SimpleQueueEntryImpl(this);
- private final QueueEntry _newerEntryAlreadyBeenAndGone = new SimpleQueueEntryImpl(this);
+ private final ConflationQueueEntry _deleteInProgress = new ConflationQueueEntry(this);
+ private final ConflationQueueEntry _newerEntryAlreadyBeenAndGone = new ConflationQueueEntry(this);
- public ConflationQueueList(AMQQueue queue, String conflationKey)
+ public ConflationQueueList(ConflationQueue queue, String conflationKey)
{
- super(queue);
+ super(queue, HEAD_CREATOR);
_conflationKey = conflationKey;
}
+ private ConflationQueueEntry createHead()
+ {
+ return new ConflationQueueEntry(this);
+ }
+
public String getConflationKey()
{
return _conflationKey;
@@ -66,7 +81,7 @@ public class ConflationQueueList extends SimpleQueueEntryList
@Override
public ConflationQueueEntry add(final ServerMessage message)
{
- final ConflationQueueEntry addedEntry = (ConflationQueueEntry) (super.add(message));
+ final ConflationQueueEntry addedEntry = super.add(message);
final Object keyValue = message.getMessageHeader().getHeader(_conflationKey);
if (keyValue != null)
@@ -76,14 +91,14 @@ public class ConflationQueueList extends SimpleQueueEntryList
LOGGER.debug("Adding entry " + addedEntry + " for message " + message.getMessageNumber() + " with conflation key " + keyValue);
}
- final AtomicReference<QueueEntry> referenceToEntry = new AtomicReference<QueueEntry>(addedEntry);
- AtomicReference<QueueEntry> entryReferenceFromMap = null;
- QueueEntry entryFromMap;
+ final AtomicReference<ConflationQueueEntry> referenceToEntry = new AtomicReference<ConflationQueueEntry>(addedEntry);
+ AtomicReference<ConflationQueueEntry> entryReferenceFromMap;
+ ConflationQueueEntry entryFromMap;
// Iterate until we have got a valid atomic reference object and either the referent is newer than the current
// entry, or the current entry has replaced it in the reference. Note that the _deletedEntryPlaceholder is a special value
// indicating that the reference object is no longer valid (it is being removed from the map).
- boolean keepTryingToUpdateEntryReference = true;
+ boolean keepTryingToUpdateEntryReference;
do
{
do
@@ -139,16 +154,16 @@ public class ConflationQueueList extends SimpleQueueEntryList
* adds and removes during execution of this method.</li>
* </ul>
*/
- private AtomicReference<QueueEntry> getOrPutIfAbsent(final Object key, final AtomicReference<QueueEntry> referenceToAddedValue)
+ private AtomicReference<ConflationQueueEntry> getOrPutIfAbsent(final Object key, final AtomicReference<ConflationQueueEntry> referenceToAddedValue)
{
- AtomicReference<QueueEntry> latestValueReference = _latestValuesMap.putIfAbsent(key, referenceToAddedValue);
+ AtomicReference<ConflationQueueEntry> latestValueReference = _latestValuesMap.putIfAbsent(key, referenceToAddedValue);
if(latestValueReference == null)
{
latestValueReference = _latestValuesMap.get(key);
if(latestValueReference == null)
{
- return new AtomicReference<QueueEntry>(_newerEntryAlreadyBeenAndGone);
+ return new AtomicReference<ConflationQueueEntry>(_newerEntryAlreadyBeenAndGone);
}
}
return latestValueReference;
@@ -177,12 +192,17 @@ public class ConflationQueueList extends SimpleQueueEntryList
}
}
- private final class ConflationQueueEntry extends SimpleQueueEntryImpl
+ final class ConflationQueueEntry extends OrderedQueueEntry<ConflationQueueEntry, ConflationQueue, ConflationQueueList>
{
- private AtomicReference<QueueEntry> _latestValueReference;
+ private AtomicReference<ConflationQueueEntry> _latestValueReference;
+
+ private ConflationQueueEntry(final ConflationQueueList queueEntryList)
+ {
+ super(queueEntryList);
+ }
- public ConflationQueueEntry(SimpleQueueEntryList queueEntryList, ServerMessage message)
+ public ConflationQueueEntry(ConflationQueueList queueEntryList, ServerMessage message)
{
super(queueEntryList, message);
}
@@ -206,7 +226,7 @@ public class ConflationQueueList extends SimpleQueueEntryList
}
- public void setLatestValueReference(final AtomicReference<QueueEntry> latestValueReference)
+ public void setLatestValueReference(final AtomicReference<ConflationQueueEntry> latestValueReference)
{
_latestValueReference = latestValueReference;
}
@@ -227,12 +247,12 @@ public class ConflationQueueList extends SimpleQueueEntryList
/**
* Exposed purposes of unit test only.
*/
- Map<Object, AtomicReference<QueueEntry>> getLatestValuesMap()
+ Map<Object, AtomicReference<ConflationQueueEntry>> getLatestValuesMap()
{
return Collections.unmodifiableMap(_latestValuesMap);
}
- static class Factory implements QueueEntryListFactory
+ static class Factory implements QueueEntryListFactory<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList>
{
private final String _conflationKey;
@@ -241,7 +261,8 @@ public class ConflationQueueList extends SimpleQueueEntryList
_conflationKey = conflationKey;
}
- public ConflationQueueList createQueueEntryList(AMQQueue queue)
+ @Override
+ public ConflationQueueList createQueueEntryList(final ConflationQueue queue)
{
return new ConflationQueueList(queue, _conflationKey);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java
index 55110c46de..e67591ae07 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java
@@ -18,43 +18,44 @@
* under the License.
*
*/
-package org.apache.qpid.server.subscription;
+package org.apache.qpid.server.queue;
-import org.apache.qpid.server.queue.QueueEntryVisitor;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.util.StateChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.queue.QueueEntry;
import java.util.HashMap;
import java.util.Map;
-public class DefinedGroupMessageGroupManager implements MessageGroupManager
+public class DefinedGroupMessageGroupManager<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements MessageGroupManager<E,Q,L>
{
private static final Logger _logger = LoggerFactory.getLogger(DefinedGroupMessageGroupManager.class);
private final String _groupId;
private final String _defaultGroup;
private final Map<Object, Group> _groupMap = new HashMap<Object, Group>();
- private final SubscriptionResetHelper _resetHelper;
+ private final ConsumerResetHelper<E,Q,L> _resetHelper;
private final class Group
{
private final Object _group;
- private Subscription _subscription;
+ private QueueConsumer<?,E,Q,L> _consumer;
private int _activeCount;
- private Group(final Object key, final Subscription subscription)
+ private Group(final Object key, final QueueConsumer<?,E,Q,L> consumer)
{
_group = key;
- _subscription = subscription;
+ _consumer = consumer;
}
public boolean add()
{
- if(_subscription != null)
+ if(_consumer != null)
{
_activeCount++;
return true;
@@ -69,8 +70,8 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
{
if(--_activeCount == 0)
{
- _resetHelper.resetSubPointersForGroups(_subscription, false);
- _subscription = null;
+ _resetHelper.resetSubPointersForGroups(_consumer, false);
+ _consumer = null;
_groupMap.remove(_group);
}
}
@@ -100,12 +101,12 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
public boolean isValid()
{
- return !(_subscription == null || (_activeCount == 0 && _subscription.isClosed()));
+ return !(_consumer == null || (_activeCount == 0 && _consumer.isClosed()));
}
- public Subscription getSubscription()
+ public QueueConsumer<?,E,Q,L> getConsumer()
{
- return _subscription;
+ return _consumer;
}
@Override
@@ -113,40 +114,33 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
{
return "Group{" +
"_group=" + _group +
- ", _subscription=" + _subscription +
+ ", _consumer=" + _consumer +
", _activeCount=" + _activeCount +
'}';
}
}
- public DefinedGroupMessageGroupManager(final String groupId, String defaultGroup, SubscriptionResetHelper resetHelper)
+ public DefinedGroupMessageGroupManager(final String groupId, String defaultGroup, ConsumerResetHelper<E,Q,L> resetHelper)
{
_groupId = groupId;
_defaultGroup = defaultGroup;
_resetHelper = resetHelper;
}
- public synchronized Subscription getAssignedSubscription(final QueueEntry entry)
+ public synchronized QueueConsumer<?,E,Q,L> getAssignedConsumer(final E entry)
{
Object groupId = getKey(entry);
Group group = _groupMap.get(groupId);
- return group == null || !group.isValid() ? null : group.getSubscription();
+ return group == null || !group.isValid() ? null : group.getConsumer();
}
- public synchronized boolean acceptMessage(final Subscription sub, final QueueEntry entry)
+ public synchronized boolean acceptMessage(final QueueConsumer<?,E,Q,L> sub, final E entry)
{
- if(assignMessage(sub, entry))
- {
- return entry.acquire(sub);
- }
- else
- {
- return false;
- }
+ return assignMessage(sub, entry) && entry.acquire(sub);
}
- private boolean assignMessage(final Subscription sub, final QueueEntry entry)
+ private boolean assignMessage(final QueueConsumer<?,E,Q,L> sub, final E entry)
{
Object groupId = getKey(entry);
Group group = _groupMap.get(groupId);
@@ -158,19 +152,19 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
_groupMap.put(groupId, group);
// there's a small change that the group became empty between the point at which getNextAvailable() was
- // called on the subscription, and when accept message is called... in that case we want to avoid delivering
+ // called on the consumer, and when accept message is called... in that case we want to avoid delivering
// out of order
- if(_resetHelper.isEntryAheadOfSubscription(entry, sub))
+ if(_resetHelper.isEntryAheadOfConsumer(entry, sub))
{
return false;
}
}
- Subscription assignedSub = group.getSubscription();
+ Consumer assignedSub = group.getConsumer();
if(assignedSub == sub)
{
- entry.addStateChangeListener(new GroupStateChangeListener(group, entry));
+ entry.addStateChangeListener(new GroupStateChangeListener(group));
return true;
}
else
@@ -179,24 +173,24 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
}
}
- public synchronized QueueEntry findEarliestAssignedAvailableEntry(final Subscription sub)
+ public synchronized E findEarliestAssignedAvailableEntry(final QueueConsumer<?,E,Q,L> sub)
{
EntryFinder visitor = new EntryFinder(sub);
sub.getQueue().visit(visitor);
return visitor.getEntry();
}
- private class EntryFinder implements QueueEntryVisitor
+ private class EntryFinder implements QueueEntryVisitor<E>
{
- private QueueEntry _entry;
- private Subscription _sub;
+ private E _entry;
+ private QueueConsumer _sub;
- public EntryFinder(final Subscription sub)
+ public EntryFinder(final QueueConsumer sub)
{
_sub = sub;
}
- public boolean visit(final QueueEntry entry)
+ public boolean visit(final E entry)
{
if(!entry.isAvailable())
{
@@ -206,7 +200,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
Object groupId = getKey(entry);
Group group = _groupMap.get(groupId);
- if(group != null && group.getSubscription() == _sub)
+ if(group != null && group.getConsumer() == _sub)
{
_entry = entry;
return true;
@@ -217,18 +211,18 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
}
}
- public QueueEntry getEntry()
+ public E getEntry()
{
return _entry;
}
}
- public void clearAssignments(final Subscription sub)
+ public void clearAssignments(final QueueConsumer sub)
{
}
- private Object getKey(QueueEntry entry)
+ private Object getKey(E entry)
{
ServerMessage message = entry.getMessage();
AMQMessageHeader messageHeader = message == null ? null : message.getMessageHeader();
@@ -240,19 +234,18 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
return groupVal;
}
- private class GroupStateChangeListener implements QueueEntry.StateChangeListener
+ private class GroupStateChangeListener implements StateChangeListener<MessageInstance<?, ? extends QueueConsumer>, QueueEntry.State>
{
private final Group _group;
- public GroupStateChangeListener(final Group group,
- final QueueEntry entry)
+ public GroupStateChangeListener(final Group group)
{
_group = group;
}
- public void stateChanged(final QueueEntry entry,
- final QueueEntry.State oldState,
- final QueueEntry.State newState)
+ public void stateChanged(final MessageInstance<?, ? extends QueueConsumer> entry,
+ final MessageInstance.State oldState,
+ final MessageInstance.State newState)
{
synchronized (DefinedGroupMessageGroupManager.this)
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java
new file mode 100644
index 0000000000..ba9dbc8a70
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.queue;
+
+public interface MessageGroupManager<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>>
+{
+ public interface ConsumerResetHelper<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>>
+ {
+ public void resetSubPointersForGroups(QueueConsumer<?,E,Q,L> consumer, boolean clearAssignments);
+
+ boolean isEntryAheadOfConsumer(E entry, QueueConsumer<?,E,Q,L> sub);
+ }
+
+ QueueConsumer getAssignedConsumer(E entry);
+
+ boolean acceptMessage(QueueConsumer<?,E,Q,L> sub, E entry);
+
+ E findEarliestAssignedAvailableEntry(QueueConsumer<?,E,Q,L> sub);
+
+ void clearAssignments(QueueConsumer sub);
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntry.java
index 251a1f55ed..369f42b183 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntry.java
@@ -24,46 +24,46 @@ import org.apache.qpid.server.message.ServerMessage;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-public class SimpleQueueEntryImpl extends QueueEntryImpl
+public abstract class OrderedQueueEntry<E extends OrderedQueueEntry<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends OrderedQueueEntryList<E,Q,L>> extends QueueEntryImpl<E,Q,L>
{
- static final AtomicReferenceFieldUpdater<SimpleQueueEntryImpl, SimpleQueueEntryImpl>
+ static final AtomicReferenceFieldUpdater<OrderedQueueEntry, OrderedQueueEntry>
_nextUpdater =
AtomicReferenceFieldUpdater.newUpdater
- (SimpleQueueEntryImpl.class, SimpleQueueEntryImpl.class, "_next");
+ (OrderedQueueEntry.class, OrderedQueueEntry.class, "_next");
- private volatile SimpleQueueEntryImpl _next;
+ private volatile E _next;
- public SimpleQueueEntryImpl(SimpleQueueEntryList queueEntryList)
+ public OrderedQueueEntry(L queueEntryList)
{
super(queueEntryList);
}
- public SimpleQueueEntryImpl(SimpleQueueEntryList queueEntryList, ServerMessage message, final long entryId)
+ public OrderedQueueEntry(L queueEntryList, ServerMessage message, final long entryId)
{
super(queueEntryList, message, entryId);
}
- public SimpleQueueEntryImpl(SimpleQueueEntryList queueEntryList, ServerMessage message)
+ public OrderedQueueEntry(L queueEntryList, ServerMessage message)
{
super(queueEntryList, message);
}
- public SimpleQueueEntryImpl getNextNode()
+ public E getNextNode()
{
return _next;
}
- public SimpleQueueEntryImpl getNextValidEntry()
+ public E getNextValidEntry()
{
- SimpleQueueEntryImpl next = getNextNode();
+ E next = getNextNode();
while(next != null && next.isDeleted())
{
- final SimpleQueueEntryImpl newNext = next.getNextNode();
+ final E newNext = next.getNextNode();
if(newNext != null)
{
- SimpleQueueEntryList._nextUpdater.compareAndSet(this,next, newNext);
+ OrderedQueueEntryList._nextUpdater.compareAndSet(this,next, newNext);
next = getNextNode();
}
else
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java
new file mode 100644
index 0000000000..f2491bdb0c
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java
@@ -0,0 +1,198 @@
+/*
+*
+* 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.queue;
+
+import org.apache.qpid.server.message.ServerMessage;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+public abstract class OrderedQueueEntryList<E extends OrderedQueueEntry<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends OrderedQueueEntryList<E,Q,L>> implements SimpleQueueEntryList<E,Q,L>
+{
+
+ private final E _head;
+
+ private volatile E _tail;
+
+ static final AtomicReferenceFieldUpdater<OrderedQueueEntryList, OrderedQueueEntry>
+ _tailUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (OrderedQueueEntryList.class, OrderedQueueEntry.class, "_tail");
+
+
+ private final Q _queue;
+
+ static final AtomicReferenceFieldUpdater<OrderedQueueEntry, OrderedQueueEntry>
+ _nextUpdater = OrderedQueueEntry._nextUpdater;
+
+ private AtomicLong _scavenges = new AtomicLong(0L);
+ private final long _scavengeCount = Integer.getInteger("qpid.queue.scavenge_count", 50);
+ private final AtomicReference<E> _unscavengedHWM = new AtomicReference<E>();
+
+
+ public OrderedQueueEntryList(Q queue, HeadCreator<E,Q,L> headCreator)
+ {
+ _queue = queue;
+ _head = headCreator.createHead((L)this);
+ _tail = _head;
+ }
+
+ void scavenge()
+ {
+ E hwm = _unscavengedHWM.getAndSet(null);
+ E next = _head.getNextValidEntry();
+
+ if(hwm != null)
+ {
+ while (next != null && hwm.compareTo(next)>0)
+ {
+ next = next.getNextValidEntry();
+ }
+ }
+ }
+
+
+ public Q getQueue()
+ {
+ return _queue;
+ }
+
+
+ public E add(ServerMessage message)
+ {
+ E node = createQueueEntry(message);
+ for (;;)
+ {
+ OrderedQueueEntry tail = _tail;
+ OrderedQueueEntry next = tail.getNextNode();
+ if (tail == _tail)
+ {
+ if (next == null)
+ {
+ node.setEntryId(tail.getEntryId()+1);
+ if (_nextUpdater.compareAndSet(tail, null, node))
+ {
+ _tailUpdater.compareAndSet(this, tail, node);
+
+ return node;
+ }
+ }
+ else
+ {
+ _tailUpdater.compareAndSet(this,tail, next);
+ }
+ }
+ }
+ }
+
+ abstract protected E createQueueEntry(ServerMessage<?> message);
+
+ public E next(E node)
+ {
+ return node.getNextValidEntry();
+ }
+
+ public static interface HeadCreator<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>>
+ {
+ E createHead(L list);
+ }
+
+ public static class QueueEntryIteratorImpl<E extends OrderedQueueEntry<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends OrderedQueueEntryList<E,Q,L>> implements QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>>
+ {
+ private E _lastNode;
+
+ QueueEntryIteratorImpl(E startNode)
+ {
+ _lastNode = startNode;
+ }
+
+ public boolean atTail()
+ {
+ return _lastNode.getNextValidEntry() == null;
+ }
+
+ public E getNode()
+ {
+ return _lastNode;
+ }
+
+ public boolean advance()
+ {
+ E nextValidNode = _lastNode.getNextValidEntry();
+
+ if(nextValidNode != null)
+ {
+ _lastNode = nextValidNode;
+ }
+
+ return nextValidNode != null;
+ }
+ }
+
+ public QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> iterator()
+ {
+ return new QueueEntryIteratorImpl<E,Q,L>(_head);
+ }
+
+
+ public E getHead()
+ {
+ return _head;
+ }
+
+ public void entryDeleted(E queueEntry)
+ {
+ E next = _head.getNextNode();
+ E newNext = _head.getNextValidEntry();
+
+ // the head of the queue has not been deleted, hence the deletion must have been mid queue.
+ if (next == newNext)
+ {
+ E unscavengedHWM = _unscavengedHWM.get();
+ while(unscavengedHWM == null || unscavengedHWM.compareTo(queueEntry)<0)
+ {
+ _unscavengedHWM.compareAndSet(unscavengedHWM, queueEntry);
+ unscavengedHWM = _unscavengedHWM.get();
+ }
+ if (_scavenges.incrementAndGet() > _scavengeCount)
+ {
+ _scavenges.set(0L);
+ scavenge();
+ }
+ }
+ else
+ {
+ E unscavengedHWM = _unscavengedHWM.get();
+ if(unscavengedHWM != null && (next == null || unscavengedHWM.compareTo(next) < 0))
+ {
+ _unscavengedHWM.compareAndSet(unscavengedHWM, null);
+ }
+ }
+ }
+
+ public int getPriorities()
+ {
+ return 0;
+ }
+
+
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java
index daa5db393a..7cf245c8f8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java
@@ -20,37 +20,35 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.subscription.SubscriptionList;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Map;
import java.util.UUID;
-public abstract class OutOfOrderQueue extends SimpleAMQQueue
+public abstract class OutOfOrderQueue<E extends QueueEntryImpl<E,Q,L>, Q extends OutOfOrderQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> extends SimpleAMQQueue<E,Q,L>
{
protected OutOfOrderQueue(UUID id, String name, boolean durable,
String owner, boolean autoDelete, boolean exclusive,
- VirtualHost virtualHost, QueueEntryListFactory entryListFactory, Map<String, Object> arguments)
+ VirtualHost virtualHost, QueueEntryListFactory<E,Q,L> entryListFactory, Map<String, Object> arguments)
{
super(id, name, durable, owner, autoDelete, exclusive, virtualHost, entryListFactory, arguments);
}
@Override
- protected void checkSubscriptionsNotAheadOfDelivery(final QueueEntry entry)
+ protected void checkConsumersNotAheadOfDelivery(final E entry)
{
- // check that all subscriptions are not in advance of the entry
- SubscriptionList.SubscriptionNodeIterator subIter = getSubscriptionList().iterator();
+ // check that all consumers are not in advance of the entry
+ QueueConsumerList.ConsumerNodeIterator<E,Q,L> subIter = getConsumerList().iterator();
while(subIter.advance() && !entry.isAcquired())
{
- final Subscription subscription = subIter.getNode().getSubscription();
- if(!subscription.isClosed())
+ final QueueConsumer<?,E,Q,L> consumer = subIter.getNode().getConsumer();
+ if(!consumer.isClosed())
{
- QueueContext context = (QueueContext) subscription.getQueueContext();
+ QueueContext<E,Q,L> context = consumer.getQueueContext();
if(context != null)
{
- QueueEntry released = context.getReleasedEntry();
+ E released = context.getReleasedEntry();
while(!entry.isAcquired() && (released == null || released.compareTo(entry) > 0))
{
if(QueueContext._releasedUpdater.compareAndSet(context,released,entry))
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueue.java
index 46c2a635b7..4440d045d1 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueue.java
@@ -25,22 +25,22 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Map;
import java.util.UUID;
-public class AMQPriorityQueue extends OutOfOrderQueue
+public class PriorityQueue extends OutOfOrderQueue<PriorityQueueList.PriorityQueueEntry, PriorityQueue, PriorityQueueList>
{
- protected AMQPriorityQueue(UUID id,
- final String name,
- final boolean durable,
- final String owner,
- final boolean autoDelete,
- boolean exclusive,
- final VirtualHost virtualHost,
- Map<String, Object> arguments, int priorities)
+ protected PriorityQueue(UUID id,
+ final String name,
+ final boolean durable,
+ final String owner,
+ final boolean autoDelete,
+ boolean exclusive,
+ final VirtualHost virtualHost,
+ Map<String, Object> arguments, int priorities)
{
super(id, name, durable, owner, autoDelete, exclusive, virtualHost, new PriorityQueueList.Factory(priorities), arguments);
}
public int getPriorities()
{
- return ((PriorityQueueList) getEntries()).getPriorities();
+ return getEntries().getPriorities();
}
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
index 66315af9fb..e877983643 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
@@ -22,132 +22,162 @@ package org.apache.qpid.server.queue;
import org.apache.qpid.server.message.ServerMessage;
-public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
+abstract public class PriorityQueueList extends OrderedQueueEntryList<PriorityQueueList.PriorityQueueEntry, PriorityQueue, PriorityQueueList>
{
- private final AMQQueue _queue;
- private final PriorityQueueEntrySubList[] _priorityLists;
- private final int _priorities;
- private final int _priorityOffset;
- public PriorityQueueList(AMQQueue queue, int priorities)
- {
- _queue = queue;
- _priorityLists = new PriorityQueueEntrySubList[priorities];
- _priorities = priorities;
- _priorityOffset = 5-((priorities + 1)/2);
- for(int i = 0; i < priorities; i++)
- {
- _priorityLists[i] = new PriorityQueueEntrySubList(queue, i);
- }
- }
- public int getPriorities()
+ public PriorityQueueList(final PriorityQueue queue,
+ final HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList> headCreator)
{
- return _priorities;
+ super(queue, headCreator);
}
- public AMQQueue getQueue()
+ static class PriorityQueueMasterList extends PriorityQueueList
{
- return _queue;
- }
+ private static final HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList> DUMMY_HEAD_CREATOR =
+ new HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList>()
+ {
+ @Override
+ public PriorityQueueEntry createHead(final PriorityQueueList list)
+ {
+ return null;
+ }
+ };
+ private final PriorityQueue _queue;
+ private final PriorityQueueEntrySubList[] _priorityLists;
+ private final int _priorities;
+ private final int _priorityOffset;
- public SimpleQueueEntryImpl add(ServerMessage message)
- {
- int index = message.getMessageHeader().getPriority() - _priorityOffset;
- if(index >= _priorities)
+ public PriorityQueueMasterList(PriorityQueue queue, int priorities)
{
- index = _priorities-1;
+ super(queue, DUMMY_HEAD_CREATOR);
+ _queue = queue;
+ _priorityLists = new PriorityQueueEntrySubList[priorities];
+ _priorities = priorities;
+ _priorityOffset = 5-((priorities + 1)/2);
+ for(int i = 0; i < priorities; i++)
+ {
+ _priorityLists[i] = new PriorityQueueEntrySubList(queue, i);
+ }
}
- else if(index < 0)
+
+ public int getPriorities()
{
- index = 0;
+ return _priorities;
}
- return _priorityLists[index].add(message);
-
- }
-
- public SimpleQueueEntryImpl next(SimpleQueueEntryImpl node)
- {
- SimpleQueueEntryImpl next = node.getNextValidEntry();
- if(next == null)
+ public PriorityQueue getQueue()
{
- final QueueEntryList<?> nodeEntryList = node.getQueueEntryList();
- int index;
- for(index = _priorityLists.length-1; _priorityLists[index] != nodeEntryList; index--) {};
+ return _queue;
+ }
- while(next == null && index != 0)
+ public PriorityQueueEntry add(ServerMessage message)
+ {
+ int index = message.getMessageHeader().getPriority() - _priorityOffset;
+ if(index >= _priorities)
+ {
+ index = _priorities-1;
+ }
+ else if(index < 0)
{
- index--;
- next = _priorityLists[index].getHead().getNextValidEntry();
+ index = 0;
}
+ return _priorityLists[index].add(message);
}
- return next;
- }
- private final class PriorityQueueEntryListIterator implements QueueEntryIterator<SimpleQueueEntryImpl>
- {
- private final SimpleQueueEntryList.QueueEntryIteratorImpl[] _iterators = new SimpleQueueEntryList.QueueEntryIteratorImpl[ _priorityLists.length ];
- private SimpleQueueEntryImpl _lastNode;
+ @Override
+ protected PriorityQueueEntry createQueueEntry(final ServerMessage<?> message)
+ {
+ throw new UnsupportedOperationException();
+ }
- PriorityQueueEntryListIterator()
+ public PriorityQueueEntry next(PriorityQueueEntry node)
{
- for(int i = 0; i < _priorityLists.length; i++)
+ PriorityQueueEntry next = node.getNextValidEntry();
+
+ if(next == null)
{
- _iterators[i] = _priorityLists[i].iterator();
+ final PriorityQueueList nodeEntryList = node.getQueueEntryList();
+ int index;
+ for(index = _priorityLists.length-1; _priorityLists[index] != nodeEntryList; index--)
+ {
+ // do nothing loop is just to find the index
+ }
+
+ while(next == null && index != 0)
+ {
+ index--;
+ next = _priorityLists[index].getHead().getNextValidEntry();
+ }
+
}
- _lastNode = _iterators[_iterators.length - 1].getNode();
+ return next;
}
-
- public boolean atTail()
+ private final class PriorityQueueEntryListIterator implements QueueEntryIterator<PriorityQueueEntry, PriorityQueue, PriorityQueueList, QueueConsumer<?,PriorityQueueEntry, PriorityQueue, PriorityQueueList>>
{
- for(int i = 0; i < _iterators.length; i++)
+ private final QueueEntryIterator<PriorityQueueEntry, PriorityQueue, PriorityQueueList,QueueConsumer<?,PriorityQueueEntry, PriorityQueue, PriorityQueueList>>[] _iterators = new QueueEntryIterator[ _priorityLists.length ];
+ private PriorityQueueEntry _lastNode;
+
+ PriorityQueueEntryListIterator()
{
- if(!_iterators[i].atTail())
+ for(int i = 0; i < _priorityLists.length; i++)
{
- return false;
+ _iterators[i] = _priorityLists[i].iterator();
}
+ _lastNode = _iterators[_iterators.length - 1].getNode();
}
- return true;
- }
- public SimpleQueueEntryImpl getNode()
- {
- return _lastNode;
- }
- public boolean advance()
- {
- for(int i = _iterators.length-1; i >= 0; i--)
+ public boolean atTail()
{
- if(_iterators[i].advance())
+ for(int i = 0; i < _iterators.length; i++)
{
- _lastNode = _iterators[i].getNode();
- return true;
+ if(!_iterators[i].atTail())
+ {
+ return false;
+ }
}
+ return true;
+ }
+
+ public PriorityQueueEntry getNode()
+ {
+ return _lastNode;
+ }
+
+ public boolean advance()
+ {
+ for(int i = _iterators.length-1; i >= 0; i--)
+ {
+ if(_iterators[i].advance())
+ {
+ _lastNode = _iterators[i].getNode();
+ return true;
+ }
+ }
+ return false;
}
- return false;
}
- }
- public PriorityQueueEntryListIterator iterator()
- {
- return new PriorityQueueEntryListIterator();
- }
+ public PriorityQueueEntryListIterator iterator()
+ {
- public SimpleQueueEntryImpl getHead()
- {
- return _priorityLists[_priorities-1].getHead();
- }
+ return new PriorityQueueEntryListIterator();
+ }
- public void entryDeleted(final SimpleQueueEntryImpl queueEntry)
- {
+ public PriorityQueueEntry getHead()
+ {
+ return _priorityLists[_priorities-1].getHead();
+ }
- }
+ public void entryDeleted(final PriorityQueueEntry queueEntry)
+ {
- static class Factory implements QueueEntryListFactory
+ }
+ }
+ static class Factory implements QueueEntryListFactory<PriorityQueueEntry, PriorityQueue, PriorityQueueList>
{
private final int _priorities;
@@ -156,26 +186,34 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
_priorities = priorities;
}
- public PriorityQueueList createQueueEntryList(AMQQueue queue)
+ public PriorityQueueList createQueueEntryList(PriorityQueue queue)
{
- return new PriorityQueueList(queue, _priorities);
+ return new PriorityQueueMasterList(queue, _priorities);
}
}
- private static class PriorityQueueEntrySubList extends SimpleQueueEntryList
+ static class PriorityQueueEntrySubList extends PriorityQueueList
{
+ private static final HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList> HEAD_CREATOR = new HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList>()
+ {
+ @Override
+ public PriorityQueueEntry createHead(final PriorityQueueList list)
+ {
+ return new PriorityQueueEntry(list);
+ }
+ };
private int _listPriority;
- public PriorityQueueEntrySubList(AMQQueue queue, int listPriority)
+ public PriorityQueueEntrySubList(PriorityQueue queue, int listPriority)
{
- super(queue);
+ super(queue, HEAD_CREATOR);
_listPriority = listPriority;
}
@Override
- protected PriorityQueueEntryImpl createQueueEntry(ServerMessage<?> message)
+ protected PriorityQueueEntry createQueueEntry(ServerMessage<?> message)
{
- return new PriorityQueueEntryImpl(this, message);
+ return new PriorityQueueEntry(this, message);
}
public int getListPriority()
@@ -184,17 +222,22 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
}
}
- private static class PriorityQueueEntryImpl extends SimpleQueueEntryImpl
+ static class PriorityQueueEntry extends OrderedQueueEntry<PriorityQueueEntry, PriorityQueue, PriorityQueueList>
{
- public PriorityQueueEntryImpl(PriorityQueueEntrySubList queueEntryList, ServerMessage<?> message)
+ private PriorityQueueEntry(final PriorityQueueList queueEntryList)
+ {
+ super(queueEntryList);
+ }
+
+ public PriorityQueueEntry(PriorityQueueEntrySubList queueEntryList, ServerMessage<?> message)
{
super(queueEntryList, message);
}
@Override
- public int compareTo(final QueueEntry o)
+ public int compareTo(final PriorityQueueEntry o)
{
- PriorityQueueEntrySubList pqel = (PriorityQueueEntrySubList)((PriorityQueueEntryImpl)o).getQueueEntryList();
+ PriorityQueueEntrySubList pqel = (PriorityQueueEntrySubList)o.getQueueEntryList();
int otherPriority = pqel.getListPriority();
int thisPriority = ((PriorityQueueEntrySubList) getQueueEntryList()).getListPriority();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java
new file mode 100644
index 0000000000..5c891797f5
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java
@@ -0,0 +1,474 @@
+/*
+ *
+ * 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.queue;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.filter.FilterManager;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.GenericActor;
+import org.apache.qpid.server.logging.messages.SubscriptionMessages;
+import org.apache.qpid.server.logging.subjects.QueueLogSubject;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.MessageConverterRegistry;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.util.StateChangeListener;
+
+import java.text.MessageFormat;
+import java.util.EnumMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SUBSCRIPTION_FORMAT;
+
+class QueueConsumer<T extends ConsumerTarget, E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements Consumer
+{
+
+ public static enum State
+ {
+ ACTIVE,
+ SUSPENDED,
+ CLOSED
+ }
+
+ private static final Logger _logger = Logger.getLogger(QueueConsumer.class);
+ private final AtomicBoolean _targetClosed = new AtomicBoolean(false);
+ private final AtomicBoolean _closed = new AtomicBoolean(false);
+ private final long _id;
+ private final Lock _stateChangeLock = new ReentrantLock();
+ private final long _createTime = System.currentTimeMillis();
+ private final MessageInstance.ConsumerAcquiredState<QueueConsumer<T,E,Q,L>> _owningState = new MessageInstance.ConsumerAcquiredState<QueueConsumer<T,E,Q,L>>(this);
+ private final boolean _acquires;
+ private final boolean _seesRequeues;
+ private final String _consumerName;
+ private final boolean _isTransient;
+ private final AtomicLong _deliveredCount = new AtomicLong(0);
+ private final AtomicLong _deliveredBytes = new AtomicLong(0);
+ private final FilterManager _filters;
+ private final Class<? extends ServerMessage> _messageClass;
+ private final Object _sessionReference;
+ private Q _queue;
+ private GenericActor _logActor = new GenericActor("[" + MessageFormat.format(SUBSCRIPTION_FORMAT, getId())
+ + "(UNKNOWN)"
+ + "] ");
+
+ static final EnumMap<ConsumerTarget.State, State> STATE_MAP =
+ new EnumMap<ConsumerTarget.State, State>(ConsumerTarget.State.class);
+
+ static
+ {
+ STATE_MAP.put(ConsumerTarget.State.ACTIVE, State.ACTIVE);
+ STATE_MAP.put(ConsumerTarget.State.SUSPENDED, State.SUSPENDED);
+ STATE_MAP.put(ConsumerTarget.State.CLOSED, State.CLOSED);
+ }
+
+ private final T _target;
+ private final SubFlushRunner _runner = new SubFlushRunner(this);
+ private volatile QueueContext<E,Q,L> _queueContext;
+ private StateChangeListener<? super QueueConsumer<T,E,Q,L>, State> _stateListener = new StateChangeListener<QueueConsumer<T,E,Q,L>, State>()
+ {
+ public void stateChanged(QueueConsumer sub, State oldState, State newState)
+ {
+ CurrentActor.get().message(SubscriptionMessages.STATE(newState.toString()));
+ }
+ };
+ private boolean _noLocal;
+
+ QueueConsumer(final FilterManager filters,
+ final Class<? extends ServerMessage> messageClass,
+ final boolean acquires,
+ final boolean seesRequeues,
+ final String consumerName,
+ final boolean isTransient,
+ T target)
+ {
+ _messageClass = messageClass;
+ _sessionReference = target.getSessionModel().getConnectionReference();
+ _id = SUB_ID_GENERATOR.getAndIncrement();
+ _filters = filters;
+ _acquires = acquires;
+ _seesRequeues = seesRequeues;
+ _consumerName = consumerName;
+ _isTransient = isTransient;
+ _target = target;
+ _target.setStateListener(
+ new StateChangeListener<ConsumerTarget, ConsumerTarget.State>()
+ {
+ @Override
+ public void stateChanged(final ConsumerTarget object,
+ final ConsumerTarget.State oldState,
+ final ConsumerTarget.State newState)
+ {
+ targetStateChanged(oldState, newState);
+ }
+ });
+ }
+
+ private void targetStateChanged(final ConsumerTarget.State oldState, final ConsumerTarget.State newState)
+ {
+ if(oldState != newState)
+ {
+ if(newState == ConsumerTarget.State.CLOSED)
+ {
+ if(_targetClosed.compareAndSet(false,true))
+ {
+ CurrentActor.get().message(getLogSubject(), SubscriptionMessages.CLOSE());
+ }
+ }
+ else
+ {
+ CurrentActor.get().message(getLogSubject(),SubscriptionMessages.STATE(newState.toString()));
+ }
+ }
+
+ if(newState == ConsumerTarget.State.CLOSED && oldState != newState && !_closed.get())
+ {
+ try
+ {
+ close();
+ }
+ catch (AMQException e)
+ {
+ _logger.error("Unable to remove to remove consumer", e);
+ throw new RuntimeException(e);
+ }
+ }
+ final StateChangeListener<? super QueueConsumer<T,E,Q,L>, State> stateListener = getStateListener();
+ if(stateListener != null)
+ {
+ stateListener.stateChanged(this, STATE_MAP.get(oldState), STATE_MAP.get(newState));
+ }
+ }
+
+ public T getTarget()
+ {
+ return _target;
+ }
+
+ @Override
+ public void externalStateChange()
+ {
+ getQueue().deliverAsync(this);
+ }
+
+ @Override
+ public long getUnacknowledgedBytes()
+ {
+ return _target.getUnacknowledgedBytes();
+ }
+
+ @Override
+ public long getUnacknowledgedMessages()
+ {
+ return _target.getUnacknowledgedMessages();
+ }
+
+ @Override
+ public AMQSessionModel getSessionModel()
+ {
+ return _target.getSessionModel();
+ }
+
+ @Override
+ public boolean isSuspended()
+ {
+ return _target.isSuspended();
+ }
+
+ @Override
+ public void close() throws AMQException
+ {
+ if(_closed.compareAndSet(false,true))
+ {
+ getSendLock();
+ try
+ {
+ _target.close();
+ _target.consumerRemoved(this);
+ _queue.unregisterConsumer(this);
+ }
+ finally
+ {
+ releaseSendLock();
+ }
+
+ }
+ }
+
+ void flushBatched()
+ {
+ _target.flushBatched();
+ }
+
+ void queueDeleted()
+ {
+ _target.queueDeleted();
+ }
+
+ boolean wouldSuspend(final MessageInstance msg)
+ {
+ return !_target.allocateCredit(msg.getMessage());
+ }
+
+ void restoreCredit(final MessageInstance queueEntry)
+ {
+ _target.restoreCredit(queueEntry.getMessage());
+ }
+
+ void queueEmpty() throws AMQException
+ {
+ _target.queueEmpty();
+ }
+
+ State getState()
+ {
+ return STATE_MAP.get(_target.getState());
+ }
+
+ public final Q getQueue()
+ {
+ return _queue;
+ }
+
+ final void setQueue(Q queue, boolean exclusive)
+ {
+ if(getQueue() != null)
+ {
+ throw new IllegalStateException("Attempt to set queue for consumer " + this + " to " + queue + "when already set to " + getQueue());
+ }
+ _queue = queue;
+
+ String queueString = new QueueLogSubject(_queue).toLogString();
+
+ _logActor = new GenericActor("[" + MessageFormat.format(SUBSCRIPTION_FORMAT, getId())
+ + "("
+ // queueString is [vh(/{0})/qu({1}) ] so need to trim
+ // ^ ^^
+ + queueString.substring(1,queueString.length() - 3)
+ + ")"
+ + "] ");
+
+
+ if (CurrentActor.get().getRootMessageLogger().isMessageEnabled(_logActor, _logActor.getLogSubject(), SubscriptionMessages.CREATE_LOG_HIERARCHY))
+ {
+ final String filterLogString = getFilterLogString();
+ CurrentActor.get().message(_logActor.getLogSubject(), SubscriptionMessages.CREATE(filterLogString, queue.isDurable() && exclusive,
+ filterLogString.length() > 0));
+ }
+ }
+
+ protected final LogSubject getLogSubject()
+ {
+ return _logActor.getLogSubject();
+ }
+
+ final LogActor getLogActor()
+ {
+ return _logActor;
+ }
+
+
+ @Override
+ public final void flush() throws AMQException
+ {
+ getQueue().flushConsumer(this);
+ }
+
+ boolean resend(final E entry) throws AMQException
+ {
+ return getQueue().resend(entry, this);
+ }
+
+ final SubFlushRunner getRunner()
+ {
+ return _runner;
+ }
+
+ public final long getId()
+ {
+ return _id;
+ }
+
+ public final StateChangeListener<? super QueueConsumer<T,E,Q,L>, State> getStateListener()
+ {
+ return _stateListener;
+ }
+
+ public final void setStateListener(StateChangeListener<? super QueueConsumer<T,E,Q,L>, State> listener)
+ {
+ _stateListener = listener;
+ }
+
+ final QueueContext<E,Q,L> getQueueContext()
+ {
+ return _queueContext;
+ }
+
+ final void setQueueContext(QueueContext<E,Q,L> queueContext)
+ {
+ _queueContext = queueContext;
+ }
+
+ public final boolean isActive()
+ {
+ return getState() == State.ACTIVE;
+ }
+
+ public final boolean isClosed()
+ {
+ return getState() == State.CLOSED;
+ }
+
+ public final void setNoLocal(boolean noLocal)
+ {
+ _noLocal = noLocal;
+ }
+
+ public final boolean hasInterest(E entry)
+ {
+ //check that the message hasn't been rejected
+ if (entry.isRejectedBy(this))
+ {
+
+ return false;
+ }
+
+ if (entry.getMessage().getClass() == _messageClass)
+ {
+ if(_noLocal)
+ {
+ Object connectionRef = entry.getMessage().getConnectionReference();
+ if (connectionRef != null && connectionRef == _sessionReference)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // no interest in messages we can't convert
+ if(_messageClass != null && MessageConverterRegistry.getConverter(entry.getMessage().getClass(),
+ _messageClass)==null)
+ {
+ return false;
+ }
+ }
+ return (_filters == null) || _filters.allAllow(entry.asFilterable());
+ }
+
+ protected String getFilterLogString()
+ {
+ StringBuilder filterLogString = new StringBuilder();
+ String delimiter = ", ";
+ boolean hasEntries = false;
+ if (_filters != null && _filters.hasFilters())
+ {
+ filterLogString.append(_filters.toString());
+ hasEntries = true;
+ }
+
+ if (!acquires())
+ {
+ if (hasEntries)
+ {
+ filterLogString.append(delimiter);
+ }
+ filterLogString.append("Browser");
+ }
+
+ return filterLogString.toString();
+ }
+
+ public final boolean trySendLock()
+ {
+ return _stateChangeLock.tryLock();
+ }
+
+ public final void getSendLock()
+ {
+ _stateChangeLock.lock();
+ }
+
+ public final void releaseSendLock()
+ {
+ _stateChangeLock.unlock();
+ }
+
+ public final long getCreateTime()
+ {
+ return _createTime;
+ }
+
+ final MessageInstance.ConsumerAcquiredState<QueueConsumer<T,E,Q,L>> getOwningState()
+ {
+ return _owningState;
+ }
+
+ public final boolean acquires()
+ {
+ return _acquires;
+ }
+
+ public final boolean seesRequeues()
+ {
+ return _seesRequeues;
+ }
+
+ public final String getName()
+ {
+ return _consumerName;
+ }
+
+ public final boolean isTransient()
+ {
+ return _isTransient;
+ }
+
+ public final long getBytesOut()
+ {
+ return _deliveredBytes.longValue();
+ }
+
+ public final long getMessagesOut()
+ {
+ return _deliveredCount.longValue();
+ }
+
+ final void send(final E entry, final boolean batch) throws AMQException
+ {
+ _deliveredCount.incrementAndGet();
+ ServerMessage message = entry.getMessage();
+ if(message == null)
+ {
+ throw new AMQException("message was null!");
+ }
+ _deliveredBytes.addAndGet(message.getSize());
+ _target.send(entry, batch);
+ }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerList.java
index 23d4fb241f..2cf0e93e9c 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerList.java
@@ -18,34 +18,34 @@
* under the License.
*
*/
-package org.apache.qpid.server.subscription;
+package org.apache.qpid.server.queue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
-public class SubscriptionList
+class QueueConsumerList<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E, Q,L>, L extends SimpleQueueEntryList<E,Q,L>>
{
- private final SubscriptionNode _head = new SubscriptionNode();
+ private final ConsumerNode<E,Q,L> _head = new ConsumerNode<E,Q,L>();
- private final AtomicReference<SubscriptionNode> _tail = new AtomicReference<SubscriptionNode>(_head);
- private final AtomicReference<SubscriptionNode> _subNodeMarker = new AtomicReference<SubscriptionNode>(_head);
+ private final AtomicReference<ConsumerNode<E,Q,L>> _tail = new AtomicReference<ConsumerNode<E,Q,L>>(_head);
+ private final AtomicReference<ConsumerNode<E,Q,L>> _subNodeMarker = new AtomicReference<ConsumerNode<E,Q,L>>(_head);
private final AtomicInteger _size = new AtomicInteger();
- public static final class SubscriptionNode
+ public static final class ConsumerNode<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E, Q,L>, L extends SimpleQueueEntryList<E,Q,L>>
{
private final AtomicBoolean _deleted = new AtomicBoolean();
- private final AtomicReference<SubscriptionNode> _next = new AtomicReference<SubscriptionNode>();
- private final Subscription _sub;
+ private final AtomicReference<ConsumerNode<E,Q,L>> _next = new AtomicReference<ConsumerNode<E,Q,L>>();
+ private final QueueConsumer<?,E,Q,L> _sub;
- public SubscriptionNode()
+ public ConsumerNode()
{
//used for sentinel head and dummy node construction
_sub = null;
_deleted.set(true);
}
- public SubscriptionNode(final Subscription sub)
+ public ConsumerNode(final QueueConsumer<?,E,Q,L> sub)
{
//used for regular node construction
_sub = sub;
@@ -57,12 +57,12 @@ public class SubscriptionList
*
* @return the next non-deleted node, or null if none was found.
*/
- public SubscriptionNode findNext()
+ public ConsumerNode<E,Q,L> findNext()
{
- SubscriptionNode next = nextNode();
+ ConsumerNode<E,Q,L> next = nextNode();
while(next != null && next.isDeleted())
{
- final SubscriptionNode newNext = next.nextNode();
+ final ConsumerNode<E,Q,L> newNext = next.nextNode();
if(newNext != null)
{
//try to move our _next reference forward to the 'newNext'
@@ -86,7 +86,7 @@ public class SubscriptionList
*
* @return the immediately next node in the structure, or null if at the tail.
*/
- protected SubscriptionNode nextNode()
+ protected ConsumerNode<E,Q,L> nextNode()
{
return _next.get();
}
@@ -94,10 +94,10 @@ public class SubscriptionList
/**
* Used to initialise the 'next' reference. Will only succeed if the reference was not previously set.
*
- * @param node the SubscriptionNode to set as 'next'
+ * @param node the ConsumerNode to set as 'next'
* @return whether the operation succeeded
*/
- private boolean setNext(final SubscriptionNode node)
+ private boolean setNext(final ConsumerNode<E,Q,L> node)
{
return _next.compareAndSet(null, node);
}
@@ -112,18 +112,18 @@ public class SubscriptionList
return _deleted.compareAndSet(false,true);
}
- public Subscription getSubscription()
+ public QueueConsumer<?,E,Q,L> getConsumer()
{
return _sub;
}
}
- private void insert(final SubscriptionNode node, final boolean count)
+ private void insert(final ConsumerNode<E,Q,L> node, final boolean count)
{
for (;;)
{
- SubscriptionNode tail = _tail.get();
- SubscriptionNode next = tail.nextNode();
+ ConsumerNode<E,Q,L> tail = _tail.get();
+ ConsumerNode<E,Q,L> next = tail.nextNode();
if (tail == _tail.get())
{
if (next == null)
@@ -146,35 +146,35 @@ public class SubscriptionList
}
}
- public void add(final Subscription sub)
+ public void add(final QueueConsumer<?,E,Q,L> sub)
{
- SubscriptionNode node = new SubscriptionNode(sub);
+ ConsumerNode<E,Q,L> node = new ConsumerNode<E,Q,L>(sub);
insert(node, true);
}
- public boolean remove(final Subscription sub)
+ public boolean remove(final QueueConsumer<?, E,Q,L> sub)
{
- SubscriptionNode prevNode = _head;
- SubscriptionNode node = _head.nextNode();
+ ConsumerNode<E,Q,L> prevNode = _head;
+ ConsumerNode<E,Q,L> node = _head.nextNode();
while(node != null)
{
- if(sub.equals(node.getSubscription()) && node.delete())
+ if(sub.equals(node.getConsumer()) && node.delete())
{
_size.decrementAndGet();
- SubscriptionNode tail = _tail.get();
+ ConsumerNode tail = _tail.get();
if(node == tail)
{
//we cant remove the last node from the structure for
//correctness reasons, however we have just 'deleted'
//the tail. Inserting an empty dummy node after it will
- //let us scavenge the node containing the Subscription.
- insert(new SubscriptionNode(), false);
+ //let us scavenge the node containing the Consumer.
+ insert(new ConsumerNode<E,Q,L>(), false);
}
//advance the next node reference in the 'prevNode' to scavenge
- //the newly 'deleted' node for the Subscription.
+ //the newly 'deleted' node for the Consumer.
prevNode.findNext();
nodeMarkerCleanup(node);
@@ -189,9 +189,9 @@ public class SubscriptionList
return false;
}
- private void nodeMarkerCleanup(final SubscriptionNode node)
+ private void nodeMarkerCleanup(final ConsumerNode<E,Q,L> node)
{
- SubscriptionNode markedNode = _subNodeMarker.get();
+ ConsumerNode<E,Q,L> markedNode = _subNodeMarker.get();
if(node == markedNode)
{
//if the marked node is the one we are removing, then
@@ -200,7 +200,7 @@ public class SubscriptionList
//into the list and find the next node to use.
//Because we inserted a dummy if node was the
//tail, markedNode.nextNode() can never be null.
- SubscriptionNode dummy = new SubscriptionNode();
+ ConsumerNode<E,Q,L> dummy = new ConsumerNode<E,Q,L>();
dummy.setNext(markedNode.nextNode());
//if the CAS fails the marked node has changed, thus
@@ -219,53 +219,53 @@ public class SubscriptionList
}
}
- public boolean updateMarkedNode(final SubscriptionNode expected, final SubscriptionNode nextNode)
+ public boolean updateMarkedNode(final ConsumerNode<E,Q,L> expected, final ConsumerNode<E,Q,L> nextNode)
{
return _subNodeMarker.compareAndSet(expected, nextNode);
}
/**
- * Get the current marked SubscriptionNode. This should only be used only to index into the list and find the next node
+ * Get the current marked ConsumerNode. This should only be used only to index into the list and find the next node
* after the mark, since if the previously marked node was subsequently deleted the item returned may be a dummy node
* with reference to the next node.
*
* @return the previously marked node (or a dummy if it was subsequently deleted)
*/
- public SubscriptionNode getMarkedNode()
+ public ConsumerNode<E,Q,L> getMarkedNode()
{
return _subNodeMarker.get();
}
- public static class SubscriptionNodeIterator
+ public static class ConsumerNodeIterator<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E, Q,L>, L extends SimpleQueueEntryList<E,Q,L>>
{
- private SubscriptionNode _lastNode;
+ private ConsumerNode<E,Q,L> _lastNode;
- SubscriptionNodeIterator(SubscriptionNode startNode)
+ ConsumerNodeIterator(ConsumerNode<E,Q,L> startNode)
{
_lastNode = startNode;
}
- public SubscriptionNode getNode()
+ public ConsumerNode<E,Q,L> getNode()
{
return _lastNode;
}
public boolean advance()
{
- SubscriptionNode nextNode = _lastNode.findNext();
+ ConsumerNode<E,Q,L> nextNode = _lastNode.findNext();
_lastNode = nextNode;
return _lastNode != null;
}
}
- public SubscriptionNodeIterator iterator()
+ public ConsumerNodeIterator<E,Q,L> iterator()
{
- return new SubscriptionNodeIterator(_head);
+ return new ConsumerNodeIterator<E,Q,L>(_head);
}
- public SubscriptionNode getHead()
+ public ConsumerNode<E,Q,L> getHead()
{
return _head;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueContext.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueContext.java
index 79279b44c7..7a59c154b6 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueContext.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueContext.java
@@ -23,32 +23,32 @@ package org.apache.qpid.server.queue;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-final class QueueContext implements AMQQueue.Context
+final class QueueContext<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>>
{
- private volatile QueueEntry _lastSeenEntry;
- private volatile QueueEntry _releasedEntry;
+ private volatile E _lastSeenEntry;
+ private volatile E _releasedEntry;
- static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry>
+ static final AtomicReferenceFieldUpdater<QueueContext, QueueEntryImpl>
_lastSeenUpdater =
AtomicReferenceFieldUpdater.newUpdater
- (QueueContext.class, QueueEntry.class, "_lastSeenEntry");
- static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry>
+ (QueueContext.class, QueueEntryImpl.class, "_lastSeenEntry");
+ static final AtomicReferenceFieldUpdater<QueueContext, QueueEntryImpl>
_releasedUpdater =
AtomicReferenceFieldUpdater.newUpdater
- (QueueContext.class, QueueEntry.class, "_releasedEntry");
+ (QueueContext.class, QueueEntryImpl.class, "_releasedEntry");
- public QueueContext(QueueEntry head)
+ public QueueContext(E head)
{
_lastSeenEntry = head;
}
- public QueueEntry getLastSeenEntry()
+ public E getLastSeenEntry()
{
return _lastSeenEntry;
}
- QueueEntry getReleasedEntry()
+ E getReleasedEntry()
{
return _releasedEntry;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
index 2aa1d1f473..9a49cd6088 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
@@ -20,207 +20,21 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.filter.Filterable;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.message.MessageInstance;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.txn.ServerTransaction;
-public interface QueueEntry extends MessageInstance, Comparable<QueueEntry>
+public interface QueueEntry<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, C extends Consumer> extends MessageInstance<E,C>, Comparable<E>
{
-
-
- public static enum State
- {
- AVAILABLE,
- ACQUIRED,
- EXPIRED,
- DEQUEUED,
- DELETED;
-
-
- }
-
- public static interface StateChangeListener
- {
- public void stateChanged(QueueEntry entry, State oldSate, State newState);
- }
-
- public abstract class EntryState
- {
- private EntryState()
- {
- }
-
- public abstract State getState();
-
- /**
- * Returns true if state is either DEQUEUED or DELETED.
- *
- * @return true if state is either DEQUEUED or DELETED.
- */
- public boolean isDispensed()
- {
- State currentState = getState();
- return currentState == State.DEQUEUED || currentState == State.DELETED;
- }
- }
-
-
- public final class AvailableState extends EntryState
- {
-
- public State getState()
- {
- return State.AVAILABLE;
- }
-
- public String toString()
- {
- return getState().name();
- }
- }
-
-
- public final class DequeuedState extends EntryState
- {
-
- public State getState()
- {
- return State.DEQUEUED;
- }
-
- public String toString()
- {
- return getState().name();
- }
- }
-
-
- public final class DeletedState extends EntryState
- {
-
- public State getState()
- {
- return State.DELETED;
- }
-
- public String toString()
- {
- return getState().name();
- }
- }
-
- public final class ExpiredState extends EntryState
- {
-
- public State getState()
- {
- return State.EXPIRED;
- }
-
- public String toString()
- {
- return getState().name();
- }
- }
-
-
- public final class NonSubscriptionAcquiredState extends EntryState
- {
- public State getState()
- {
- return State.ACQUIRED;
- }
-
- public String toString()
- {
- return getState().name();
- }
- }
-
- public final class SubscriptionAcquiredState extends EntryState
- {
- private final Subscription _subscription;
-
- public SubscriptionAcquiredState(Subscription subscription)
- {
- _subscription = subscription;
- }
-
-
- public State getState()
- {
- return State.ACQUIRED;
- }
-
- public Subscription getSubscription()
- {
- return _subscription;
- }
-
- public String toString()
- {
- return "{" + getState().name() + " : " + _subscription +"}";
- }
- }
-
-
- final static EntryState AVAILABLE_STATE = new AvailableState();
- final static EntryState DELETED_STATE = new DeletedState();
- final static EntryState DEQUEUED_STATE = new DequeuedState();
- final static EntryState NON_SUBSCRIPTION_ACQUIRED_STATE = new NonSubscriptionAcquiredState();
-
-
-
-
- AMQQueue getQueue();
+ Q getQueue();
long getSize();
- boolean getDeliveredToConsumer();
-
- boolean expired() throws AMQException;
-
- boolean acquire(Subscription sub);
-
- boolean acquiredBySubscription();
- boolean isAcquiredBy(Subscription subscription);
-
- void setRedelivered();
-
- boolean isRedelivered();
-
- Subscription getDeliveredSubscription();
-
- void reject();
-
- boolean isRejectedBy(long subscriptionId);
-
- int routeToAlternate(final BaseQueue.PostEnqueueAction action, ServerTransaction txn);
-
boolean isQueueDeleted();
- QueueEntry getNextNode();
-
- QueueEntry getNextValidEntry();
-
- void addStateChangeListener(StateChangeListener listener);
- boolean removeStateChangeListener(StateChangeListener listener);
-
-
- /**
- * Number of times this queue entry has been delivered.
- *
- * @return delivery count
- */
- int getDeliveryCount();
-
- void incrementDeliveryCount();
+ E getNextNode();
- void decrementDeliveryCount();
+ E getNextValidEntry();
- Filterable asFilterable();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
index 461d493437..ae5c560db0 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
@@ -26,11 +26,15 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.filter.Filterable;
import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.util.StateChangeListener;
import java.util.EnumMap;
import java.util.HashSet;
@@ -40,13 +44,13 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-public abstract class QueueEntryImpl implements QueueEntry
+public abstract class QueueEntryImpl<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements QueueEntry<E,Q,QueueConsumer<?,E,Q,L>>
{
private static final Logger _log = Logger.getLogger(QueueEntryImpl.class);
- private final QueueEntryList _queueEntryList;
+ private final L _queueEntryList;
- private MessageReference _message;
+ private final MessageReference _message;
private Set<Long> _rejectedBy = null;
@@ -59,7 +63,7 @@ public abstract class QueueEntryImpl implements QueueEntry
(QueueEntryImpl.class, EntryState.class, "_state");
- private volatile Set<StateChangeListener> _stateChangeListeners;
+ private volatile Set<StateChangeListener<? super E, State>> _stateChangeListeners;
private static final
AtomicReferenceFieldUpdater<QueueEntryImpl, Set>
@@ -86,14 +90,14 @@ public abstract class QueueEntryImpl implements QueueEntry
private boolean _deliveredToConsumer;
- public QueueEntryImpl(QueueEntryList<?> queueEntryList)
+ public QueueEntryImpl(L queueEntryList)
{
this(queueEntryList,null,Long.MIN_VALUE);
_state = DELETED_STATE;
}
- public QueueEntryImpl(QueueEntryList<?> queueEntryList, ServerMessage message, final long entryId)
+ public QueueEntryImpl(L queueEntryList, ServerMessage message, final long entryId)
{
_queueEntryList = queueEntryList;
@@ -103,7 +107,7 @@ public abstract class QueueEntryImpl implements QueueEntry
populateInstanceProperties();
}
- public QueueEntryImpl(QueueEntryList<?> queueEntryList, ServerMessage message)
+ public QueueEntryImpl(L queueEntryList, ServerMessage message)
{
_queueEntryList = queueEntryList;
_message = message == null ? null : message.newReference();
@@ -134,7 +138,7 @@ public abstract class QueueEntryImpl implements QueueEntry
return _entryId;
}
- public AMQQueue getQueue()
+ public Q getQueue()
{
return _queueEntryList.getQueue();
}
@@ -183,7 +187,7 @@ public abstract class QueueEntryImpl implements QueueEntry
public boolean acquire()
{
- return acquire(NON_SUBSCRIPTION_ACQUIRED_STATE);
+ return acquire(NON_CONSUMER_ACQUIRED_STATE);
}
private boolean acquire(final EntryState state)
@@ -198,7 +202,7 @@ public abstract class QueueEntryImpl implements QueueEntry
return acquired;
}
- public boolean acquire(Subscription sub)
+ public boolean acquire(QueueConsumer<?,E,Q,L> sub)
{
final boolean acquired = acquire(sub.getOwningState());
if(acquired)
@@ -208,17 +212,17 @@ public abstract class QueueEntryImpl implements QueueEntry
return acquired;
}
- public boolean acquiredBySubscription()
+ public boolean acquiredByConsumer()
{
- return (_state instanceof SubscriptionAcquiredState);
+ return (_state instanceof ConsumerAcquiredState);
}
- public boolean isAcquiredBy(Subscription subscription)
+ public boolean isAcquiredBy(QueueConsumer consumer)
{
EntryState state = _state;
- return state instanceof SubscriptionAcquiredState
- && ((SubscriptionAcquiredState)state).getSubscription() == subscription;
+ return state instanceof ConsumerAcquiredState
+ && ((ConsumerAcquiredState)state).getConsumer() == consumer;
}
public void release()
@@ -228,19 +232,14 @@ public abstract class QueueEntryImpl implements QueueEntry
if((state.getState() == State.ACQUIRED) &&_stateUpdater.compareAndSet(this, state, AVAILABLE_STATE))
{
- if(state instanceof SubscriptionAcquiredState)
+ if(state instanceof ConsumerAcquiredState)
{
- getQueue().decrementUnackedMsgCount(this);
- Subscription subscription = ((SubscriptionAcquiredState)state).getSubscription();
- if (subscription != null)
- {
- subscription.releaseQueueEntry(this);
- }
+ getQueue().decrementUnackedMsgCount((E) this);
}
if(!getQueue().isDeleted())
{
- getQueue().requeue(this);
+ getQueue().requeue((E)this);
if(_stateChangeListeners != null)
{
notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE);
@@ -265,12 +264,12 @@ public abstract class QueueEntryImpl implements QueueEntry
return Boolean.TRUE.equals(_instanceProperties.getProperty(InstanceProperties.Property.REDELIVERED));
}
- public Subscription getDeliveredSubscription()
+ public QueueConsumer getDeliveredConsumer()
{
EntryState state = _state;
- if (state instanceof SubscriptionAcquiredState)
+ if (state instanceof ConsumerAcquiredState)
{
- return ((SubscriptionAcquiredState) state).getSubscription();
+ return (QueueConsumer) ((ConsumerAcquiredState) state).getConsumer();
}
else
{
@@ -280,16 +279,16 @@ public abstract class QueueEntryImpl implements QueueEntry
public void reject()
{
- Subscription subscription = getDeliveredSubscription();
+ QueueConsumer consumer = getDeliveredConsumer();
- if (subscription != null)
+ if (consumer != null)
{
if (_rejectedBy == null)
{
_rejectedBy = new HashSet<Long>();
}
- _rejectedBy.add(subscription.getSubscriptionID());
+ _rejectedBy.add(consumer.getId());
}
else
{
@@ -297,12 +296,12 @@ public abstract class QueueEntryImpl implements QueueEntry
}
}
- public boolean isRejectedBy(long subscriptionId)
+ public boolean isRejectedBy(QueueConsumer consumer)
{
- if (_rejectedBy != null) // We have subscriptions that rejected this message
+ if (_rejectedBy != null) // We have consumers that rejected this message
{
- return _rejectedBy.contains(subscriptionId);
+ return _rejectedBy.contains(consumer.getId());
}
else // This message hasn't been rejected yet.
{
@@ -316,15 +315,12 @@ public abstract class QueueEntryImpl implements QueueEntry
if((state.getState() == State.ACQUIRED) &&_stateUpdater.compareAndSet(this, state, DEQUEUED_STATE))
{
- Subscription s = null;
- if (state instanceof SubscriptionAcquiredState)
+ if (state instanceof ConsumerAcquiredState)
{
- getQueue().decrementUnackedMsgCount(this);
- s = ((SubscriptionAcquiredState) state).getSubscription();
- s.onDequeue(this);
+ getQueue().decrementUnackedMsgCount((E) this);
}
- getQueue().dequeue(this,s);
+ getQueue().dequeue((E)this);
if(_stateChangeListeners != null)
{
notifyStateChange(state.getState() , QueueEntry.State.DEQUEUED);
@@ -336,9 +332,9 @@ public abstract class QueueEntryImpl implements QueueEntry
private void notifyStateChange(final State oldState, final State newState)
{
- for(StateChangeListener l : _stateChangeListeners)
+ for(StateChangeListener<? super E, State> l : _stateChangeListeners)
{
- l.stateChanged(this, oldState, newState);
+ l.stateChanged((E)this, oldState, newState);
}
}
@@ -348,7 +344,7 @@ public abstract class QueueEntryImpl implements QueueEntry
if(state != DELETED_STATE && _stateUpdater.compareAndSet(this,state,DELETED_STATE))
{
- _queueEntryList.entryDeleted(this);
+ _queueEntryList.entryDeleted((E)this);
onDelete();
_message.release();
@@ -367,44 +363,49 @@ public abstract class QueueEntryImpl implements QueueEntry
dispose();
}
- public int routeToAlternate(final BaseQueue.PostEnqueueAction action, ServerTransaction txn)
+ public int routeToAlternate(final Action<? super MessageInstance<?, ? extends Consumer>> action, ServerTransaction txn)
{
final AMQQueue currentQueue = getQueue();
Exchange alternateExchange = currentQueue.getAlternateExchange();
boolean autocommit = txn == null;
+ int enqueues;
+
+ if(autocommit)
+ {
+ txn = new LocalTransaction(getQueue().getVirtualHost().getMessageStore());
+ }
+
if (alternateExchange != null)
{
- if(autocommit)
+ enqueues = alternateExchange.send(getMessage(),
+ getInstanceProperties(),
+ txn,
+ action);
+ }
+ else
+ {
+ enqueues = 0;
+ }
+
+ txn.dequeue(currentQueue, getMessage(), new ServerTransaction.Action()
+ {
+ public void postCommit()
{
- txn = new LocalTransaction(getQueue().getVirtualHost().getMessageStore());
+ delete();
}
- int enqueues = alternateExchange.send(getMessage(), getInstanceProperties(), txn, action);
-
- txn.dequeue(currentQueue, getMessage(), new ServerTransaction.Action()
+ public void onRollback()
{
- public void postCommit()
- {
- delete();
- }
-
- public void onRollback()
- {
-
- }
- });
- if(autocommit)
- {
- txn.commit();
}
- return enqueues;
+ });
- }
- else
+ if(autocommit)
{
- return 0;
+ txn.commit();
}
+
+ return enqueues;
}
public boolean isQueueDeleted()
@@ -412,21 +413,21 @@ public abstract class QueueEntryImpl implements QueueEntry
return getQueue().isDeleted();
}
- public void addStateChangeListener(StateChangeListener listener)
+ public void addStateChangeListener(StateChangeListener<? super E,State> listener)
{
- Set<StateChangeListener> listeners = _stateChangeListeners;
+ Set<StateChangeListener<? super E, State>> listeners = _stateChangeListeners;
if(listeners == null)
{
- _listenersUpdater.compareAndSet(this, null, new CopyOnWriteArraySet<StateChangeListener>());
+ _listenersUpdater.compareAndSet(this, null, new CopyOnWriteArraySet<StateChangeListener<? super E, State>>());
listeners = _stateChangeListeners;
}
listeners.add(listener);
}
- public boolean removeStateChangeListener(StateChangeListener listener)
+ public boolean removeStateChangeListener(StateChangeListener<? super E, State> listener)
{
- Set<StateChangeListener> listeners = _stateChangeListeners;
+ Set<StateChangeListener<? super E, State>> listeners = _stateChangeListeners;
if(listeners != null)
{
return listeners.remove(listener);
@@ -436,9 +437,9 @@ public abstract class QueueEntryImpl implements QueueEntry
}
- public int compareTo(final QueueEntry o)
+ public int compareTo(final E o)
{
- QueueEntryImpl other = (QueueEntryImpl)o;
+ E other = o;
return getEntryId() > other.getEntryId() ? 1 : getEntryId() < other.getEntryId() ? -1 : 0;
}
@@ -446,7 +447,7 @@ public abstract class QueueEntryImpl implements QueueEntry
{
}
- public QueueEntryList getQueueEntryList()
+ public L getQueueEntryList()
{
return _queueEntryList;
}
@@ -461,6 +462,12 @@ public abstract class QueueEntryImpl implements QueueEntry
return _deliveryCount;
}
+ @Override
+ public int getMaximumDeliveryCount()
+ {
+ return getQueue().getMaximumDeliveryCount();
+ }
+
public void incrementDeliveryCount()
{
_deliveryCountUpdater.incrementAndGet(this);
@@ -485,6 +492,23 @@ public abstract class QueueEntryImpl implements QueueEntry
'}';
}
+ @Override
+ public boolean resend() throws AMQException
+ {
+ QueueConsumer<?,E,Q,L> sub = getDeliveredConsumer();
+ if(sub != null)
+ {
+ return sub.resend((E)this);
+ }
+ return false;
+ }
+
+ @Override
+ public TransactionLogResource getOwningResource()
+ {
+ return getQueue();
+ }
+
private static class EntryInstanceProperties implements InstanceProperties
{
private final EnumMap<Property, Object> _properties = new EnumMap<Property, Object>(Property.class);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java
index 73ebb0f300..72502feb3d 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java
@@ -20,11 +20,13 @@
*/
package org.apache.qpid.server.queue;
-public interface QueueEntryIterator<QE extends QueueEntry>
+import org.apache.qpid.server.consumer.Consumer;
+
+public interface QueueEntryIterator<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, L extends QueueEntryList<E,Q,L,C>, C extends Consumer>
{
boolean atTail();
- QE getNode();
+ E getNode();
boolean advance();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
index 641aaa0a08..a49320e9d6 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
@@ -20,21 +20,23 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.message.ServerMessage;
-public interface QueueEntryList<Q extends QueueEntry>
+public interface QueueEntryList<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, L extends QueueEntryList<E,Q,L,C>, C extends Consumer>
{
- AMQQueue getQueue();
+ Q getQueue();
- Q add(ServerMessage message);
+ E add(ServerMessage message);
- Q next(Q node);
+ E next(E node);
- QueueEntryIterator<Q> iterator();
+ QueueEntryIterator<E,Q,L,C> iterator();
- Q getHead();
+ E getHead();
- void entryDeleted(Q queueEntry);
+ void entryDeleted(E queueEntry);
int getPriorities();
+
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java
index 4dbce45f67..ae8b6560be 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java
@@ -20,7 +20,7 @@
*/
package org.apache.qpid.server.queue;
-interface QueueEntryListFactory
+interface QueueEntryListFactory<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>>
{
- public QueueEntryList createQueueEntryList(AMQQueue queue);
+ public L createQueueEntryList(Q queue);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java
index 9ecaf6dafd..e6b5ac5611 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java
@@ -16,7 +16,9 @@
*/
package org.apache.qpid.server.queue;
-public interface QueueEntryVisitor
+import org.apache.qpid.server.consumer.Consumer;
+
+public interface QueueEntryVisitor<E extends QueueEntry>
{
- boolean visit(QueueEntry entry);
+ boolean visit(E entry);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueRunner.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueRunner.java
index 22a2029494..005d9b66b3 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueRunner.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueRunner.java
@@ -32,8 +32,8 @@ import org.apache.qpid.transport.TransportException;
/**
* QueueRunners are Runnables used to process a queue when requiring
- * asynchronous message delivery to subscriptions, which is necessary
- * when straight-through delivery of a message to a subscription isn't
+ * asynchronous message delivery to consumers, which is necessary
+ * when straight-through delivery of a message to a consumer isn't
* possible during the enqueue operation.
*/
public class QueueRunner implements Runnable
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
index 87d11a892e..4450a3ed0c 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
@@ -18,15 +18,7 @@
*/
package org.apache.qpid.server.queue;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
@@ -43,27 +35,33 @@ import org.apache.qpid.server.binding.Binding;
import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.configuration.QueueConfiguration;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.QueueActor;
import org.apache.qpid.server.logging.messages.QueueMessages;
import org.apache.qpid.server.logging.subjects.QueueLogSubject;
+import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
-import org.apache.qpid.server.subscription.AssignedSubscriptionMessageGroupManager;
-import org.apache.qpid.server.subscription.DefinedGroupMessageGroupManager;
-import org.apache.qpid.server.subscription.MessageGroupManager;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.subscription.SubscriptionList;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.store.StorableMessageMetaData;
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.Action;
+import org.apache.qpid.server.util.StateChangeListener;
import org.apache.qpid.server.virtualhost.VirtualHost;
-public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, MessageGroupManager.SubscriptionResetHelper
+abstract class SimpleAMQQueue<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E, Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements AMQQueue<E, Q, QueueConsumer<?,E,Q,L>>,
+ StateChangeListener<QueueConsumer<?,E,Q,L>, QueueConsumer.State>,
+ MessageGroupManager.ConsumerResetHelper<E,Q,L>
{
private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class);
@@ -96,11 +94,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private Exchange _alternateExchange;
- private final QueueEntryList<QueueEntry> _entries;
+ private final L _entries;
- private final SubscriptionList _subscriptionList = new SubscriptionList();
+ private final QueueConsumerList<E,Q,L> _consumerList = new QueueConsumerList<E,Q,L>();
- private volatile Subscription _exclusiveSubscriber;
+ private volatile QueueConsumer<?,E,Q,L> _exclusiveSubscriber;
@@ -120,13 +118,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private final AtomicLong _persistentMessageDequeueSize = new AtomicLong();
private final AtomicLong _persistentMessageEnqueueCount = new AtomicLong();
private final AtomicLong _persistentMessageDequeueCount = new AtomicLong();
- private final AtomicInteger _consumerCountHigh = new AtomicInteger(0);
- private final AtomicLong _msgTxnEnqueues = new AtomicLong(0);
- private final AtomicLong _byteTxnEnqueues = new AtomicLong(0);
- private final AtomicLong _msgTxnDequeues = new AtomicLong(0);
- private final AtomicLong _byteTxnDequeues = new AtomicLong(0);
private final AtomicLong _unackedMsgCount = new AtomicLong(0);
- private final AtomicLong _unackedMsgCountHigh = new AtomicLong(0);
private final AtomicLong _unackedMsgBytes = new AtomicLong();
private final AtomicInteger _bindingCountHigh = new AtomicInteger();
@@ -165,14 +157,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private final Set<AMQSessionModel> _blockedChannels = new ConcurrentSkipListSet<AMQSessionModel>();
private final AtomicBoolean _deleted = new AtomicBoolean(false);
- private final List<Task> _deleteTaskList = new CopyOnWriteArrayList<Task>();
+ private final List<Action<AMQQueue>> _deleteTaskList = new CopyOnWriteArrayList<Action<AMQQueue>>();
private LogSubject _logSubject;
private LogActor _logActor;
- private static final String SUB_FLUSH_RUNNER = "SUB_FLUSH_RUNNER";
- private boolean _nolocal;
+ private boolean _noLocal;
private final AtomicBoolean _overfull = new AtomicBoolean(false);
private boolean _deleteOnNoConsumers;
@@ -185,20 +176,15 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
/** the maximum delivery count for each message on this queue or 0 if maximum delivery count is not to be enforced. */
private int _maximumDeliveryCount;
- private final MessageGroupManager _messageGroupManager;
+ private final MessageGroupManager<E,Q,L> _messageGroupManager;
- private final Collection<SubscriptionRegistrationListener> _subscriptionListeners =
- new ArrayList<SubscriptionRegistrationListener>();
+ private final Collection<ConsumerRegistrationListener<Q>> _consumerListeners =
+ new ArrayList<ConsumerRegistrationListener<Q>>();
private AMQQueue.NotificationListener _notificationListener;
private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length];
- public SimpleAMQQueue(UUID id, String queueName, boolean durable, String owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String, Object> arguments)
- {
- this(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, new SimpleQueueEntryList.Factory(), arguments);
- }
-
protected SimpleAMQQueue(UUID id,
String name,
boolean durable,
@@ -206,7 +192,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
boolean autoDelete,
boolean exclusive,
VirtualHost virtualHost,
- QueueEntryListFactory entryListFactory, Map<String,Object> arguments)
+ QueueEntryListFactory<E,Q,L> entryListFactory, Map<String,Object> arguments)
{
if (name == null)
@@ -225,7 +211,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
_autoDelete = autoDelete;
_exclusive = exclusive;
_virtualHost = virtualHost;
- _entries = entryListFactory.createQueueEntryList(this);
+ _entries = entryListFactory.createQueueEntryList((Q)this);
_arguments = Collections.synchronizedMap(arguments == null ? new LinkedHashMap<String, Object>() : new LinkedHashMap<String, Object>(arguments));
_id = id;
@@ -251,13 +237,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
Object defaultGroup = arguments.get(Queue.MESSAGE_GROUP_DEFAULT_GROUP);
_messageGroupManager =
- new DefinedGroupMessageGroupManager(String.valueOf(arguments.get(Queue.MESSAGE_GROUP_KEY)),
+ new DefinedGroupMessageGroupManager<E,Q,L>(String.valueOf(arguments.get(Queue.MESSAGE_GROUP_KEY)),
defaultGroup == null ? DEFAULT_SHARED_MESSAGE_GROUP : defaultGroup.toString(),
this);
}
else
{
- _messageGroupManager = new AssignedSubscriptionMessageGroupManager(String.valueOf(arguments.get(
+ _messageGroupManager = new AssignedConsumerMessageGroupManager<E,Q,L>(String.valueOf(arguments.get(
Queue.MESSAGE_GROUP_KEY)), DEFAULT_MAX_GROUPS);
}
}
@@ -289,21 +275,20 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
catch (RejectedExecutionException ree)
{
- if (_stopped.get())
- {
- // Ignore - SubFlusherRunner or QueueRunner submitted execution as queue was being stopped.
- }
- else
+ // Ignore - SubFlusherRunner or QueueRunner submitted execution as queue was being stopped.
+ if(!_stopped.get())
{
_logger.error("Unexpected rejected execution", ree);
throw ree;
+
}
+
}
}
public void setNoLocal(boolean nolocal)
{
- _nolocal = nolocal;
+ _noLocal = nolocal;
}
public UUID getId()
@@ -388,11 +373,17 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _name;
}
- // ------ Manage Subscriptions
+ // ------ Manage Consumers
+
- public synchronized void registerSubscription(final Subscription subscription, final boolean exclusive)
- throws AMQSecurityException, ExistingExclusiveSubscription, ExistingSubscriptionPreventsExclusive
+ @Override
+ public synchronized <T extends ConsumerTarget> QueueConsumer<T,E,Q,L> addConsumer(final T target,
+ final FilterManager filters,
+ final Class<? extends ServerMessage> messageClass,
+ final String consumerName,
+ EnumSet<Consumer.Option> optionSet) throws AMQException
{
+
// Access control
if (!getVirtualHost().getSecurityManager().authoriseConsume(this))
{
@@ -400,58 +391,61 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- if (hasExclusiveSubscriber())
+ if (hasExclusiveConsumer())
{
- throw new ExistingExclusiveSubscription();
+ throw new ExistingExclusiveConsumer();
}
- if (exclusive && !subscription.isTransient())
+
+ boolean exclusive = optionSet.contains(Consumer.Option.EXCLUSIVE);
+ boolean isTransient = optionSet.contains(Consumer.Option.TRANSIENT);
+
+ if (exclusive && !isTransient && getConsumerCount() != 0)
{
- if (getConsumerCount() != 0)
- {
- throw new ExistingSubscriptionPreventsExclusive();
- }
- else
- {
- _exclusiveSubscriber = subscription;
- }
+ throw new ExistingConsumerPreventsExclusive();
+ }
+
+ QueueConsumer<T,E,Q,L> consumer = new QueueConsumer<T,E,Q,L>(filters, messageClass,
+ optionSet.contains(Consumer.Option.ACQUIRES),
+ optionSet.contains(Consumer.Option.SEES_REQUEUES),
+ consumerName, optionSet.contains(Consumer.Option.TRANSIENT), target);
+ target.consumerAdded(consumer);
+
+
+ if (exclusive && !isTransient)
+ {
+ _exclusiveSubscriber = consumer;
}
- if(subscription.isActive())
+ if(consumer.isActive())
{
_activeSubscriberCount.incrementAndGet();
}
- subscription.setStateListener(this);
- subscription.setQueueContext(new QueueContext(_entries.getHead()));
+
+ consumer.setStateListener(this);
+ consumer.setQueueContext(new QueueContext<E,Q,L>(_entries.getHead()));
if (!isDeleted())
{
- subscription.setQueue(this, exclusive);
- if(_nolocal)
+ consumer.setQueue((Q)this, exclusive);
+ if(_noLocal)
{
- subscription.setNoLocal(_nolocal);
+ consumer.setNoLocal(true);
}
- synchronized (_subscriptionListeners)
+ synchronized (_consumerListeners)
{
- for(SubscriptionRegistrationListener listener : _subscriptionListeners)
+ for(ConsumerRegistrationListener<Q> listener : _consumerListeners)
{
- listener.subscriptionRegistered(this, subscription);
+ listener.consumerAdded((Q)this, consumer);
}
}
- _subscriptionList.add(subscription);
-
- //Increment consumerCountHigh if necessary. (un)registerSubscription are both
- //synchronized methods so we don't need additional synchronization here
- if(_consumerCountHigh.get() < getConsumerCount())
- {
- _consumerCountHigh.incrementAndGet();
- }
+ _consumerList.add(consumer);
if (isDeleted())
{
- subscription.queueDeleted(this);
+ consumer.queueDeleted();
}
}
else
@@ -459,42 +453,49 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
// TODO
}
- deliverAsync(subscription);
+ deliverAsync(consumer);
+
+ return consumer;
}
- public synchronized void unregisterSubscription(final Subscription subscription) throws AMQException
+ synchronized void unregisterConsumer(final QueueConsumer<?,E,Q,L> consumer) throws AMQException
{
- if (subscription == null)
+ if (consumer == null)
{
- throw new NullPointerException("subscription argument is null");
+ throw new NullPointerException("consumer argument is null");
}
- boolean removed = _subscriptionList.remove(subscription);
+ boolean removed = _consumerList.remove(consumer);
if (removed)
{
- subscription.close();
+ consumer.close();
// No longer can the queue have an exclusive consumer
setExclusiveSubscriber(null);
- subscription.setQueueContext(null);
+ consumer.setQueueContext(null);
+
+ if(!isDeleted() && isExclusive() && getConsumerCount() == 0)
+ {
+ setAuthorizationHolder(null);
+ }
if(_messageGroupManager != null)
{
- resetSubPointersForGroups(subscription, true);
+ resetSubPointersForGroups(consumer, true);
}
- synchronized (_subscriptionListeners)
+ synchronized (_consumerListeners)
{
- for(SubscriptionRegistrationListener listener : _subscriptionListeners)
+ for(ConsumerRegistrationListener<Q> listener : _consumerListeners)
{
- listener.subscriptionUnregistered(this, subscription);
+ listener.consumerRemoved((Q)this, consumer);
}
}
// auto-delete queues must be deleted if there are no remaining subscribers
- if (_autoDelete && getDeleteOnNoConsumers() && !subscription.isTransient() && getConsumerCount() == 0 )
+ if (_autoDelete && getDeleteOnNoConsumers() && !consumer.isTransient() && getConsumerCount() == 0 )
{
if (_logger.isInfoEnabled())
{
@@ -503,57 +504,57 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
getVirtualHost().removeQueue(this);
- // we need to manually fire the event to the removed subscription (which was the last one left for this
- // queue. This is because the delete method uses the subscription set which has just been cleared
- subscription.queueDeleted(this);
+ // we need to manually fire the event to the removed consumer (which was the last one left for this
+ // queue. This is because the delete method uses the consumer set which has just been cleared
+ consumer.queueDeleted();
}
}
}
- public Collection<Subscription> getConsumers()
+ public Collection<QueueConsumer<?,E,Q,L>> getConsumers()
{
- List<Subscription> consumers = new ArrayList<Subscription>();
- SubscriptionList.SubscriptionNodeIterator iter = _subscriptionList.iterator();
+ List<QueueConsumer<?,E,Q,L>> consumers = new ArrayList<QueueConsumer<?,E,Q,L>>();
+ QueueConsumerList.ConsumerNodeIterator<E,Q,L> iter = _consumerList.iterator();
while(iter.advance())
{
- consumers.add(iter.getNode().getSubscription());
+ consumers.add(iter.getNode().getConsumer());
}
return consumers;
}
- public void addSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ public void addConsumerRegistrationListener(final ConsumerRegistrationListener<Q> listener)
{
- synchronized (_subscriptionListeners)
+ synchronized (_consumerListeners)
{
- _subscriptionListeners.add(listener);
+ _consumerListeners.add(listener);
}
}
- public void removeSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ public void removeConsumerRegistrationListener(final ConsumerRegistrationListener<Q> listener)
{
- synchronized (_subscriptionListeners)
+ synchronized (_consumerListeners)
{
- _subscriptionListeners.remove(listener);
+ _consumerListeners.remove(listener);
}
}
- public void resetSubPointersForGroups(Subscription subscription, boolean clearAssignments)
+ public void resetSubPointersForGroups(QueueConsumer<?,E,Q,L> consumer, boolean clearAssignments)
{
- QueueEntry entry = _messageGroupManager.findEarliestAssignedAvailableEntry(subscription);
+ E entry = _messageGroupManager.findEarliestAssignedAvailableEntry(consumer);
if(clearAssignments)
{
- _messageGroupManager.clearAssignments(subscription);
+ _messageGroupManager.clearAssignments(consumer);
}
if(entry != null)
{
- SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
+ QueueConsumerList.ConsumerNodeIterator<E,Q,L> subscriberIter = _consumerList.iterator();
// iterate over all the subscribers, and if they are in advance of this queue entry then move them backwards
while (subscriberIter.advance())
{
- Subscription sub = subscriberIter.getNode().getSubscription();
+ QueueConsumer<?,E,Q,L> sub = subscriberIter.getNode().getConsumer();
// we don't make browsers send the same stuff twice
if (sub.seesRequeues())
@@ -591,11 +592,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- public int getBindingCountHigh()
- {
- return _bindingCountHigh.get();
- }
-
public void removeBinding(final Binding binding)
{
_bindings.remove(binding);
@@ -617,59 +613,45 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
// ------ Enqueue / Dequeue
- public void enqueue(ServerMessage message) throws AMQException
- {
- enqueue(message, null);
- }
- public void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException
+ public void enqueue(ServerMessage message, Action<? super MessageInstance<?, QueueConsumer<?,E,Q,L>>> action) throws AMQException
{
- enqueue(message, false, action);
- }
-
- public void enqueue(ServerMessage message, boolean transactional, PostEnqueueAction action) throws AMQException
- {
-
- if(transactional)
- {
- incrementTxnEnqueueStats(message);
- }
incrementQueueCount();
incrementQueueSize(message);
_totalMessagesReceived.incrementAndGet();
- QueueEntry entry;
- final Subscription exclusiveSub = _exclusiveSubscriber;
+ E entry;
+ final QueueConsumer<?,E,Q,L> exclusiveSub = _exclusiveSubscriber;
entry = _entries.add(message);
if(action != null || (exclusiveSub == null && _queueRunner.isIdle()))
{
/*
- iterate over subscriptions and if any is at the end of the queue and can deliver this message, then deliver the message
+ iterate over consumers and if any is at the end of the queue and can deliver this message, then deliver the message
*/
- SubscriptionList.SubscriptionNode node = _subscriptionList.getMarkedNode();
- SubscriptionList.SubscriptionNode nextNode = node.findNext();
+ QueueConsumerList.ConsumerNode<E,Q,L> node = _consumerList.getMarkedNode();
+ QueueConsumerList.ConsumerNode<E,Q,L> nextNode = node.findNext();
if (nextNode == null)
{
- nextNode = _subscriptionList.getHead().findNext();
+ nextNode = _consumerList.getHead().findNext();
}
while (nextNode != null)
{
- if (_subscriptionList.updateMarkedNode(node, nextNode))
+ if (_consumerList.updateMarkedNode(node, nextNode))
{
break;
}
else
{
- node = _subscriptionList.getMarkedNode();
+ node = _consumerList.getMarkedNode();
nextNode = node.findNext();
if (nextNode == null)
{
- nextNode = _subscriptionList.getHead().findNext();
+ nextNode = _consumerList.getHead().findNext();
}
}
}
@@ -683,13 +665,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if (nextNode == null)
{
loops--;
- nextNode = _subscriptionList.getHead();
+ nextNode = _consumerList.getHead();
}
else
{
- // if subscription at end, and active, offer
- Subscription sub = nextNode.getSubscription();
- deliverToSubscription(sub, entry);
+ // if consumer at end, and active, offer
+ QueueConsumer<?,E,Q,L> sub = nextNode.getConsumer();
+ deliverToConsumer(sub, entry);
}
nextNode = nextNode.findNext();
@@ -699,7 +681,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if (entry.isAvailable())
{
- checkSubscriptionsNotAheadOfDelivery(entry);
+ checkConsumersNotAheadOfDelivery(entry);
if (exclusiveSub != null)
{
@@ -715,12 +697,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if(action != null)
{
- action.onEnqueue(entry);
+ action.performAction(entry);
}
}
- private void deliverToSubscription(final Subscription sub, final QueueEntry entry)
+ private void deliverToConsumer(final QueueConsumer<?,E,Q,L> sub, final E entry)
throws AMQException
{
@@ -729,14 +711,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
try
{
if (!sub.isSuspended()
- && subscriptionReadyAndHasInterest(sub, entry)
+ && consumerReadyAndHasInterest(sub, entry)
&& mightAssign(sub, entry)
&& !sub.wouldSuspend(entry))
{
if (sub.acquires() && !assign(sub, entry))
{
// restore credit here that would have been taken away by wouldSuspend since we didn't manage
- // to acquire the entry for this subscription
+ // to acquire the entry for this consumer
sub.restoreCredit(entry);
}
else
@@ -752,7 +734,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- private boolean assign(final Subscription sub, final QueueEntry entry)
+ private boolean assign(final QueueConsumer<?,E,Q,L> sub, final E entry)
{
if(_messageGroupManager == null)
{
@@ -766,17 +748,17 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- private boolean mightAssign(final Subscription sub, final QueueEntry entry)
+ private boolean mightAssign(final QueueConsumer<?,E,Q,L> sub, final E entry)
{
if(_messageGroupManager == null || !sub.acquires())
{
return true;
}
- Subscription assigned = _messageGroupManager.getAssignedSubscription(entry);
+ QueueConsumer assigned = _messageGroupManager.getAssignedConsumer(entry);
return (assigned == null) || (assigned == sub);
}
- protected void checkSubscriptionsNotAheadOfDelivery(final QueueEntry entry)
+ protected void checkConsumersNotAheadOfDelivery(final E entry)
{
// This method is only required for queues which mess with ordering
// Simple Queues don't :-)
@@ -810,19 +792,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
getAtomicQueueCount().incrementAndGet();
}
- private void incrementTxnEnqueueStats(final ServerMessage message)
- {
- _msgTxnEnqueues.incrementAndGet();
- _byteTxnEnqueues.addAndGet(message.getSize());
- }
-
- private void incrementTxnDequeueStats(QueueEntry entry)
- {
- _msgTxnDequeues.incrementAndGet();
- _byteTxnDequeues.addAndGet(entry.getSize());
- }
-
- private void deliverMessage(final Subscription sub, final QueueEntry entry, boolean batch)
+ private void deliverMessage(final QueueConsumer<?,E,Q,L> sub, final E entry, boolean batch)
throws AMQException
{
setLastSeenEntry(sub, entry);
@@ -833,18 +803,18 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
sub.send(entry, batch);
}
- private boolean subscriptionReadyAndHasInterest(final Subscription sub, final QueueEntry entry) throws AMQException
+ private boolean consumerReadyAndHasInterest(final QueueConsumer<?,E,Q,L> sub, final E entry) throws AMQException
{
return sub.hasInterest(entry) && (getNextAvailableEntry(sub) == entry);
}
- private void setLastSeenEntry(final Subscription sub, final QueueEntry entry)
+ private void setLastSeenEntry(final QueueConsumer<?,E,Q,L> sub, final E entry)
{
- QueueContext subContext = (QueueContext) sub.getQueueContext();
+ QueueContext<E,Q,L> subContext = sub.getQueueContext();
if (subContext != null)
{
- QueueEntry releasedEntry = subContext.getReleasedEntry();
+ E releasedEntry = subContext.getReleasedEntry();
QueueContext._lastSeenUpdater.set(subContext, entry);
if(releasedEntry == entry)
@@ -854,13 +824,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- private void updateSubRequeueEntry(final Subscription sub, final QueueEntry entry)
+ private void updateSubRequeueEntry(final QueueConsumer<?,E,Q,L> sub, final E entry)
{
- QueueContext subContext = (QueueContext) sub.getQueueContext();
+ QueueContext<E,Q,L> subContext = sub.getQueueContext();
if(subContext != null)
{
- QueueEntry oldEntry;
+ E oldEntry;
while((oldEntry = subContext.getReleasedEntry()) == null || oldEntry.compareTo(entry) > 0)
{
@@ -872,13 +842,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- public void requeue(QueueEntry entry)
+ public void requeue(E entry)
{
- SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
+ QueueConsumerList.ConsumerNodeIterator<E,Q,L> subscriberIter = _consumerList.iterator();
// iterate over all the subscribers, and if they are in advance of this queue entry then move them backwards
while (subscriberIter.advance() && entry.isAvailable())
{
- Subscription sub = subscriberIter.getNode().getSubscription();
+ QueueConsumer<?,E,Q,L> sub = subscriberIter.getNode().getConsumer();
// we don't make browsers send the same stuff twice
if (sub.seesRequeues())
@@ -891,25 +861,21 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void dequeue(QueueEntry entry, Subscription sub)
+ @Override
+ public void dequeue(E entry)
{
decrementQueueCount();
decrementQueueSize(entry);
- if (entry.acquiredBySubscription())
+ if (entry.acquiredByConsumer())
{
_deliveredMessages.decrementAndGet();
}
- if(sub != null && sub.isSessionTransactional())
- {
- incrementTxnDequeueStats(entry);
- }
-
checkCapacity();
}
- private void decrementQueueSize(final QueueEntry entry)
+ private void decrementQueueSize(final E entry)
{
final ServerMessage message = entry.getMessage();
long size = message.getSize();
@@ -928,17 +894,17 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
_dequeueCount.incrementAndGet();
}
- public boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException
+ public boolean resend(final E entry, final QueueConsumer<?,E,Q,L> consumer) throws AMQException
{
- /* TODO : This is wrong as the subscription may be suspended, we should instead change the state of the message
- entry to resend and move back the subscription pointer. */
+ /* TODO : This is wrong as the consumer may be suspended, we should instead change the state of the message
+ entry to resend and move back the consumer pointer. */
- subscription.getSendLock();
+ consumer.getSendLock();
try
{
- if (!subscription.isClosed())
+ if (!consumer.isClosed())
{
- deliverMessage(subscription, entry, false);
+ deliverMessage(consumer, entry, false);
return true;
}
else
@@ -948,7 +914,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
finally
{
- subscription.releaseSendLock();
+ consumer.releaseSendLock();
}
}
@@ -956,12 +922,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public int getConsumerCount()
{
- return _subscriptionList.size();
- }
-
- public int getConsumerCountHigh()
- {
- return _consumerCountHigh.get();
+ return _consumerList.size();
}
public int getActiveConsumerCount()
@@ -1009,11 +970,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public long getOldestMessageArrivalTime()
{
- QueueEntry entry = getOldestQueueEntry();
+ E entry = getOldestQueueEntry();
return entry == null ? Long.MAX_VALUE : entry.getMessage().getArrivalTime();
}
- protected QueueEntry getOldestQueueEntry()
+ protected E getOldestQueueEntry()
{
return _entries.next(_entries.getHead());
}
@@ -1023,13 +984,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _deleted.get();
}
- public List<QueueEntry> getMessagesOnTheQueue()
+ public List<E> getMessagesOnTheQueue()
{
- ArrayList<QueueEntry> entryList = new ArrayList<QueueEntry>();
- QueueEntryIterator queueListIterator = _entries.iterator();
+ ArrayList<E> entryList = new ArrayList<E>();
+ QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator();
while (queueListIterator.advance())
{
- QueueEntry node = queueListIterator.getNode();
+ E node = queueListIterator.getNode();
if (node != null && !node.isDeleted())
{
entryList.add(node);
@@ -1039,16 +1000,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void stateChange(Subscription sub, Subscription.State oldState, Subscription.State newState)
+ public void stateChanged(QueueConsumer<?,E,Q,L> sub, QueueConsumer.State oldState, QueueConsumer.State newState)
{
- if (oldState == Subscription.State.ACTIVE && newState != Subscription.State.ACTIVE)
+ if (oldState == QueueConsumer.State.ACTIVE && newState != QueueConsumer.State.ACTIVE)
{
_activeSubscriberCount.decrementAndGet();
}
- else if (newState == Subscription.State.ACTIVE)
+ else if (newState == QueueConsumer.State.ACTIVE)
{
- if (oldState != Subscription.State.ACTIVE)
+ if (oldState != QueueConsumer.State.ACTIVE)
{
_activeSubscriberCount.incrementAndGet();
@@ -1057,7 +1018,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- public int compareTo(final AMQQueue o)
+ public int compareTo(final Q o)
{
return _name.compareTo(o.getName());
}
@@ -1072,12 +1033,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _atomicQueueSize;
}
- public boolean hasExclusiveSubscriber()
+ public boolean hasExclusiveConsumer()
{
return _exclusiveSubscriber != null;
}
- private void setExclusiveSubscriber(Subscription exclusiveSubscriber)
+ private void setExclusiveSubscriber(QueueConsumer<?,E,Q,L> exclusiveSubscriber)
{
_exclusiveSubscriber = exclusiveSubscriber;
}
@@ -1088,32 +1049,32 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
/** Used to track bindings to exchanges so that on deletion they can easily be cancelled. */
- protected QueueEntryList getEntries()
+ protected L getEntries()
{
return _entries;
}
- protected SubscriptionList getSubscriptionList()
+ protected QueueConsumerList<E,Q,L> getConsumerList()
{
- return _subscriptionList;
+ return _consumerList;
}
- public static interface QueueEntryFilter
+ public static interface QueueEntryFilter<E extends QueueEntry>
{
- public boolean accept(QueueEntry entry);
+ public boolean accept(E entry);
public boolean filterComplete();
}
- public List<QueueEntry> getMessagesOnTheQueue(final long fromMessageId, final long toMessageId)
+ public List<E> getMessagesOnTheQueue(final long fromMessageId, final long toMessageId)
{
- return getMessagesOnTheQueue(new QueueEntryFilter()
+ return getMessagesOnTheQueue(new QueueEntryFilter<E>()
{
- public boolean accept(QueueEntry entry)
+ public boolean accept(E entry)
{
final long messageId = entry.getMessage().getMessageNumber();
return messageId >= fromMessageId && messageId <= toMessageId;
@@ -1126,13 +1087,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
});
}
- public QueueEntry getMessageOnTheQueue(final long messageId)
+ public E getMessageOnTheQueue(final long messageId)
{
- List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
+ List<E> entries = getMessagesOnTheQueue(new QueueEntryFilter<E>()
{
private boolean _complete;
- public boolean accept(QueueEntry entry)
+ public boolean accept(E entry)
{
_complete = entry.getMessage().getMessageNumber() == messageId;
return _complete;
@@ -1146,13 +1107,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return entries.isEmpty() ? null : entries.get(0);
}
- public List<QueueEntry> getMessagesOnTheQueue(QueueEntryFilter filter)
+ public List<E> getMessagesOnTheQueue(QueueEntryFilter<E> filter)
{
- ArrayList<QueueEntry> entryList = new ArrayList<QueueEntry>();
- QueueEntryIterator queueListIterator = _entries.iterator();
+ ArrayList<E> entryList = new ArrayList<E>();
+ QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator();
while (queueListIterator.advance() && !filter.filterComplete())
{
- QueueEntry node = queueListIterator.getNode();
+ E node = queueListIterator.getNode();
if (!node.isDeleted() && filter.accept(node))
{
entryList.add(node);
@@ -1162,13 +1123,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void visit(final QueueEntryVisitor visitor)
+ public void visit(final QueueEntryVisitor<E> visitor)
{
- QueueEntryIterator queueListIterator = _entries.iterator();
+ QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator();
while(queueListIterator.advance())
{
- QueueEntry node = queueListIterator.getNode();
+ E node = queueListIterator.getNode();
if(!node.isDeleted())
{
@@ -1185,17 +1146,17 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
*
* The 'queue position' index starts from 1. Using 0 in 'from' will be ignored and continue from 1.
* Using 0 in the 'to' field will return an empty list regardless of the 'from' value.
- * @param fromPosition
- * @param toPosition
- * @return
+ * @param fromPosition first message position
+ * @param toPosition last message position
+ * @return list of messages
*/
- public List<QueueEntry> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition)
+ public List<E> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition)
{
- return getMessagesOnTheQueue(new QueueEntryFilter()
+ return getMessagesOnTheQueue(new QueueEntryFilter<E>()
{
private long position = 0;
- public boolean accept(QueueEntry entry)
+ public boolean accept(E entry)
{
position++;
return (position >= fromPosition) && (position <= toPosition);
@@ -1224,12 +1185,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
// TODO - now only used by the tests
public void deleteMessageFromTop()
{
- QueueEntryIterator queueListIterator = _entries.iterator();
+ QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator();
boolean noDeletes = true;
while (noDeletes && queueListIterator.advance())
{
- QueueEntry node = queueListIterator.getNode();
+ E node = queueListIterator.getNode();
if (node.acquire())
{
dequeueEntry(node);
@@ -1252,14 +1213,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
throw new AMQSecurityException("Permission denied: queue " + getName());
}
- QueueEntryIterator queueListIterator = _entries.iterator();
+ QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator();
long count = 0;
ServerTransaction txn = new LocalTransaction(getVirtualHost().getMessageStore());
while (queueListIterator.advance())
{
- QueueEntry node = queueListIterator.getNode();
+ E node = queueListIterator.getNode();
if (node.acquire())
{
dequeueEntry(node, txn);
@@ -1276,13 +1237,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return count;
}
- private void dequeueEntry(final QueueEntry node)
+ private void dequeueEntry(final E node)
{
ServerTransaction txn = new AutoCommitTransaction(getVirtualHost().getMessageStore());
dequeueEntry(node, txn);
}
- private void dequeueEntry(final QueueEntry node, ServerTransaction txn)
+ private void dequeueEntry(final E node, ServerTransaction txn)
{
txn.dequeue(this, node.getMessage(),
new ServerTransaction.Action()
@@ -1300,18 +1261,18 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
});
}
- public void addQueueDeleteTask(final Task task)
+ public void addQueueDeleteTask(final Action<AMQQueue> task)
{
_deleteTaskList.add(task);
}
- public void removeQueueDeleteTask(final Task task)
+ public void removeQueueDeleteTask(final Action<AMQQueue> task)
{
_deleteTaskList.remove(task);
}
// TODO list all thrown exceptions
- public int delete() throws AMQSecurityException, AMQException
+ public int delete() throws AMQException
{
// Check access
if (!_virtualHost.getSecurityManager().authoriseDelete(this))
@@ -1322,27 +1283,29 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if (!_deleted.getAndSet(true))
{
- for (Binding b : _bindings)
+ final ArrayList<Binding> bindingCopy = new ArrayList<Binding>(_bindings);
+
+ for (Binding b : bindingCopy)
{
b.getExchange().removeBinding(b);
}
- SubscriptionList.SubscriptionNodeIterator subscriptionIter = _subscriptionList.iterator();
+ QueueConsumerList.ConsumerNodeIterator consumerNodeIterator = _consumerList.iterator();
- while (subscriptionIter.advance())
+ while (consumerNodeIterator.advance())
{
- Subscription s = subscriptionIter.getNode().getSubscription();
+ QueueConsumer s = consumerNodeIterator.getNode().getConsumer();
if (s != null)
{
- s.queueDeleted(this);
+ s.queueDeleted();
}
}
- List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
+ List<E> entries = getMessagesOnTheQueue(new QueueEntryFilter<E>()
{
- public boolean accept(QueueEntry entry)
+ public boolean accept(E entry)
{
return entry.acquire();
}
@@ -1356,7 +1319,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
ServerTransaction txn = new LocalTransaction(getVirtualHost().getMessageStore());
- for(final QueueEntry entry : entries)
+ for(final E entry : entries)
{
// TODO log requeues with a post enqueue action
int requeues = entry.routeToAlternate(null, txn);
@@ -1375,9 +1338,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- for (Task task : _deleteTaskList)
+ for (Action<AMQQueue> task : _deleteTaskList)
{
- task.doTask(this);
+ task.performAction(this);
}
_deleteTaskList.clear();
@@ -1461,7 +1424,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void deliverAsync(Subscription sub)
+ public void deliverAsync(QueueConsumer<?,E,Q,L> sub)
{
if(_exclusiveSubscriber == null)
{
@@ -1469,28 +1432,23 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
else
{
- SubFlushRunner flusher = (SubFlushRunner) sub.get(SUB_FLUSH_RUNNER);
- if(flusher == null)
- {
- flusher = new SubFlushRunner(sub);
- sub.set(SUB_FLUSH_RUNNER, flusher);
- }
+ SubFlushRunner flusher = sub.getRunner();
flusher.execute(_asyncDelivery);
}
}
- public void flushSubscription(Subscription sub) throws AMQException
+ void flushConsumer(QueueConsumer<?,E,Q,L> sub) throws AMQException
{
// Access control
if (!getVirtualHost().getSecurityManager().authoriseConsume(this))
{
throw new AMQSecurityException("Permission denied: " + getName());
}
- flushSubscription(sub, Long.MAX_VALUE);
+ flushConsumer(sub, Long.MAX_VALUE);
}
- public boolean flushSubscription(Subscription sub, long iterations) throws AMQException
+ boolean flushConsumer(QueueConsumer<?,E,Q,L> sub, long iterations) throws AMQException
{
boolean atTail = false;
final boolean keepSendLockHeld = iterations <= SimpleAMQQueue.MAX_ASYNC_DELIVERIES;
@@ -1546,29 +1504,29 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- // if there's (potentially) more than one subscription the others will potentially not have been advanced to the
+ // if there's (potentially) more than one consumer the others will potentially not have been advanced to the
// next entry they are interested in yet. This would lead to holding on to references to expired messages, etc
// which would give us memory "leak".
- if (!hasExclusiveSubscriber())
+ if (!hasExclusiveConsumer())
{
- advanceAllSubscriptions();
+ advanceAllConsumers();
}
return atTail;
}
/**
- * Attempt delivery for the given subscription.
+ * Attempt delivery for the given consumer.
*
- * Looks up the next node for the subscription and attempts to deliver it.
+ * Looks up the next node for the consumer and attempts to deliver it.
*
*
- * @param sub
- * @param batch
+ * @param sub the consumer
+ * @param batch true if processing can be batched
* @return true if we have completed all possible deliveries for this sub.
* @throws AMQException
*/
- private boolean attemptDelivery(Subscription sub, boolean batch) throws AMQException
+ private boolean attemptDelivery(QueueConsumer<?,E,Q,L> sub, boolean batch) throws AMQException
{
boolean atTail = false;
@@ -1576,7 +1534,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if (subActive)
{
- QueueEntry node = getNextAvailableEntry(sub);
+ E node = getNextAvailableEntry(sub);
if (node != null && node.isAvailable())
{
@@ -1587,7 +1545,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if (sub.acquires() && !assign(sub, node))
{
// restore credit here that would have been taken away by wouldSuspend since we didn't manage
- // to acquire the entry for this subscription
+ // to acquire the entry for this consumer
sub.restoreCredit(node);
}
else
@@ -1598,7 +1556,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
else // Not enough Credit for message and wouldSuspend
{
- //QPID-1187 - Treat the subscription as suspended for this message
+ //QPID-1187 - Treat the consumer as suspended for this message
// and wait for the message to be removed to continue delivery.
subActive = false;
node.addStateChangeListener(new QueueEntryListener(sub));
@@ -1611,13 +1569,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return atTail || !subActive;
}
- protected void advanceAllSubscriptions() throws AMQException
+ protected void advanceAllConsumers() throws AMQException
{
- SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
- while (subscriberIter.advance())
+ QueueConsumerList.ConsumerNodeIterator<E,Q,L> consumerNodeIterator = _consumerList.iterator();
+ while (consumerNodeIterator.advance())
{
- SubscriptionList.SubscriptionNode subNode = subscriberIter.getNode();
- Subscription sub = subNode.getSubscription();
+ QueueConsumerList.ConsumerNode<E,Q,L> subNode = consumerNodeIterator.getNode();
+ QueueConsumer<?,E,Q,L> sub = subNode.getConsumer();
if(sub.acquires())
{
getNextAvailableEntry(sub);
@@ -1629,16 +1587,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- private QueueEntry getNextAvailableEntry(final Subscription sub)
+ private E getNextAvailableEntry(final QueueConsumer<?,E,Q,L> sub)
throws AMQException
{
- QueueContext context = (QueueContext) sub.getQueueContext();
+ QueueContext<E,Q,L> context = sub.getQueueContext();
if(context != null)
{
- QueueEntry lastSeen = context.getLastSeenEntry();
- QueueEntry releasedNode = context.getReleasedEntry();
+ E lastSeen = context.getLastSeenEntry();
+ E releasedNode = context.getReleasedEntry();
- QueueEntry node = (releasedNode != null && lastSeen.compareTo(releasedNode)>=0) ? releasedNode : _entries.next(lastSeen);
+ E node = (releasedNode != null && lastSeen.compareTo(releasedNode)>=0) ? releasedNode : _entries.next(lastSeen);
boolean expired = false;
while (node != null && (!node.isAvailable() || (expired = node.expired()) || !sub.hasInterest(node) ||
@@ -1670,12 +1628,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- public boolean isEntryAheadOfSubscription(QueueEntry entry, Subscription sub)
+ public boolean isEntryAheadOfConsumer(E entry, QueueConsumer<?,E,Q,L> sub)
{
- QueueContext context = (QueueContext) sub.getQueueContext();
+ QueueContext<E,Q,L> context = sub.getQueueContext();
if(context != null)
{
- QueueEntry releasedNode = context.getReleasedEntry();
+ E releasedNode = context.getReleasedEntry();
return releasedNode != null && releasedNode.compareTo(entry) < 0;
}
else
@@ -1689,14 +1647,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
*
* A queue Runner is started whenever a state change occurs, e.g when a new
* message arrives on the queue and cannot be immediately delivered to a
- * subscription (i.e. asynchronous delivery is required). Unless there are
- * SubFlushRunners operating (due to subscriptions unsuspending) which are
+ * consumer (i.e. asynchronous delivery is required). Unless there are
+ * SubFlushRunners operating (due to consumers unsuspending) which are
* capable of accepting/delivering all messages then these messages would
* otherwise remain on the queue.
*
* processQueue should be running while there are messages on the queue AND
- * there are subscriptions that can deliver them. If there are no
- * subscriptions capable of delivering the remaining messages on the queue
+ * there are consumers that can deliver them. If there are no
+ * consumers capable of delivering the remaining messages on the queue
* then processQueue should stop to prevent spinning.
*
* Since processQueue is runs in a fixed size Executor, it should not run
@@ -1712,7 +1670,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
*/
public long processQueue(QueueRunner runner) throws AMQException
{
- long stateChangeCount = Long.MIN_VALUE;
+ long stateChangeCount;
long previousStateChangeCount = Long.MIN_VALUE;
long rVal = Long.MIN_VALUE;
boolean deliveryIncomplete = true;
@@ -1720,7 +1678,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
boolean lastLoop = false;
int iterations = MAX_ASYNC_DELIVERIES;
- final int numSubs = _subscriptionList.size();
+ final int numSubs = _consumerList.size();
final int perSub = Math.max(iterations / Math.max(numSubs,1), 1);
@@ -1731,8 +1689,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
// So whilst delivery/rejection is going on a processQueue thread will be running
while (iterations != 0 && ((previousStateChangeCount != (stateChangeCount = _stateChangeCount.get())) || deliveryIncomplete))
{
- // we want to have one extra loop after every subscription has reached the point where it cannot move
- // further, just in case the advance of one subscription in the last loop allows a different subscription to
+ // we want to have one extra loop after every consumer has reached the point where it cannot move
+ // further, just in case the advance of one consumer in the last loop allows a different consumer to
// move forward in the next iteration
if (previousStateChangeCount != stateChangeCount)
@@ -1744,14 +1702,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
previousStateChangeCount = stateChangeCount;
- boolean allSubscriptionsDone = true;
- boolean subscriptionDone;
+ boolean allConsumersDone = true;
+ boolean consumerDone;
- SubscriptionList.SubscriptionNodeIterator subscriptionIter = _subscriptionList.iterator();
+ QueueConsumerList.ConsumerNodeIterator<E,Q,L> consumerNodeIterator = _consumerList.iterator();
//iterate over the subscribers and try to advance their pointer
- while (subscriptionIter.advance())
+ while (consumerNodeIterator.advance())
{
- Subscription sub = subscriptionIter.getNode().getSubscription();
+ QueueConsumer<?,E,Q,L> sub = consumerNodeIterator.getNode().getConsumer();
sub.getSendLock();
try
@@ -1759,8 +1717,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
for(int i = 0 ; i < perSub; i++)
{
//attempt delivery. returns true if no further delivery currently possible to this sub
- subscriptionDone = attemptDelivery(sub, true);
- if (subscriptionDone)
+ consumerDone = attemptDelivery(sub, true);
+ if (consumerDone)
{
sub.flushBatched();
if (lastLoop && !sub.isSuspended())
@@ -1771,9 +1729,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
else
{
- //this subscription can accept additional deliveries, so we must
+ //this consumer can accept additional deliveries, so we must
//keep going after this (if iteration slicing allows it)
- allSubscriptionsDone = false;
+ allConsumersDone = false;
lastLoop = false;
if(--iterations == 0)
{
@@ -1792,24 +1750,24 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- if(allSubscriptionsDone && lastLoop)
+ if(allConsumersDone && lastLoop)
{
//We have done an extra loop already and there are again
//again no further delivery attempts possible, only
//keep going if state change demands it.
deliveryIncomplete = false;
}
- else if(allSubscriptionsDone)
+ else if(allConsumersDone)
{
- //All subscriptions reported being done, but we have to do
+ //All consumers reported being done, but we have to do
//an extra loop if the iterations are not exhausted and
//there is still any work to be done
- deliveryIncomplete = _subscriptionList.size() != 0;
+ deliveryIncomplete = _consumerList.size() != 0;
lastLoop = true;
}
else
{
- //some subscriptions can still accept more messages,
+ //some consumers can still accept more messages,
//keep going if iteration count allows.
lastLoop = false;
deliveryIncomplete = true;
@@ -1833,11 +1791,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public void checkMessageStatus() throws AMQException
{
- QueueEntryIterator queueListIterator = _entries.iterator();
+ QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator();
while (queueListIterator.advance())
{
- QueueEntry node = queueListIterator.getNode();
+ E node = queueListIterator.getNode();
// Only process nodes that are not currently deleted and not dequeued
if (!node.isDeleted())
{
@@ -1984,12 +1942,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _notificationChecks;
}
- private final class QueueEntryListener implements QueueEntry.StateChangeListener
+ private final class QueueEntryListener implements StateChangeListener<E, QueueEntry.State>
{
- private final Subscription _sub;
+ private final QueueConsumer<?,E,Q,L> _sub;
- public QueueEntryListener(final Subscription sub)
+ public QueueEntryListener(final QueueConsumer<?,E,Q,L> sub)
{
_sub = sub;
}
@@ -2005,7 +1963,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return System.identityHashCode(_sub);
}
- public void stateChanged(QueueEntry entry, QueueEntry.State oldSate, QueueEntry.State newState)
+ public void stateChanged(E entry, QueueEntry.State oldSate, QueueEntry.State newState)
{
entry.removeStateChangeListener(this);
deliverAsync(_sub);
@@ -2076,26 +2034,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _dequeueSize.get();
}
- public long getByteTxnEnqueues()
- {
- return _byteTxnEnqueues.get();
- }
-
- public long getByteTxnDequeues()
- {
- return _byteTxnDequeues.get();
- }
-
- public long getMsgTxnEnqueues()
- {
- return _msgTxnEnqueues.get();
- }
-
- public long getMsgTxnDequeues()
- {
- return _msgTxnDequeues.get();
- }
-
public long getPersistentByteEnqueues()
{
return _persistentMessageEnqueueSize.get();
@@ -2123,11 +2061,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return getName();
}
- public long getUnackedMessageCountHigh()
- {
- return _unackedMsgCountHigh.get();
- }
-
public long getUnackedMessageCount()
{
return _unackedMsgCount.get();
@@ -2138,25 +2071,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _unackedMsgBytes.get();
}
- public void decrementUnackedMsgCount(QueueEntry queueEntry)
+ public void decrementUnackedMsgCount(E queueEntry)
{
_unackedMsgCount.decrementAndGet();
_unackedMsgBytes.addAndGet(-queueEntry.getSize());
}
- private void incrementUnackedMsgCount(QueueEntry entry)
+ private void incrementUnackedMsgCount(E entry)
{
- long unackedMsgCount = _unackedMsgCount.incrementAndGet();
+ _unackedMsgCount.incrementAndGet();
_unackedMsgBytes.addAndGet(entry.getSize());
-
- long unackedMsgCountHigh;
- while(unackedMsgCount > (unackedMsgCountHigh = _unackedMsgCountHigh.get()))
- {
- if(_unackedMsgCountHigh.compareAndSet(unackedMsgCountHigh, unackedMsgCount))
- {
- break;
- }
- }
}
public LogActor getLogActor()
@@ -2224,4 +2148,39 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return (String) _arguments.get(Queue.DESCRIPTION);
}
+ public final <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message,
+ final InstanceProperties instanceProperties,
+ final ServerTransaction txn,
+ final Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction)
+ {
+ txn.enqueue(this,message, new ServerTransaction.Action()
+ {
+ MessageReference _reference = message.newReference();
+
+ public void postCommit()
+ {
+ try
+ {
+ SimpleAMQQueue.this.enqueue(message, postEnqueueAction);
+ }
+ catch (AMQException e)
+ {
+ // TODO
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ _reference.release();
+ }
+ }
+
+ public void onRollback()
+ {
+ _reference.release();
+ }
+ });
+ return 1;
+
+ }
+
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
index b8d8ec19f4..b6954e0696 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
@@ -1,205 +1,25 @@
/*
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-* KIND, either express or implied. See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*
-*/
+ *
+ * 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.queue;
-import org.apache.qpid.server.message.ServerMessage;
-
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-
-public class SimpleQueueEntryList implements QueueEntryList<SimpleQueueEntryImpl>
+public interface SimpleQueueEntryList<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> extends QueueEntryList<E,Q,L,QueueConsumer<?,E,Q,L>>
{
-
- private final SimpleQueueEntryImpl _head;
-
- private volatile SimpleQueueEntryImpl _tail;
-
- static final AtomicReferenceFieldUpdater<SimpleQueueEntryList, SimpleQueueEntryImpl>
- _tailUpdater =
- AtomicReferenceFieldUpdater.newUpdater
- (SimpleQueueEntryList.class, SimpleQueueEntryImpl.class, "_tail");
-
-
- private final AMQQueue _queue;
-
- static final AtomicReferenceFieldUpdater<SimpleQueueEntryImpl, SimpleQueueEntryImpl>
- _nextUpdater = SimpleQueueEntryImpl._nextUpdater;
-
- private AtomicLong _scavenges = new AtomicLong(0L);
- private final long _scavengeCount = Integer.getInteger("qpid.queue.scavenge_count", 50);
- private final AtomicReference<SimpleQueueEntryImpl> _unscavengedHWM = new AtomicReference<SimpleQueueEntryImpl>();
-
-
- public SimpleQueueEntryList(AMQQueue queue)
- {
- _queue = queue;
- _head = new SimpleQueueEntryImpl(this);
- _tail = _head;
- }
-
- void scavenge()
- {
- SimpleQueueEntryImpl hwm = _unscavengedHWM.getAndSet(null);
- SimpleQueueEntryImpl next = _head.getNextValidEntry();
-
- if(hwm != null)
- {
- while (next != null && hwm.compareTo(next)>0)
- {
- next = next.getNextValidEntry();
- }
- }
- }
-
-
- public AMQQueue getQueue()
- {
- return _queue;
- }
-
-
- public SimpleQueueEntryImpl add(ServerMessage message)
- {
- SimpleQueueEntryImpl node = createQueueEntry(message);
- for (;;)
- {
- SimpleQueueEntryImpl tail = _tail;
- SimpleQueueEntryImpl next = tail.getNextNode();
- if (tail == _tail)
- {
- if (next == null)
- {
- node.setEntryId(tail.getEntryId()+1);
- if (_nextUpdater.compareAndSet(tail, null, node))
- {
- _tailUpdater.compareAndSet(this, tail, node);
-
- return node;
- }
- }
- else
- {
- _tailUpdater.compareAndSet(this,tail, next);
- }
- }
- }
- }
-
- protected SimpleQueueEntryImpl createQueueEntry(ServerMessage<?> message)
- {
- return new SimpleQueueEntryImpl(this, message);
- }
-
- public SimpleQueueEntryImpl next(SimpleQueueEntryImpl node)
- {
- return node.getNextValidEntry();
- }
-
- public static class QueueEntryIteratorImpl implements QueueEntryIterator<SimpleQueueEntryImpl>
- {
- private SimpleQueueEntryImpl _lastNode;
-
- QueueEntryIteratorImpl(SimpleQueueEntryImpl startNode)
- {
- _lastNode = startNode;
- }
-
- public boolean atTail()
- {
- return _lastNode.getNextValidEntry() == null;
- }
-
- public SimpleQueueEntryImpl getNode()
- {
- return _lastNode;
- }
-
- public boolean advance()
- {
- SimpleQueueEntryImpl nextValidNode = _lastNode.getNextValidEntry();
-
- if(nextValidNode != null)
- {
- _lastNode = nextValidNode;
- }
-
- return nextValidNode != null;
- }
- }
-
- public QueueEntryIteratorImpl iterator()
- {
- return new QueueEntryIteratorImpl(_head);
- }
-
-
- public SimpleQueueEntryImpl getHead()
- {
- return _head;
- }
-
- public void entryDeleted(SimpleQueueEntryImpl queueEntry)
- {
- SimpleQueueEntryImpl next = _head.getNextNode();
- SimpleQueueEntryImpl newNext = _head.getNextValidEntry();
-
- // the head of the queue has not been deleted, hence the deletion must have been mid queue.
- if (next == newNext)
- {
- SimpleQueueEntryImpl unscavengedHWM = _unscavengedHWM.get();
- while(unscavengedHWM == null || unscavengedHWM.compareTo(queueEntry)<0)
- {
- _unscavengedHWM.compareAndSet(unscavengedHWM, queueEntry);
- unscavengedHWM = _unscavengedHWM.get();
- }
- if (_scavenges.incrementAndGet() > _scavengeCount)
- {
- _scavenges.set(0L);
- scavenge();
- }
- }
- else
- {
- SimpleQueueEntryImpl unscavengedHWM = _unscavengedHWM.get();
- if(unscavengedHWM != null && (next == null || unscavengedHWM.compareTo(next) < 0))
- {
- _unscavengedHWM.compareAndSet(unscavengedHWM, null);
- }
- }
- }
-
- public int getPriorities()
- {
- return 0;
- }
-
- static class Factory implements QueueEntryListFactory
- {
-
- public SimpleQueueEntryList createQueueEntryList(AMQQueue queue)
- {
- return new SimpleQueueEntryList(queue);
- }
- }
-
-
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java
index b3566df0c4..2cae18f3ec 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java
@@ -20,16 +20,19 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Map;
import java.util.UUID;
-public class SortedQueue extends OutOfOrderQueue
+public class SortedQueue extends OutOfOrderQueue<SortedQueueEntry, SortedQueue, SortedQueueEntryList>
{
//Lock object to synchronize enqueue. Used instead of the object
- //monitor to prevent lock order issues with subscription sendLocks
+ //monitor to prevent lock order issues with consumer sendLocks
//and consumer updates in the super classes
private final Object _sortedQueueLock = new Object();
private final String _sortedPropertyName;
@@ -38,17 +41,33 @@ public class SortedQueue extends OutOfOrderQueue
final boolean durable, final String owner, final boolean autoDelete,
final boolean exclusive, final VirtualHost virtualHost, Map<String, Object> arguments, String sortedPropertyName)
{
+ this(id, name, durable, owner, autoDelete, exclusive,
+ virtualHost, arguments, sortedPropertyName, new SortedQueueEntryListFactory(sortedPropertyName));
+ }
+
+
+ protected SortedQueue(UUID id, final String name,
+ final boolean durable, final String owner, final boolean autoDelete,
+ final boolean exclusive, final VirtualHost virtualHost,
+ Map<String, Object> arguments,
+ String sortedPropertyName,
+ QueueEntryListFactory<SortedQueueEntry,SortedQueue,SortedQueueEntryList> factory)
+ {
super(id, name, durable, owner, autoDelete, exclusive,
- virtualHost, new SortedQueueEntryListFactory(sortedPropertyName), arguments);
+ virtualHost, factory, arguments);
this._sortedPropertyName = sortedPropertyName;
}
+
public String getSortedPropertyName()
{
return _sortedPropertyName;
}
- public void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException
+ @Override
+ public void enqueue(final ServerMessage message,
+ final Action<? super MessageInstance<?, QueueConsumer<?, SortedQueueEntry, SortedQueue, SortedQueueEntryList>>> action)
+ throws AMQException
{
synchronized (_sortedQueueLock)
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntry.java
index 1052adbe67..30d58138fb 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntry.java
@@ -24,37 +24,37 @@ import org.apache.qpid.server.message.ServerMessage;
/**
* An implementation of QueueEntryImpl to be used in SortedQueueEntryList.
*/
-public class SortedQueueEntryImpl extends QueueEntryImpl
+public class SortedQueueEntry extends QueueEntryImpl<SortedQueueEntry, SortedQueue, SortedQueueEntryList>
{
public static enum Colour
{
RED, BLACK
};
- private volatile SortedQueueEntryImpl _next;
- private SortedQueueEntryImpl _prev;
+ private volatile SortedQueueEntry _next;
+ private SortedQueueEntry _prev;
private String _key;
private Colour _colour = Colour.BLACK;
- private SortedQueueEntryImpl _parent;
- private SortedQueueEntryImpl _left;
- private SortedQueueEntryImpl _right;
+ private SortedQueueEntry _parent;
+ private SortedQueueEntry _left;
+ private SortedQueueEntry _right;
- public SortedQueueEntryImpl(final SortedQueueEntryList queueEntryList)
+ public SortedQueueEntry(final SortedQueueEntryList queueEntryList)
{
super(queueEntryList);
}
- public SortedQueueEntryImpl(final SortedQueueEntryList queueEntryList,
- final ServerMessage message, final long entryId)
+ public SortedQueueEntry(final SortedQueueEntryList queueEntryList,
+ final ServerMessage message, final long entryId)
{
super(queueEntryList, message, entryId);
}
@Override
- public int compareTo(final QueueEntry o)
+ public int compareTo(final SortedQueueEntry o)
{
- final String otherKey = ((SortedQueueEntryImpl) o)._key;
+ final String otherKey = o._key;
final int compare = _key == null ? (otherKey == null ? 0 : -1) : otherKey == null ? 1 : _key.compareTo(otherKey);
return compare == 0 ? super.compareTo(o) : compare;
}
@@ -69,33 +69,33 @@ public class SortedQueueEntryImpl extends QueueEntryImpl
return _key;
}
- public SortedQueueEntryImpl getLeft()
+ public SortedQueueEntry getLeft()
{
return _left;
}
- public SortedQueueEntryImpl getNextNode()
+ public SortedQueueEntry getNextNode()
{
return _next;
}
@Override
- public SortedQueueEntryImpl getNextValidEntry()
+ public SortedQueueEntry getNextValidEntry()
{
return getNextNode();
}
- public SortedQueueEntryImpl getParent()
+ public SortedQueueEntry getParent()
{
return _parent;
}
- public SortedQueueEntryImpl getPrev()
+ public SortedQueueEntry getPrev()
{
return _prev;
}
- public SortedQueueEntryImpl getRight()
+ public SortedQueueEntry getRight()
{
return _right;
}
@@ -110,27 +110,27 @@ public class SortedQueueEntryImpl extends QueueEntryImpl
_key = key;
}
- public void setLeft(final SortedQueueEntryImpl left)
+ public void setLeft(final SortedQueueEntry left)
{
_left = left;
}
- public void setNext(final SortedQueueEntryImpl next)
+ public void setNext(final SortedQueueEntry next)
{
_next = next;
}
- public void setParent(final SortedQueueEntryImpl parent)
+ public void setParent(final SortedQueueEntry parent)
{
_parent = parent;
}
- public void setPrev(final SortedQueueEntryImpl prev)
+ public void setPrev(final SortedQueueEntry prev)
{
_prev = prev;
}
- public void setRight(final SortedQueueEntryImpl right)
+ public void setRight(final SortedQueueEntry right)
{
_right = right;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java
index 85559157a9..05b874cd91 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java
@@ -21,37 +21,37 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.queue.SortedQueueEntryImpl.Colour;
+import org.apache.qpid.server.queue.SortedQueueEntry.Colour;
/**
* A sorted implementation of QueueEntryList.
* Uses the red/black tree algorithm specified in "Introduction to Algorithms".
* ISBN-10: 0262033844
* ISBN-13: 978-0262033848
- * @see http://en.wikipedia.org/wiki/Red-black_tree
+ * see http://en.wikipedia.org/wiki/Red-black_tree
*/
-public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl>
+public class SortedQueueEntryList implements SimpleQueueEntryList<SortedQueueEntry, SortedQueue, SortedQueueEntryList>
{
- private final SortedQueueEntryImpl _head;
- private SortedQueueEntryImpl _root;
+ private final SortedQueueEntry _head;
+ private SortedQueueEntry _root;
private long _entryId = Long.MIN_VALUE;
private final Object _lock = new Object();
- private final AMQQueue _queue;
+ private final SortedQueue _queue;
private final String _propertyName;
- public SortedQueueEntryList(final AMQQueue queue, final String propertyName)
+ public SortedQueueEntryList(final SortedQueue queue, final String propertyName)
{
_queue = queue;
- _head = new SortedQueueEntryImpl(this);
+ _head = new SortedQueueEntry(this);
_propertyName = propertyName;
}
- public AMQQueue getQueue()
+ public SortedQueue getQueue()
{
return _queue;
}
- public SortedQueueEntryImpl add(final ServerMessage message)
+ public SortedQueueEntry add(final ServerMessage message)
{
synchronized(_lock)
{
@@ -62,7 +62,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
key = val.toString();
}
- final SortedQueueEntryImpl entry = new SortedQueueEntryImpl(this,message, ++_entryId);
+ final SortedQueueEntry entry = new SortedQueueEntry(this,message, ++_entryId);
entry.setKey(key);
insert(entry);
@@ -75,9 +75,9 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
* Red Black Tree insert implementation.
* @param entry the entry to insert.
*/
- private void insert(final SortedQueueEntryImpl entry)
+ private void insert(final SortedQueueEntry entry)
{
- SortedQueueEntryImpl node = _root;
+ SortedQueueEntry node;
if((node = _root) == null)
{
_root = entry;
@@ -87,7 +87,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
}
else
{
- SortedQueueEntryImpl parent = null;
+ SortedQueueEntry parent = null;
while(node != null)
{
parent = node;
@@ -105,7 +105,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
if(entry.compareTo(parent) < 0)
{
parent.setLeft(entry);
- final SortedQueueEntryImpl prev = parent.getPrev();
+ final SortedQueueEntry prev = parent.getPrev();
entry.setNext(parent);
prev.setNext(entry);
entry.setPrev(prev);
@@ -115,7 +115,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
{
parent.setRight(entry);
- final SortedQueueEntryImpl next = parent.getNextValidEntry();
+ final SortedQueueEntry next = parent.getNextValidEntry();
entry.setNext(next);
parent.setNext(entry);
@@ -130,15 +130,15 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
insertFixup(entry);
}
- private void insertFixup(SortedQueueEntryImpl entry)
+ private void insertFixup(SortedQueueEntry entry)
{
while(isParentColour(entry, Colour.RED))
{
- final SortedQueueEntryImpl grandparent = nodeGrandparent(entry);
+ final SortedQueueEntry grandparent = nodeGrandparent(entry);
if(nodeParent(entry) == leftChild(grandparent))
{
- final SortedQueueEntryImpl y = rightChild(grandparent);
+ final SortedQueueEntry y = rightChild(grandparent);
if(isNodeColour(y, Colour.RED))
{
setColour(nodeParent(entry), Colour.BLACK);
@@ -160,7 +160,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
}
else
{
- final SortedQueueEntryImpl y = leftChild(grandparent);
+ final SortedQueueEntry y = leftChild(grandparent);
if(isNodeColour(y, Colour.RED))
{
setColour(nodeParent(entry), Colour.BLACK);
@@ -184,11 +184,11 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
_root.setColour(Colour.BLACK);
}
- private void leftRotate(final SortedQueueEntryImpl entry)
+ private void leftRotate(final SortedQueueEntry entry)
{
if(entry != null)
{
- final SortedQueueEntryImpl rightChild = rightChild(entry);
+ final SortedQueueEntry rightChild = rightChild(entry);
entry.setRight(rightChild.getLeft());
if(entry.getRight() != null)
{
@@ -212,11 +212,11 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
}
}
- private void rightRotate(final SortedQueueEntryImpl entry)
+ private void rightRotate(final SortedQueueEntry entry)
{
if(entry != null)
{
- final SortedQueueEntryImpl leftChild = leftChild(entry);
+ final SortedQueueEntry leftChild = leftChild(entry);
entry.setLeft(leftChild.getRight());
if(entry.getLeft() != null)
{
@@ -240,7 +240,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
}
}
- private void setColour(final SortedQueueEntryImpl node, final Colour colour)
+ private void setColour(final SortedQueueEntry node, final Colour colour)
{
if(node != null)
{
@@ -248,45 +248,45 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
}
}
- private SortedQueueEntryImpl leftChild(final SortedQueueEntryImpl node)
+ private SortedQueueEntry leftChild(final SortedQueueEntry node)
{
return node == null ? null : node.getLeft();
}
- private SortedQueueEntryImpl rightChild(final SortedQueueEntryImpl node)
+ private SortedQueueEntry rightChild(final SortedQueueEntry node)
{
return node == null ? null : node.getRight();
}
- private SortedQueueEntryImpl nodeParent(final SortedQueueEntryImpl node)
+ private SortedQueueEntry nodeParent(final SortedQueueEntry node)
{
return node == null ? null : node.getParent();
}
- private SortedQueueEntryImpl nodeGrandparent(final SortedQueueEntryImpl node)
+ private SortedQueueEntry nodeGrandparent(final SortedQueueEntry node)
{
return nodeParent(nodeParent(node));
}
- private boolean isParentColour(final SortedQueueEntryImpl node, final SortedQueueEntryImpl.Colour colour)
+ private boolean isParentColour(final SortedQueueEntry node, final SortedQueueEntry.Colour colour)
{
return node != null && isNodeColour(node.getParent(), colour);
}
- protected boolean isNodeColour(final SortedQueueEntryImpl node, final SortedQueueEntryImpl.Colour colour)
+ protected boolean isNodeColour(final SortedQueueEntry node, final SortedQueueEntry.Colour colour)
{
return (node == null ? Colour.BLACK : node.getColour()) == colour;
}
- public SortedQueueEntryImpl next(final SortedQueueEntryImpl node)
+ public SortedQueueEntry next(final SortedQueueEntry node)
{
synchronized(_lock)
{
if(node.isDeleted() && _head != node)
{
- SortedQueueEntryImpl current = _head;
- SortedQueueEntryImpl next;
+ SortedQueueEntry current = _head;
+ SortedQueueEntry next;
while(current != null)
{
next = current.getNextValidEntry();
@@ -308,22 +308,22 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
}
}
- public QueueEntryIterator<SortedQueueEntryImpl> iterator()
+ public QueueEntryIterator<SortedQueueEntry,SortedQueue,SortedQueueEntryList,QueueConsumer<?,SortedQueueEntry,SortedQueue,SortedQueueEntryList>> iterator()
{
return new QueueEntryIteratorImpl(_head);
}
- public SortedQueueEntryImpl getHead()
+ public SortedQueueEntry getHead()
{
return _head;
}
- protected SortedQueueEntryImpl getRoot()
+ protected SortedQueueEntry getRoot()
{
return _root;
}
- public void entryDeleted(final SortedQueueEntryImpl entry)
+ public void entryDeleted(final SortedQueueEntry entry)
{
synchronized(_lock)
{
@@ -336,20 +336,20 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
// Then deal with the easy doubly linked list deletion (need to do
// this after the swap as the swap uses next
- final SortedQueueEntryImpl prev = entry.getPrev();
+ final SortedQueueEntry prev = entry.getPrev();
if(prev != null)
{
prev.setNext(entry.getNextValidEntry());
}
- final SortedQueueEntryImpl next = entry.getNextValidEntry();
+ final SortedQueueEntry next = entry.getNextValidEntry();
if(next != null)
{
next.setPrev(prev);
}
// now deal with splicing
- final SortedQueueEntryImpl chosenChild;
+ final SortedQueueEntry chosenChild;
if(leftChild(entry) != null)
{
@@ -428,14 +428,14 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
/**
* Swaps the position of the node in the tree with it's successor
* (that is the node with the next highest key)
- * @param entry
+ * @param entry the entry to be swapped with its successor
*/
- private void swapWithSuccessor(final SortedQueueEntryImpl entry)
+ private void swapWithSuccessor(final SortedQueueEntry entry)
{
- final SortedQueueEntryImpl next = entry.getNextValidEntry();
- final SortedQueueEntryImpl nextParent = next.getParent();
- final SortedQueueEntryImpl nextLeft = next.getLeft();
- final SortedQueueEntryImpl nextRight = next.getRight();
+ final SortedQueueEntry next = entry.getNextValidEntry();
+ final SortedQueueEntry nextParent = next.getParent();
+ final SortedQueueEntry nextLeft = next.getLeft();
+ final SortedQueueEntry nextRight = next.getRight();
final Colour nextColour = next.getColour();
// Special case - the successor is the right child of the node
@@ -530,7 +530,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
}
}
- private void deleteFixup(SortedQueueEntryImpl entry)
+ private void deleteFixup(SortedQueueEntry entry)
{
int i = 0;
while(entry != null && entry != _root
@@ -545,7 +545,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
if(entry == leftChild(nodeParent(entry)))
{
- SortedQueueEntryImpl rightSibling = rightChild(nodeParent(entry));
+ SortedQueueEntry rightSibling = rightChild(nodeParent(entry));
if(isNodeColour(rightSibling, Colour.RED))
{
setColour(rightSibling, Colour.BLACK);
@@ -578,7 +578,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
}
else
{
- SortedQueueEntryImpl leftSibling = leftChild(nodeParent(entry));
+ SortedQueueEntry leftSibling = leftChild(nodeParent(entry));
if(isNodeColour(leftSibling, Colour.RED))
{
setColour(leftSibling, Colour.BLACK);
@@ -613,16 +613,16 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
setColour(entry, Colour.BLACK);
}
- private Colour getColour(final SortedQueueEntryImpl x)
+ private Colour getColour(final SortedQueueEntry x)
{
return x == null ? null : x.getColour();
}
- public class QueueEntryIteratorImpl implements QueueEntryIterator<SortedQueueEntryImpl>
+ public class QueueEntryIteratorImpl implements QueueEntryIterator<SortedQueueEntry,SortedQueue,SortedQueueEntryList,QueueConsumer<?,SortedQueueEntry,SortedQueue,SortedQueueEntryList>>
{
- private SortedQueueEntryImpl _lastNode;
+ private SortedQueueEntry _lastNode;
- public QueueEntryIteratorImpl(final SortedQueueEntryImpl startNode)
+ public QueueEntryIteratorImpl(final SortedQueueEntry startNode)
{
_lastNode = startNode;
}
@@ -632,7 +632,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
return next(_lastNode) == null;
}
- public SortedQueueEntryImpl getNode()
+ public SortedQueueEntry getNode()
{
return _lastNode;
}
@@ -641,7 +641,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
{
if(!atTail())
{
- SortedQueueEntryImpl nextNode = next(_lastNode);
+ SortedQueueEntry nextNode = next(_lastNode);
while(nextNode.isDeleted() && next(nextNode) != null)
{
nextNode = next(nextNode);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryListFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryListFactory.java
index 87c79178f0..69ffcd67a7 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryListFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryListFactory.java
@@ -19,7 +19,7 @@
*/
package org.apache.qpid.server.queue;
-public class SortedQueueEntryListFactory implements QueueEntryListFactory
+public class SortedQueueEntryListFactory implements QueueEntryListFactory<SortedQueueEntry,SortedQueue,SortedQueueEntryList>
{
private final String _propertyName;
@@ -30,9 +30,8 @@ public class SortedQueueEntryListFactory implements QueueEntryListFactory
}
@Override
- public QueueEntryList<SortedQueueEntryImpl> createQueueEntryList(final AMQQueue queue)
+ public SortedQueueEntryList createQueueEntryList(final SortedQueue queue)
{
return new SortedQueueEntryList(queue, _propertyName);
}
-
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueue.java
new file mode 100644
index 0000000000..e2ccdc45cf
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueue.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.queue;
+
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import java.util.Map;
+import java.util.UUID;
+
+public class StandardQueue extends SimpleAMQQueue<StandardQueueEntry,StandardQueue,StandardQueueEntryList>
+{
+ public StandardQueue(final UUID id,
+ final String name,
+ final boolean durable,
+ final String owner,
+ final boolean autoDelete,
+ final boolean exclusive,
+ final VirtualHost virtualHost,
+ final Map<String, Object> arguments)
+ {
+ super(id, name, durable, owner, autoDelete, exclusive, virtualHost, new StandardQueueEntryList.Factory(), arguments);
+ }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/SubscriptionActor.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntry.java
index 906cd6db3a..368015e9c0 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/logging/actors/SubscriptionActor.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntry.java
@@ -18,29 +18,28 @@
* under the License.
*
*/
-package org.apache.qpid.server.logging.actors;
+package org.apache.qpid.server.queue;
-import org.apache.qpid.server.logging.RootMessageLogger;
-import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.message.ServerMessage;
-/**
- * The subscription actor provides formatted logging for actions that are
- * performed by the subscription. Such as STATE changes.
- */
-public class SubscriptionActor extends AbstractActor
+public class StandardQueueEntry extends OrderedQueueEntry<StandardQueueEntry, StandardQueue, StandardQueueEntryList>
{
- private SubscriptionLogSubject _logSubject;
-
- public SubscriptionActor(RootMessageLogger logger, Subscription subscription)
+ protected StandardQueueEntry(final StandardQueueEntryList queueEntryList)
{
- super(logger);
+ super(queueEntryList);
+ }
- _logSubject = new SubscriptionLogSubject(subscription);
+ public StandardQueueEntry(final StandardQueueEntryList queueEntryList,
+ final ServerMessage message,
+ final long entryId)
+ {
+ super(queueEntryList, message, entryId);
}
- public String getLogMessage()
+ public StandardQueueEntry(final StandardQueueEntryList queueEntryList, final ServerMessage message)
{
- return _logSubject.toLogString();
+ super(queueEntryList, message);
}
+
+
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntryList.java
new file mode 100644
index 0000000000..11ad04e61c
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntryList.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.queue;
+
+import org.apache.qpid.server.message.ServerMessage;
+
+public class StandardQueueEntryList extends OrderedQueueEntryList<StandardQueueEntry, StandardQueue, StandardQueueEntryList>
+{
+
+ private static final HeadCreator<StandardQueueEntry, StandardQueue, StandardQueueEntryList> HEAD_CREATOR = new HeadCreator<StandardQueueEntry, StandardQueue, StandardQueueEntryList>()
+ {
+ @Override
+ public StandardQueueEntry createHead(final StandardQueueEntryList list)
+ {
+ return new StandardQueueEntry(list);
+ }
+ };
+
+ public StandardQueueEntryList(final StandardQueue queue)
+ {
+ super(queue, HEAD_CREATOR);
+ }
+
+
+ protected StandardQueueEntry createQueueEntry(ServerMessage<?> message)
+ {
+ return new StandardQueueEntry(this, message);
+ }
+
+ static class Factory implements QueueEntryListFactory<StandardQueueEntry, StandardQueue, StandardQueueEntryList>
+ {
+
+ public StandardQueueEntryList createQueueEntryList(StandardQueue queue)
+ {
+ return new StandardQueueEntryList(queue);
+ }
+ }
+
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java
index 47a7d733dd..c30a48b03a 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java
@@ -25,7 +25,6 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.transport.TransportException;
import java.util.concurrent.Executor;
@@ -38,7 +37,7 @@ class SubFlushRunner implements Runnable
private static final Logger _logger = Logger.getLogger(SubFlushRunner.class);
- private final Subscription _sub;
+ private final QueueConsumer _sub;
private static int IDLE = 0;
private static int SCHEDULED = 1;
@@ -51,7 +50,7 @@ class SubFlushRunner implements Runnable
private static final long ITERATIONS = SimpleAMQQueue.MAX_ASYNC_DELIVERIES;
private final AtomicBoolean _stateChange = new AtomicBoolean();
- public SubFlushRunner(Subscription sub)
+ public SubFlushRunner(QueueConsumer sub)
{
_sub = sub;
}
@@ -65,7 +64,7 @@ class SubFlushRunner implements Runnable
try
{
CurrentActor.set(_sub.getLogActor());
- complete = getQueue().flushSubscription(_sub, ITERATIONS);
+ complete = getQueue().flushConsumer(_sub, ITERATIONS);
}
catch (AMQException e)
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
index 38d27c9c09..eb3bc9c9e0 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
@@ -1078,7 +1078,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
stmt.setString(4, "E");
for(Transaction.Record record : enqueues)
{
- stmt.setString(5, record.getQueue().getId().toString());
+ stmt.setString(5, record.getResource().getId().toString());
stmt.setLong(6, record.getMessage().getMessageNumber());
stmt.executeUpdate();
}
@@ -1089,7 +1089,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
stmt.setString(4, "D");
for(Transaction.Record record : dequeues)
{
- stmt.setString(5, record.getQueue().getId().toString());
+ stmt.setString(5, record.getResource().getId().toString());
stmt.setLong(6, record.getMessage().getMessageNumber());
stmt.executeUpdate();
}
@@ -1212,7 +1212,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
buf.position(1);
buf = buf.slice();
- metaData.writeToBuffer(0, buf);
+ metaData.writeToBuffer(buf);
ByteArrayInputStream bis = new ByteArrayInputStream(underlying);
try
{
@@ -1384,7 +1384,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
}
@Override
- public TransactionLogResource getQueue()
+ public TransactionLogResource getResource()
{
return this;
}
@@ -1414,10 +1414,22 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
}
@Override
+ public String getName()
+ {
+ return _queueId.toString();
+ }
+
+ @Override
public UUID getId()
{
return _queueId;
}
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
}
protected void recoverXids(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh) throws SQLException
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java
index a688b493e1..eff9bdf433 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java
@@ -29,6 +29,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.model.Binding;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.LifetimePolicy;
@@ -46,7 +47,7 @@ public class DurableConfigurationStoreHelper
Queue.EXCLUSIVE,
Queue.ALTERNATE_EXCHANGE));
- public static void updateQueue(DurableConfigurationStore store, AMQQueue queue) throws AMQStoreException
+ public static void updateQueue(DurableConfigurationStore store, AMQQueue<?,?,?> queue) throws AMQStoreException
{
Map<String, Object> attributesMap = new LinkedHashMap<String, Object>();
attributesMap.put(Queue.NAME, queue.getName());
@@ -71,7 +72,7 @@ public class DurableConfigurationStoreHelper
store.update(queue.getId(), QUEUE, attributesMap);
}
- public static void createQueue(DurableConfigurationStore store, AMQQueue queue)
+ public static void createQueue(DurableConfigurationStore store, AMQQueue<?,?,?> queue)
throws AMQStoreException
{
Map<String, Object> attributesMap = new HashMap<String, Object>();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java
index 9ae6cca8e6..4fd452649d 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java
@@ -29,7 +29,7 @@ public interface StorableMessageMetaData
int getStorableSize();
- int writeToBuffer(int offsetInMetaData, ByteBuffer dest);
+ int writeToBuffer(ByteBuffer dest);
int getContentSize();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/Transaction.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/Transaction.java
index 66bcfff32b..74b91dec2d 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/Transaction.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/Transaction.java
@@ -70,7 +70,7 @@ public interface Transaction
public static interface Record
{
- TransactionLogResource getQueue();
+ TransactionLogResource getResource();
EnqueueableMessage getMessage();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java
index 576dca847d..18b3125641 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java
@@ -24,5 +24,7 @@ import java.util.UUID;
public interface TransactionLogResource
{
+ String getName();
public UUID getId();
+ boolean isDurable();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
index 1f5a4907ed..57c67f54cd 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
@@ -25,12 +25,14 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQStoreException;
import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
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.store.StoreFuture;
import org.apache.qpid.server.store.Transaction;
+import org.apache.qpid.server.store.TransactionLogResource;
import java.util.Collection;
import java.util.List;
@@ -88,7 +90,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
- public void dequeue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction)
+ public void dequeue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction)
{
Transaction txn = null;
try
@@ -158,15 +160,15 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
}
- public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction)
+ public void dequeue(Collection<MessageInstance> queueEntries, Action postTransactionAction)
{
Transaction txn = null;
try
{
- for(QueueEntry entry : queueEntries)
+ for(MessageInstance entry : queueEntries)
{
ServerMessage message = entry.getMessage();
- BaseQueue queue = entry.getQueue();
+ TransactionLogResource queue = entry.getOwningResource();
if(message.isPersistent() && queue.isDurable())
{
@@ -210,7 +212,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
- public void enqueue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction)
+ public void enqueue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction)
{
Transaction txn = null;
try
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
index b057998456..4ea48c6a24 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
@@ -25,11 +25,13 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQStoreException;
import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
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.store.Transaction;
+import org.apache.qpid.server.store.TransactionLogResource;
import java.util.Collection;
import java.util.List;
@@ -73,7 +75,7 @@ public class AutoCommitTransaction implements ServerTransaction
immediateAction.postCommit();
}
- public void dequeue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction)
+ public void dequeue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction)
{
Transaction txn = null;
try
@@ -105,15 +107,15 @@ public class AutoCommitTransaction implements ServerTransaction
}
- public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction)
+ public void dequeue(Collection<MessageInstance> queueEntries, Action postTransactionAction)
{
Transaction txn = null;
try
{
- for(QueueEntry entry : queueEntries)
+ for(MessageInstance entry : queueEntries)
{
ServerMessage message = entry.getMessage();
- BaseQueue queue = entry.getQueue();
+ TransactionLogResource queue = entry.getOwningResource();
if(message.isPersistent() && queue.isDurable())
{
@@ -152,7 +154,7 @@ public class AutoCommitTransaction implements ServerTransaction
}
- public void enqueue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction)
+ public void enqueue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction)
{
Transaction txn = null;
try
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java
index 35f2887562..4a7c16a7cd 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java
@@ -22,10 +22,12 @@
package org.apache.qpid.server.txn;
import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.message.MessageInstance;
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.store.TransactionLogResource;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Xid;
@@ -74,7 +76,7 @@ public class DistributedTransaction implements ServerTransaction
}
}
- public void dequeue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction)
+ public void dequeue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction)
{
if(_branch != null)
{
@@ -87,13 +89,13 @@ public class DistributedTransaction implements ServerTransaction
}
}
- public void dequeue(Collection<QueueEntry> messages, Action postTransactionAction)
+ public void dequeue(Collection<MessageInstance> messages, Action postTransactionAction)
{
if(_branch != null)
{
- for(QueueEntry entry : messages)
+ for(MessageInstance entry : messages)
{
- _branch.dequeue(entry.getQueue(), entry.getMessage());
+ _branch.dequeue(entry.getOwningResource(), entry.getMessage());
}
_branch.addPostTransactionAction(postTransactionAction);
}
@@ -103,13 +105,12 @@ public class DistributedTransaction implements ServerTransaction
}
}
- public void enqueue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction)
+ public void enqueue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction)
{
if(_branch != null)
{
_branch.enqueue(queue, message);
_branch.addPostTransactionAction(postTransactionAction);
- enqueue(Collections.singletonList(queue), message, postTransactionAction);
}
else
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DtxBranch.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
index 6b12862690..2505548ab8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
@@ -34,6 +34,7 @@ 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.store.Transaction;
+import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Xid;
@@ -335,7 +336,7 @@ public class DtxBranch
{
if(enqueue.isDurable())
{
- _transaction.enqueueMessage(enqueue.getQueue(), enqueue.getMessage());
+ _transaction.enqueueMessage(enqueue.getResource(), enqueue.getMessage());
}
}
@@ -344,7 +345,7 @@ public class DtxBranch
{
if(enqueue.isDurable())
{
- _transaction.dequeueMessage(enqueue.getQueue(), enqueue.getMessage());
+ _transaction.dequeueMessage(enqueue.getResource(), enqueue.getMessage());
}
}
}
@@ -356,31 +357,31 @@ public class DtxBranch
}
- public void dequeue(BaseQueue queue, EnqueueableMessage message)
+ public void dequeue(TransactionLogResource resource, EnqueueableMessage message)
{
- _dequeueRecords.add(new Record(queue, message));
+ _dequeueRecords.add(new Record(resource, message));
}
- public void enqueue(BaseQueue queue, EnqueueableMessage message)
+ public void enqueue(TransactionLogResource queue, EnqueueableMessage message)
{
_enqueueRecords.add(new Record(queue, message));
}
private static final class Record implements Transaction.Record
{
- private final BaseQueue _queue;
+ private final TransactionLogResource _resource;
private final EnqueueableMessage _message;
- public Record(BaseQueue queue, EnqueueableMessage message)
+ public Record(TransactionLogResource resource, EnqueueableMessage message)
{
- _queue = queue;
+ _resource = resource;
_message = message;
}
- public BaseQueue getQueue()
+ public TransactionLogResource getResource()
{
- return _queue;
+ return _resource;
}
public EnqueueableMessage getMessage()
@@ -390,7 +391,7 @@ public class DtxBranch
public boolean isDurable()
{
- return _message.isPersistent() && _queue.isDurable();
+ return _message.isPersistent() && _resource.isDurable();
}
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
index 81aabc6bd3..4b02d4f8ec 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
@@ -21,7 +21,9 @@
package org.apache.qpid.server.txn;
import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.TransactionLogResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -91,7 +93,7 @@ public class LocalTransaction implements ServerTransaction
_postTransactionActions.add(postTransactionAction);
}
- public void dequeue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction)
+ public void dequeue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction)
{
sync();
_postTransactionActions.add(postTransactionAction);
@@ -118,7 +120,7 @@ public class LocalTransaction implements ServerTransaction
}
}
- public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction)
+ public void dequeue(Collection<MessageInstance> queueEntries, Action postTransactionAction)
{
sync();
_postTransactionActions.add(postTransactionAction);
@@ -126,10 +128,10 @@ public class LocalTransaction implements ServerTransaction
try
{
- for(QueueEntry entry : queueEntries)
+ for(MessageInstance entry : queueEntries)
{
ServerMessage message = entry.getMessage();
- BaseQueue queue = entry.getQueue();
+ TransactionLogResource queue = entry.getOwningResource();
if(message.isPersistent() && queue.isDurable())
{
@@ -195,7 +197,7 @@ public class LocalTransaction implements ServerTransaction
}
}
- public void enqueue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction)
+ public void enqueue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction)
{
sync();
_postTransactionActions.add(postTransactionAction);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
index 240ad154ba..cae5fa73bf 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
@@ -24,8 +24,9 @@ import java.util.Collection;
import java.util.List;
import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.queue.BaseQueue;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.store.TransactionLogResource;
/**
@@ -79,21 +80,21 @@ public interface ServerTransaction
*
* A store operation will result only for a persistent message on a durable queue.
*/
- void dequeue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction);
+ void dequeue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction);
/**
* Dequeue a message(s) from queue(s) registering a post transaction action.
*
* Store operations will result only for a persistent messages on durable queues.
*/
- void dequeue(Collection<QueueEntry> messages, Action postTransactionAction);
+ void dequeue(Collection<MessageInstance> messages, Action postTransactionAction);
/**
* Enqueue a message to a queue registering a post transaction action.
*
* A store operation will result only for a persistent message on a durable queue.
*/
- void enqueue(BaseQueue queue, EnqueueableMessage message, Action postTransactionAction);
+ void enqueue(TransactionLogResource queue, EnqueueableMessage message, Action postTransactionAction);
/**
* Enqueue a message(s) to queue(s) registering a post transaction action.
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/Action.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/Action.java
new file mode 100644
index 0000000000..0d53b4d03b
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/Action.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.util;
+
+public interface Action<T>
+{
+ void performAction(T object);
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/StateChangeListener.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/StateChangeListener.java
new file mode 100644
index 0000000000..b5dc90cfb6
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/StateChangeListener.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.util;
+
+public interface StateChangeListener<T, E extends Enum>
+{
+ void stateChanged(T object, E oldState, E newState);
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
index b7a98384ac..7d2429f907 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
@@ -52,8 +52,13 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.VirtualHostMessages;
import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageNode;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.plugin.ExchangeType;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+import org.apache.qpid.server.plugin.SystemNodeCreator;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.protocol.LinkRegistry;
@@ -105,8 +110,8 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
private final DtxRegistry _dtxRegistry;
private final AMQQueueFactory _queueFactory;
-
- private final org.apache.qpid.server.model.VirtualHost _virtualHost;
+ private final SystemNodeRegistry _systemNodeRegistry = new SystemNodeRegistry();
+ private final org.apache.qpid.server.model.VirtualHost _model;
private final Map<String, LinkRegistry> _linkRegistry = new HashMap<String, LinkRegistry>();
@@ -125,6 +130,13 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
private volatile State _state = State.INITIALISING;
private volatile ScheduledThreadPoolExecutor _houseKeepingTasks;
+ private final Map<String, MessageDestination> _systemNodeDestinations =
+ Collections.synchronizedMap(new HashMap<String,MessageDestination>());
+
+ private final Map<String, MessageSource> _systemNodeSources =
+ Collections.synchronizedMap(new HashMap<String,MessageSource>());
+
+
public AbstractVirtualHost(VirtualHostRegistry virtualHostRegistry,
StatisticsGatherer brokerStatisticsGatherer,
SecurityManager parentSecurityManager,
@@ -146,6 +158,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
_vhostConfig = hostConfig;
_name = _vhostConfig.getName();
_dtxRegistry = new DtxRegistry();
+ _model = virtualHost;
_id = UUIDGenerator.generateVhostUUID(_name);
@@ -162,7 +175,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
_exchangeRegistry = new DefaultExchangeRegistry(this, _queueRegistry);
- _virtualHost = virtualHost;
+ registerSystemNodes();
initialiseStatistics();
@@ -179,7 +192,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
try
{
- initialiseStorage(_vhostConfig, _virtualHost);
+ initialiseStorage(_vhostConfig, _model);
getMessageStore().addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL);
getMessageStore().addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL);
@@ -205,6 +218,16 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
setState(State.QUIESCED);
}
+ private void registerSystemNodes()
+ {
+ QpidServiceLoader<SystemNodeCreator> qpidServiceLoader = new QpidServiceLoader<SystemNodeCreator>();
+ Iterable<SystemNodeCreator> factories = qpidServiceLoader.instancesOf(SystemNodeCreator.class);
+ for(SystemNodeCreator creator : factories)
+ {
+ creator.register(_systemNodeRegistry);
+ }
+ }
+
abstract protected void initialiseStorage(VirtualHostConfiguration hostConfig,
org.apache.qpid.server.model.VirtualHost virtualHost) throws Exception;
@@ -494,6 +517,13 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
}
@Override
+ public MessageSource getMessageSource(final String name)
+ {
+ MessageSource systemSource = _systemNodeSources.get(name);
+ return systemSource == null ? getQueue(name) : systemSource;
+ }
+
+ @Override
public AMQQueue getQueue(UUID id)
{
return _queueRegistry.getQueue(id);
@@ -577,6 +607,14 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
}
+
+ @Override
+ public MessageDestination getMessageDestination(final String name)
+ {
+ MessageDestination destination = _systemNodeDestinations.get(name);
+ return destination == null ? getExchange(name) : destination;
+ }
+
@Override
public Exchange getExchange(String name)
{
@@ -690,7 +728,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
protected void passivate(String reason)
{
- _virtualHost.removeChangeListener(this);
+ _model.removeChangeListener(this);
removeHouseKeepingTasks();
//Stop Connections
@@ -907,7 +945,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
try
{
initialiseHouseKeeping(_vhostConfig.getHousekeepingCheckPeriod());
- _virtualHost.addChangeListener(this);
+ _model.addChangeListener(this);
finalState = State.ACTIVE;
}
finally
@@ -1059,4 +1097,44 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
}
}
+ private class SystemNodeRegistry implements SystemNodeCreator.SystemNodeRegistry
+ {
+ @Override
+ public void registerSystemNode(final MessageNode node)
+ {
+ if(node instanceof MessageDestination)
+ {
+ _systemNodeDestinations.put(node.getName(), (MessageDestination) node);
+ }
+ if(node instanceof MessageSource)
+ {
+ _systemNodeSources.put(node.getName(), (MessageSource)node);
+ }
+ }
+
+ @Override
+ public void removeSystemNode(final MessageNode node)
+ {
+ if(node instanceof MessageDestination)
+ {
+ _systemNodeDestinations.remove(node.getName());
+ }
+ if(node instanceof MessageSource)
+ {
+ _systemNodeSources.remove(node.getName());
+ }
+ }
+
+ @Override
+ public VirtualHost getVirtualHost()
+ {
+ return AbstractVirtualHost.this;
+ }
+
+ @Override
+ public org.apache.qpid.server.model.VirtualHost getVirtualHostModel()
+ {
+ return _model;
+ }
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
index 7949c40d9e..9edc227813 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
@@ -29,6 +29,9 @@ import org.apache.qpid.common.Closeable;
import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.connection.IConnectionRegistry;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageNode;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.plugin.ExchangeType;
import org.apache.qpid.server.protocol.LinkRegistry;
import org.apache.qpid.server.queue.AMQQueue;
@@ -48,6 +51,7 @@ public interface VirtualHost extends DurableConfigurationStore.Source, Closeable
String getName();
AMQQueue getQueue(String name);
+ MessageSource getMessageSource(String name);
AMQQueue getQueue(UUID id);
@@ -75,6 +79,8 @@ public interface VirtualHost extends DurableConfigurationStore.Source, Closeable
void removeExchange(Exchange exchange, boolean force) throws AMQException;
+ MessageDestination getMessageDestination(String name);
+
Exchange getExchange(String name);
Exchange getExchange(UUID id);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
index b7d3cf872b..6e36cdfa94 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
@@ -119,7 +119,7 @@ public class VirtualHostConfigRecoveryHandler implements
}
for(Transaction.Record record : enqueues)
{
- final AMQQueue queue = _virtualHost.getQueue(record.getQueue().getId());
+ final AMQQueue queue = _virtualHost.getQueue(record.getResource().getId());
if(queue != null)
{
final long messageId = record.getMessage().getMessageNumber();
@@ -141,7 +141,7 @@ public class VirtualHostConfigRecoveryHandler implements
try
{
- queue.enqueue(message, true, null);
+ queue.enqueue(message, null);
ref.release();
}
catch (AMQException e)
@@ -173,13 +173,13 @@ public class VirtualHostConfigRecoveryHandler implements
StringBuilder xidString = xidAsString(id);
CurrentActor.get().message(_logSubject,
TransactionLogMessages.XA_INCOMPLETE_QUEUE(xidString.toString(),
- record.getQueue().getId().toString()));
+ record.getResource().getId().toString()));
}
}
for(Transaction.Record record : dequeues)
{
- final AMQQueue queue = _virtualHost.getQueue(record.getQueue().getId());
+ final AMQQueue queue = _virtualHost.getQueue(record.getResource().getId());
if(queue != null)
{
final long messageId = record.getMessage().getMessageNumber();
@@ -223,7 +223,7 @@ public class VirtualHostConfigRecoveryHandler implements
StringBuilder xidString = xidAsString(id);
CurrentActor.get().message(_logSubject,
TransactionLogMessages.XA_INCOMPLETE_QUEUE(xidString.toString(),
- record.getQueue().getId().toString()));
+ record.getResource().getId().toString()));
}
}
@@ -292,7 +292,7 @@ public class VirtualHostConfigRecoveryHandler implements
count = 0;
}
- queue.enqueue(message);
+ queue.enqueue(message,null);
_queueRecoveries.put(queueName, ++count);
}
@@ -312,10 +312,22 @@ public class VirtualHostConfigRecoveryHandler implements
new TransactionLogResource()
{
@Override
+ public String getName()
+ {
+ return "<<UNKNOWN>>";
+ }
+
+ @Override
public UUID getId()
{
return queueId;
}
+
+ @Override
+ public boolean isDurable()
+ {
+ return false;
+ }
};
txn.dequeueMessage(mockQueue, new DummyMessage(messageId));
txn.commitTranAsync();
diff --git a/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType b/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType
new file mode 100644
index 0000000000..a744bfff53
--- /dev/null
+++ b/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+org.apache.qpid.server.message.internal.InternalMessageMetaDataType
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
index f60f173de9..4dd9831454 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
@@ -27,7 +27,7 @@ import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.queue.AMQPriorityQueue;
+import org.apache.qpid.server.queue.PriorityQueue;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.util.BrokerTestHelper;
@@ -113,17 +113,17 @@ public class VirtualHostConfigurationTest extends QpidTestCase
// Check that atest was a priority queue with 5 priorities
AMQQueue atest = vhost.getQueue("atest");
- assertTrue(atest instanceof AMQPriorityQueue);
- assertEquals(5, ((AMQPriorityQueue) atest).getPriorities());
+ assertTrue(atest instanceof PriorityQueue);
+ assertEquals(5, ((PriorityQueue) atest).getPriorities());
// Check that ptest was a priority queue with 10 priorities
AMQQueue ptest = vhost.getQueue("ptest");
- assertTrue(ptest instanceof AMQPriorityQueue);
- assertEquals(10, ((AMQPriorityQueue) ptest).getPriorities());
+ assertTrue(ptest instanceof PriorityQueue);
+ assertEquals(10, ((PriorityQueue) ptest).getPriorities());
// Check that ntest wasn't a priority queue
AMQQueue ntest = vhost.getQueue("ntest");
- assertFalse(ntest instanceof AMQPriorityQueue);
+ assertFalse(ntest instanceof PriorityQueue);
}
public void testQueueAlerts() throws Exception
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java
index 8d1b27e272..a9b99503ec 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java
@@ -19,20 +19,24 @@
*
*/
-package org.apache.qpid.server.subscription;
+package org.apache.qpid.server.consumer;
import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.filter.FilterManager;
+import org.apache.qpid.server.filter.Filterable;
+import org.apache.qpid.server.filter.MessageFilter;
+import org.apache.qpid.server.filter.SimpleFilterManager;
import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Transport;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.queue.QueueEntry.SubscriptionAcquiredState;
import org.apache.qpid.server.stats.StatisticsCounter;
+import org.apache.qpid.server.util.StateChangeListener;
import java.util.ArrayList;
import java.util.List;
@@ -41,83 +45,66 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-public class MockSubscription implements Subscription
+public class MockConsumer implements ConsumerTarget
{
+ private final List<String> _messageIds;
private boolean _closed = false;
private String tag = "mocktag";
private AMQQueue queue = null;
- private StateListener _listener = null;
- private volatile AMQQueue.Context _queueContext = null;
+ private StateChangeListener<ConsumerTarget, State> _listener = null;
private State _state = State.ACTIVE;
- private ArrayList<QueueEntry> messages = new ArrayList<QueueEntry>();
+ private ArrayList<MessageInstance> messages = new ArrayList<MessageInstance>();
private final Lock _stateChangeLock = new ReentrantLock();
- private List<QueueEntry> _acceptEntries = null;
- private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
-
- private static final AtomicLong idGenerator = new AtomicLong(0);
- // Create a simple ID that increments for ever new Subscription
- private final long _subscriptionID = idGenerator.getAndIncrement();
private boolean _isActive = true;
- public MockSubscription()
+ public MockConsumer()
{
+ _messageIds = null;
}
- public MockSubscription(List<QueueEntry> acceptEntries)
+ public MockConsumer(List<String> messageIds)
{
- _acceptEntries = acceptEntries;
+ _messageIds = messageIds;
}
- public void close()
+ public boolean close()
{
_closed = true;
if (_listener != null)
{
- _listener.stateChange(this, _state, State.CLOSED);
+ _listener.stateChanged(this, _state, State.CLOSED);
}
_state = State.CLOSED;
+ return true;
}
- public String getConsumerName()
+ public String getName()
{
return tag;
}
- public long getSubscriptionID()
- {
- return _subscriptionID;
- }
-
- public AMQQueue.Context getQueueContext()
- {
- return _queueContext;
- }
-
- public SubscriptionAcquiredState getOwningState()
- {
- return _owningState;
- }
-
- public LogActor getLogActor()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public boolean isTransient()
- {
- return false;
- }
-
- public long getBytesOut()
- {
- return 0; // TODO - Implement
- }
-
- public long getMessagesOut()
+ public FilterManager getFilters()
{
- return 0; // TODO - Implement
+ if(_messageIds != null)
+ {
+ SimpleFilterManager filters = new SimpleFilterManager();
+ filters.add(new MessageFilter()
+ {
+ @Override
+ public boolean matches(final Filterable message)
+ {
+ final String messageId = message.getMessageHeader().getMessageId();
+ return _messageIds.contains(messageId);
+ }
+ });
+ return filters;
+ }
+ else
+ {
+ return null;
+ }
}
public long getUnacknowledgedBytes()
@@ -140,90 +127,33 @@ public class MockSubscription implements Subscription
return new MockSessionModel();
}
- public boolean trySendLock()
- {
- return _stateChangeLock.tryLock();
- }
-
-
- public void getSendLock()
- {
- _stateChangeLock.lock();
- }
-
- public boolean hasInterest(QueueEntry entry)
- {
- if(_acceptEntries != null)
- {
- //simulate selector behaviour, only signal
- //interest in the dictated queue entries
- return _acceptEntries.contains(entry);
- }
-
- return true;
- }
-
public boolean isActive()
{
return _isActive ;
}
- public void set(String key, Object value)
- {
- }
-
- public Object get(String key)
- {
- return null;
- }
- public boolean isAutoClose()
- {
- return false;
- }
public boolean isClosed()
{
return _closed;
}
- public boolean acquires()
- {
- return true;
- }
-
- public boolean seesRequeues()
- {
- return true;
- }
public boolean isSuspended()
{
return false;
}
- public void queueDeleted(AMQQueue queue)
- {
- }
-
- public void releaseSendLock()
+ public void queueDeleted()
{
- _stateChangeLock.unlock();
}
- public void onDequeue(QueueEntry queueEntry)
+ public void restoreCredit(ServerMessage message)
{
}
- public void restoreCredit(QueueEntry queueEntry)
- {
- }
-
- public void releaseQueueEntry(QueueEntry queueEntry)
- {
- }
-
- public void send(QueueEntry entry, boolean batch) throws AMQException
+ public void send(MessageInstance entry, boolean batch) throws AMQException
{
if (messages.contains(entry))
{
@@ -237,47 +167,52 @@ public class MockSubscription implements Subscription
}
- public void setQueueContext(AMQQueue.Context queueContext)
+ public State getState()
{
- _queueContext = queueContext;
+ return _state;
}
- public void setQueue(AMQQueue queue, boolean exclusive)
+ @Override
+ public void consumerAdded(final Consumer sub)
{
- this.queue = queue;
}
- public void setNoLocal(boolean noLocal)
+ @Override
+ public void consumerRemoved(final Consumer sub)
{
- }
- public void setStateListener(StateListener listener)
- {
- this._listener = listener;
}
- public State getState()
+ public void setState(State state)
{
- return _state;
+ State oldState = _state;
+ _state = state;
+ if(_listener != null)
+ {
+ _listener.stateChanged(this, oldState, state);
+ }
}
- public boolean wouldSuspend(QueueEntry msg)
+ @Override
+ public void setStateListener(final StateChangeListener<ConsumerTarget, State> listener)
{
- return false;
+ _listener = listener;
}
- public ArrayList<QueueEntry> getMessages()
+ public ArrayList<MessageInstance> getMessages()
{
return messages;
}
- public boolean isSessionTransactional()
+
+ public void queueEmpty() throws AMQException
{
- return false;
}
- public void queueEmpty() throws AMQException
+ @Override
+ public boolean allocateCredit(final ServerMessage msg)
{
+ return true;
}
public void setActive(final boolean isActive)
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
index 764549626a..8cab2e9058 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
@@ -25,6 +25,7 @@ import junit.framework.Assert;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
@@ -73,7 +74,7 @@ public class TopicExchangeTest extends QpidTestCase
public void testNoRoute() throws AMQException
{
- AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*#b", false, null, false, false,
+ AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*#b", false, null, false, false,
false, null);
_exchange.registerQueue(new Binding(null, "a.*.#.b",queue, _exchange, null));
@@ -85,7 +86,7 @@ public class TopicExchangeTest extends QpidTestCase
public void testDirectMatch() throws AMQException
{
- AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "ab", false, null, false, false,
+ AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "ab", false, null, false, false,
false, null);
_exchange.registerQueue(new Binding(null, "a.b",queue, _exchange, null));
@@ -108,7 +109,7 @@ public class TopicExchangeTest extends QpidTestCase
public void testStarMatch() throws AMQException
{
- AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*", false, null, false, false, false, null);
+ AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*", false, null, false, false, false, null);
_exchange.registerQueue(new Binding(null, "a.*",queue, _exchange, null));
@@ -139,7 +140,7 @@ public class TopicExchangeTest extends QpidTestCase
public void testHashMatch() throws AMQException
{
- AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, false, null);
+ AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, false, null);
_exchange.registerQueue(new Binding(null, "a.#",queue, _exchange, null));
@@ -190,7 +191,7 @@ public class TopicExchangeTest extends QpidTestCase
public void testMidHash() throws AMQException
{
- AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false,
+ AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false,
false, null);
_exchange.registerQueue(new Binding(null, "a.*.#.b",queue, _exchange, null));
@@ -216,7 +217,7 @@ public class TopicExchangeTest extends QpidTestCase
public void testMatchAfterHash() throws AMQException
{
- AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false,
+ AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false,
false, null);
_exchange.registerQueue(new Binding(null, "a.*.#.b.c",queue, _exchange, null));
@@ -255,7 +256,7 @@ public class TopicExchangeTest extends QpidTestCase
public void testHashAfterHash() throws AMQException
{
- AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false,
+ AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false,
false, null);
_exchange.registerQueue(new Binding(null, "a.*.#.b.c.#.d",queue, _exchange, null));
@@ -277,7 +278,7 @@ public class TopicExchangeTest extends QpidTestCase
public void testHashHash() throws AMQException
{
- AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false,
+ AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false,
false, null);
_exchange.registerQueue(new Binding(null, "a.#.*.#.d",queue, _exchange, null));
@@ -321,7 +322,7 @@ public class TopicExchangeTest extends QpidTestCase
when(message.getMessageNumber()).thenReturn(messageNumber);
for(BaseQueue q : queues)
{
- q.enqueue(message);
+ q.enqueue(message, null);
}
return queues.size();
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java
deleted file mode 100644
index a0a2a7b648..0000000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java
+++ /dev/null
@@ -1,86 +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.server.logging.actors;
-
-import org.apache.qpid.server.subscription.MockSubscription;
-import org.apache.qpid.server.util.BrokerTestHelper;
-
-import java.util.List;
-
-/**
- * Test : AMQPConnectionActorTest
- * Validate the AMQPConnectionActor class.
- *
- * The test creates a new AMQPActor and then logs a message using it.
- *
- * The test then verifies that the logged message was the only one created and
- * that the message contains the required message.
- */
-public class SubscriptionActorTest extends BaseConnectionActorTestCase
-{
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- MockSubscription mockSubscription = new MockSubscription();
-
- mockSubscription.setQueue(BrokerTestHelper.createQueue(getName(), getVirtualHost()), false);
-
- setAmqpActor(new SubscriptionActor(getRootLogger(), mockSubscription));
- }
-
- /**
- * Test the AMQPActor logging as a Subscription logger.
- *
- * The test sends a message then verifies that it entered the logs.
- *
- * The log message should be fully replaced (no '{n}' values) and should
- * contain subscription identification.
- */
- public void testSubscription()
- {
- final String message = sendTestLogMessage(getAmqpActor());
-
- List<Object> logs = getRawLogger().getLogMessages();
-
- assertEquals("Message log size not as expected.", 1, logs.size());
-
- // Verify that the logged message is present in the output
- assertTrue("Message was not found in log message",
- logs.get(0).toString().contains(message));
-
- // Verify that all the values were presented to the MessageFormatter
- // so we will not end up with '{n}' entries in the log.
- assertFalse("Verify that the string does not contain any '{'.",
- logs.get(0).toString().contains("{"));
-
- // Verify that the message has the correct type
- assertTrue("Message contains the [sub: prefix",
- logs.get(0).toString().contains("[sub:"));
-
- // Verify that the logged message does not contains the 'ch:' marker
- assertFalse("Message was logged with a channel identifier." + logs.get(0),
- logs.get(0).toString().contains("/ch:"));
- }
-
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/ConsumerMessagesTest.java
index b2bc351f8f..52a53e8d38 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/ConsumerMessagesTest.java
@@ -25,7 +25,7 @@ import java.util.List;
/**
* Test SUB Log Messages
*/
-public class SubscriptionMessagesTest extends AbstractTestMessages
+public class ConsumerMessagesTest extends AbstractTestMessages
{
public void testSubscriptionCreateALL()
{
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/VirtualHostMessagesTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/VirtualHostMessagesTest.java
index 17d68ef7c3..c1068b4a0b 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/VirtualHostMessagesTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/messages/VirtualHostMessagesTest.java
@@ -38,7 +38,7 @@ public class VirtualHostMessagesTest extends AbstractTestMessages
validateLogMessage(log, "VHT-1001", expected);
}
- public void testSubscriptionClosed()
+ public void testVirtualhostClosed()
{
_logMessage = VirtualHostMessages.CLOSED();
List<Object> log = performLog();
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java
deleted file mode 100644
index 3afba28cd6..0000000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java
+++ /dev/null
@@ -1,105 +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.server.logging.subjects;
-
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.MockAMQQueue;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.util.BrokerTestHelper;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-/**
- * Validate SubscriptionLogSubjects are logged as expected
- */
-public class SubscriptionLogSubjectTest extends AbstractTestLogSubject
-{
-
- private static final long SUBSCRIPTION_ID = 1;
- private AMQQueue _queue;
- private VirtualHost _testVhost;
- private Subscription _subscription;
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- _testVhost = BrokerTestHelper.createVirtualHost("test");
-
- _queue = new MockAMQQueue("SubscriptionLogSubjectTest");
- ((MockAMQQueue) _queue).setVirtualHost(_testVhost);
-
- _subscription = mock(Subscription.class);
- when(_subscription.getQueue()).thenReturn(_queue);
- when(_subscription.getSubscriptionID()).thenReturn(SUBSCRIPTION_ID);
-
- _subject = new SubscriptionLogSubject(_subscription);
- }
-
- @Override
- public void tearDown() throws Exception
- {
- if (_testVhost != null)
- {
- _testVhost.close();
- }
- super.tearDown();
- }
-
- /**
- * Validate that the logged Subject message is as expected:
- * MESSAGE [Blank][sub:0(vh(/test)/qu(SubscriptionLogSubjectTest))] <Log Message>
- *
- * @param message the message whose format needs validation
- */
- @Override
- protected void validateLogStatement(String message)
- {
- String subscriptionSlice = getSlice("sub:"
- + _subscription.getSubscriptionID(),
- message);
-
- assertNotNull("Unable to locate subscription 'sub:" +
- _subscription.getSubscriptionID() + "'");
-
-
-
- // Pull out the qu(..) section from the subscription message
- // Split it into three parts
- // MESSAGE [Blank][sub:0(vh(/
- // test)/
- // qu(SubscriptionLogSubjectTest))]
- // Take the last bit and drop off the extra )]
- String[] parts = message.split("/");
- assertEquals("Message part count wrong", 3, parts.length);
- String subscription = parts[2].substring(0, parts[2].indexOf(")") + 1);
-
- // Adding the ')' is a bit ugly but SubscriptionLogSubject is the only
- // Subject that nests () and so the simple parser of checking for the
- // next ')' falls down.
- verifyVirtualHost(subscriptionSlice+ ")", _queue.getVirtualHost());
-
- verifyQueue(subscription, _queue);
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
index bcf54c97a4..febce9ea2e 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
@@ -231,7 +231,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
false,
attributes);
- assertEquals("Queue not a priority queue", AMQPriorityQueue.class, queue.getClass());
+ assertEquals("Queue not a priority queue", PriorityQueue.class, queue.getClass());
verifyQueueRegistered("testPriorityQueue");
verifyRegisteredQueueCount(1);
}
@@ -246,7 +246,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
false,
false,
null);
- assertEquals("Queue not a simple queue", SimpleAMQQueue.class, queue.getClass());
+ assertEquals("Queue not a simple queue", StandardQueue.class, queue.getClass());
verifyQueueRegistered(queueName);
//verify that no alternate exchange or DLQ were produced
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java
index d67c70c831..c2291f5eed 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java
@@ -28,6 +28,9 @@ import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.Collections;
+import java.util.UUID;
+
public class ConflationQueueListTest extends TestCase
{
private static final String CONFLATION_KEY = "CONFLATION_KEY";
@@ -37,13 +40,15 @@ public class ConflationQueueListTest extends TestCase
private static final String TEST_KEY_VALUE2 = "testKeyValue2";
private ConflationQueueList _list;
- private AMQQueue _queue = createTestQueue();
+ private ConflationQueue _queue;
@Override
protected void setUp() throws Exception
{
super.setUp();
- _list = new ConflationQueueList(_queue, CONFLATION_KEY);
+ _queue = new ConflationQueue(UUID.randomUUID(), getName(), false, null, false, false, mock(VirtualHost.class),
+ Collections.<String,Object>emptyMap(),CONFLATION_KEY);
+ _list = _queue.getEntries();
}
public void testListHasNoEntries()
@@ -175,7 +180,8 @@ public class ConflationQueueListTest extends TestCase
private int countEntries(ConflationQueueList list)
{
- QueueEntryIterator<SimpleQueueEntryImpl> iterator = list.iterator();
+ QueueEntryIterator<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList,QueueConsumer<?,ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList>> iterator =
+ list.iterator();
int count = 0;
while(iterator.advance())
{
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConsumerListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConsumerListTest.java
new file mode 100644
index 0000000000..35508bb2c4
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConsumerListTest.java
@@ -0,0 +1,445 @@
+/*
+ *
+ * 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.queue;
+
+
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ConsumerListTest extends QpidTestCase
+{
+ private QueueConsumerList _subList;
+ private QueueConsumer _sub1;
+ private QueueConsumer _sub2;
+ private QueueConsumer _sub3;
+ private QueueConsumerList.ConsumerNode _node;
+
+ protected void setUp()
+ {
+ _subList = new QueueConsumerList();
+
+ _sub1 = newMockConsumer();
+ _sub2 = newMockConsumer();
+ _sub3 = newMockConsumer();
+
+ _subList.add(_sub1);
+ _subList.add(_sub2);
+ _subList.add(_sub3);
+
+ _node = _subList.getHead();
+ }
+
+
+ private QueueConsumer newMockConsumer()
+ {
+ ConsumerTarget target = mock(ConsumerTarget.class);
+ when(target.getSessionModel()).thenReturn(mock(AMQSessionModel.class));
+ return new QueueConsumer(null,null,true,true,"sub",false,target);
+ }
+
+ /**
+ * Test that if the first (non-head) node in the list is deleted (but is still present),
+ * it is not returned when searching through the list for the next viable node, and the
+ * subsequent viable node is returned instead.
+ */
+ public void testFindNextSkipsFirstDeletedNode()
+ {
+ assertTrue("Deleting consumer node should have succeeded",
+ getNodeForConsumer(_subList, _sub1).delete());
+
+ assertNotNull("Returned node should not be null", _node = _node.findNext());
+ assertEquals("Should have returned node for 2nd consumer", _sub2, _node.getConsumer());
+
+ assertNotNull("Returned node should not be null", _node = _node.findNext());
+ assertEquals("Should have returned node for 3rd consumer", _sub3, _node.getConsumer());
+ }
+
+ /**
+ * Test that if a central node in the list is deleted (but is still present),
+ * it is not returned when searching through the list for the next viable node,
+ * and the subsequent viable node is returned instead.
+ */
+ public void testFindNextSkipsCentralDeletedNode()
+ {
+ assertNotNull("Returned node should not be null", _node = _node.findNext());
+
+ assertTrue("Deleting consumer node should have succeeded",
+ getNodeForConsumer(_subList, _sub2).delete());
+
+ assertNotNull("Returned node should not be null", _node = _node.findNext());
+ assertEquals("Should have returned node for 3rd consumer", _sub3, _node.getConsumer());
+ }
+
+ /**
+ * Test that if the last node in the list is deleted (but is still present),
+ * it is not returned when searching through the list for the next viable node,
+ * and null is returned instead.
+ */
+ public void testFindNextSkipsLastDeletedNode()
+ {
+ assertNotNull("Returned node should not be null", _node = _node.findNext());
+ assertEquals("Should have returned node for 1st consumer", _sub1, _node.getConsumer());
+
+ assertNotNull("Returned node should not be null", _node = _node.findNext());
+ assertEquals("Should have returned node for 2nd consumer", _sub2, _node.getConsumer());
+
+ assertTrue("Deleting consumer node should have succeeded",
+ getNodeForConsumer(_subList, _sub3).delete());
+
+ assertNull("Returned node should be null", _node = _node.findNext());
+ }
+
+ /**
+ * Test that if multiple nodes in the list are deleted (but still present), they
+ * are not returned when searching through the list for the next viable node,
+ * and the subsequent viable node is returned instead.
+ */
+ public void testFindNextSkipsMultipleDeletedNode()
+ {
+ assertTrue("Deleting consumer node should have succeeded",
+ getNodeForConsumer(_subList, _sub1).delete());
+ assertTrue("Deleting consumer node should have succeeded",
+ getNodeForConsumer(_subList, _sub2).delete());
+
+ assertNotNull("Returned node should not be null", _node = _node.findNext());
+ assertEquals("Should have returned node for 3rd consumer", _sub3, _node.getConsumer());
+ }
+
+ /**
+ * Test that if a node in the list is marked 'deleted' it is still present in the list
+ * until actually removed. counter-test to verify above testing of getNext() method.
+ */
+ public void testDeletedNodeStillPresent()
+ {
+ assertTrue("Deleting consumer node should have succeeded",
+ getNodeForConsumer(_subList, _sub1).delete());
+
+ assertNotNull("Node marked deleted should still be present", getNodeForConsumer(_subList, _sub1));
+ assertEquals("All 3 nodes are still expected to be present", 3, countNodes(_subList));
+ }
+
+ /**
+ * Traverses the list nodes in a non-mutating fashion, returning the first node which matches the given
+ * Consumer, or null if none is found.
+ */
+ private QueueConsumerList.ConsumerNode getNodeForConsumer(final QueueConsumerList list, final Consumer sub)
+ {
+ QueueConsumerList.ConsumerNode node = list.getHead();
+ while (node != null && node.getConsumer() != sub)
+ {
+ node = node.nextNode();
+ }
+
+ return node;
+ }
+
+ /**
+ * Counts the number of (non-head) nodes in the list.
+ */
+ private int countNodes(final QueueConsumerList list)
+ {
+ QueueConsumerList.ConsumerNode node = list.getHead();
+ int count;
+ for(count = -1; node != null; count++)
+ {
+ node = node.nextNode();
+ }
+
+ return count;
+ }
+
+ /**
+ * Tests that the head is returned as expected, and isn't the node for the first consumer.
+ */
+ public void testGetHead()
+ {
+ assertNotNull("List head should be non null", _node);
+ assertNotSame("Head should not be node for first consumer",
+ _node, getNodeForConsumer(_subList, _sub1));
+ }
+
+ /**
+ * Tests that the size is returned correctly in the face of additions and removals.
+ */
+ public void testGetSize()
+ {
+ QueueConsumerList subList = new QueueConsumerList();
+
+ assertEquals("Unexpected size result", 0, subList.size());
+
+ QueueConsumer sub1 = newMockConsumer();
+ QueueConsumer sub2 = newMockConsumer();
+ QueueConsumer sub3 = newMockConsumer();
+
+ subList.add(sub1);
+ assertEquals("Unexpected size result", 1, subList.size());
+
+ subList.add(sub2);
+ assertEquals("Unexpected size result", 2, subList.size());
+
+ subList.add(sub3);
+ assertEquals("Unexpected size result", 3, subList.size());
+
+ assertTrue("Removing consumer from list should have succeeded", subList.remove(sub1));
+ assertEquals("Unexpected size result", 2, subList.size());
+
+ assertTrue("Removing consumer from list should have succeeded", subList.remove(sub2));
+ assertEquals("Unexpected size result", 1, subList.size());
+
+ assertTrue("Removing consumer from list should have succeeded", subList.remove(sub3));
+ assertEquals("Unexpected size result", 0, subList.size());
+ }
+
+ /**
+ * Test that if the first (non-head) node in the list is removed it is no longer
+ * present in the node structure of the list at all.
+ */
+ public void testRemoveFirstNode()
+ {
+ assertNotNull("Should have been a node present for the consumer", getNodeForConsumer(_subList, _sub1));
+ assertTrue("Removing consumer node should have succeeded", _subList.remove(_sub1));
+ assertNull("Should not have been a node present for the removed consumer",
+ getNodeForConsumer(_subList, _sub1));
+ assertEquals("Unexpected number of nodes", 2, countNodes(_subList));
+ assertNotNull("Should have been a node present for the consumer", getNodeForConsumer(_subList, _sub2));
+ assertNotNull("Should have been a node present for the consumer", getNodeForConsumer(_subList, _sub3));
+ }
+
+ /**
+ * Test that if a central node in the list is removed it is no longer
+ * present in the node structure of the list at all.
+ */
+ public void testRemoveCentralNode()
+ {
+ assertNotNull("Should have been a node present for the consumer", getNodeForConsumer(_subList, _sub2));
+ assertTrue("Removing consumer node should have succeeded", _subList.remove(_sub2));
+ assertNull("Should not have been a node present for the removed consumer",
+ getNodeForConsumer(_subList, _sub2));
+ assertEquals("Unexpected number of nodes", 2, countNodes(_subList));
+ assertNotNull("Should have been a node present for the consumer", getNodeForConsumer(_subList, _sub1));
+ assertNotNull("Should have been a node present for the consumer", getNodeForConsumer(_subList, _sub3));
+ }
+
+ /**
+ * Test that if the consumer contained in the last node of the list is removed
+ * it is no longer present in the node structure of the list at all. However,
+ * as the last node in the structure can't actually be removed a dummy will instead
+ * be present.
+ */
+ public void testRemoveLastNode()
+ {
+ assertNotNull("Should have been a node present for the consumer", getNodeForConsumer(_subList, _sub3));
+ assertTrue("Removing consumer node should have succeeded", _subList.remove(_sub3));
+ assertNull("Should not have been a node present for the removed consumer",
+ getNodeForConsumer(_subList, _sub3));
+
+ //We actually expect 3 nodes to remain this time, because the last node cant be removed for thread safety reasons,
+ //however a dummy final node can be used as substitute to allow removal of the consumer node.
+ assertEquals("Unexpected number of nodes", 2 + 1, countNodes(_subList));
+ assertNotNull("Should have been a node present for the consumer", getNodeForConsumer(_subList, _sub1));
+ assertNotNull("Should have been a node present for the consumer", getNodeForConsumer(_subList, _sub2));
+ }
+
+ /**
+ * Test that if the consumer not contained in the list is requested to be removed
+ * that the removal fails
+ */
+ public void testRemoveNonexistentNode()
+ {
+ QueueConsumer sub4 = newMockConsumer();
+ assertNull("Should not have been a node present for the consumer", getNodeForConsumer(_subList, sub4));
+ assertFalse("Removing consumer node should not have succeeded", _subList.remove(sub4));
+ assertEquals("Unexpected number of nodes", 3, countNodes(_subList));
+ }
+
+ /**
+ * Test that if a consumer node which occurs later in the main list than the marked node is
+ * removed from the list after the marked node is also removed, then the marker node doesn't
+ * serve to retain the subsequent nodes in the list structure (and thus memory) despite their
+ * removal.
+ */
+ public void testDeletedMarkedNodeDoesntLeakSubsequentlyDeletedNodes()
+ {
+ //get the nodes out the list for the 1st and 3rd consumers
+ QueueConsumerList.ConsumerNode sub1Node = getNodeForConsumer(_subList, _sub1);
+ assertNotNull("Should have been a node present for the consumer", sub1Node);
+ QueueConsumerList.ConsumerNode sub3Node = getNodeForConsumer(_subList, _sub3);
+ assertNotNull("Should have been a node present for the consumer", sub3Node);
+
+ //mark the first consumer node
+ assertTrue("should have succeeded in updating the marked node",
+ _subList.updateMarkedNode(_subList.getMarkedNode(), sub1Node));
+
+ //remove the 1st consumer from the list
+ assertTrue("Removing consumer node should have succeeded", _subList.remove(_sub1));
+ //verify the 1st consumer is no longer the marker node (replaced by a dummy), or in the main list structure
+ assertNotSame("Unexpected marker node", sub1Node, _subList.getMarkedNode());
+ assertNull("Should not have been a node present in the list structure for the marked-but-removed sub1 node",
+ getNodeForConsumer(_subList, _sub1));
+
+ //remove the 2nd consumer from the list
+ assertTrue("Removing consumer node should have succeeded", _subList.remove(_sub2));
+
+ //verify the marker node isn't leaking subsequently removed nodes, by ensuring the very next node
+ //in its list structure is now the 3rd consumer (since the 2nd was removed too)
+ assertEquals("Unexpected next node", sub3Node, _subList.getMarkedNode().nextNode());
+
+ //remove the 3rd and final/tail consumer
+ assertTrue("Removing consumer node should have succeeded", _subList.remove(_sub3));
+
+ //verify the marker node isn't leaking subsequently removed nodes, by ensuring the very next node
+ //in its list structure is now the dummy tail (since the 3rd consumer was removed, and a dummy
+ //tail was inserted) and NOT the 3rd sub node.
+ assertNotSame("Unexpected next node", sub3Node, _subList.getMarkedNode().nextNode());
+ assertTrue("Unexpected next node", _subList.getMarkedNode().nextNode().isDeleted());
+ assertNull("Next non-deleted node from the marker should now be the list end, i.e. null", _subList.getMarkedNode().findNext());
+ }
+
+ /**
+ * Test that the marked node 'findNext' behaviour is as expected after a consumer is added
+ * to the list following the tail consumer node being removed while it is the marked node.
+ * That is, that the new consumers node is returned by getMarkedNode().findNext().
+ */
+ public void testMarkedNodeFindsNewConsumerAfterRemovingTailWhilstMarked()
+ {
+ //get the node out the list for the 3rd consumer
+ QueueConsumerList.ConsumerNode sub3Node = getNodeForConsumer(_subList, _sub3);
+ assertNotNull("Should have been a node present for the consumer", sub3Node);
+
+ //mark the 3rd consumer node
+ assertTrue("should have succeeded in updating the marked node",
+ _subList.updateMarkedNode(_subList.getMarkedNode(), sub3Node));
+
+ //verify calling findNext on the marked node returns null, i.e. the end of the list has been reached
+ assertEquals("Unexpected node after marked node", null, _subList.getMarkedNode().findNext());
+
+ //remove the 3rd(marked) consumer from the list
+ assertTrue("Removing consumer node should have succeeded", _subList.remove(_sub3));
+
+ //add a new 4th consumer to the list
+ QueueConsumer sub4 = newMockConsumer();
+ _subList.add(sub4);
+
+ //get the node out the list for the 4th consumer
+ QueueConsumerList.ConsumerNode sub4Node = getNodeForConsumer(_subList, sub4);
+ assertNotNull("Should have been a node present for the consumer", sub4Node);
+
+ //verify the marked node (which is now a dummy substitute for the 3rd consumer) returns
+ //the 4th consumers node as the next non-deleted node.
+ assertEquals("Unexpected next node", sub4Node, _subList.getMarkedNode().findNext());
+ }
+
+ /**
+ * Test that setting the marked node to null doesn't cause problems during remove operations
+ */
+ public void testRemoveWithNullMarkedNode()
+ {
+ //set the marker to null
+ assertTrue("should have succeeded in updating the marked node",
+ _subList.updateMarkedNode(_subList.getMarkedNode(), null));
+
+ //remove the 1st consumer from the main list
+ assertTrue("Removing consumer node should have succeeded", _subList.remove(_sub1));
+
+ //verify the 1st consumer is no longer in the main list structure
+ assertNull("Should not have been a node present in the main list structure for sub1",
+ getNodeForConsumer(_subList, _sub1));
+ assertEquals("Unexpected number of nodes", 2, countNodes(_subList));
+ }
+
+ /**
+ * Tests that after the first (non-head) node of the list is marked deleted but has not
+ * yet been removed, the iterator still skips it.
+ */
+ public void testIteratorSkipsFirstDeletedNode()
+ {
+ //'delete' but don't remove the node for the 1st consumer
+ assertTrue("Deleting consumer node should have succeeded",
+ getNodeForConsumer(_subList, _sub1).delete());
+ assertNotNull("Should still have been a node present for the deleted consumer",
+ getNodeForConsumer(_subList, _sub1));
+
+ QueueConsumerList.ConsumerNodeIterator iter = _subList.iterator();
+
+ //verify the iterator returns the 2nd consumers node
+ assertTrue("Iterator should have been able to advance", iter.advance());
+ assertEquals("Iterator returned unexpected ConsumerNode", _sub2, iter.getNode().getConsumer());
+
+ //verify the iterator returns the 3rd consumers node and not the 2nd.
+ assertTrue("Iterator should have been able to advance", iter.advance());
+ assertEquals("Iterator returned unexpected ConsumerNode", _sub3, iter.getNode().getConsumer());
+ }
+
+ /**
+ * Tests that after a central node of the list is marked deleted but has not yet been removed,
+ * the iterator still skips it.
+ */
+ public void testIteratorSkipsCentralDeletedNode()
+ {
+ //'delete' but don't remove the node for the 2nd consumer
+ assertTrue("Deleting consumer node should have succeeded",
+ getNodeForConsumer(_subList, _sub2).delete());
+ assertNotNull("Should still have been a node present for the deleted consumer",
+ getNodeForConsumer(_subList, _sub2));
+
+ QueueConsumerList.ConsumerNodeIterator iter = _subList.iterator();
+
+ //verify the iterator returns the 1st consumers node
+ assertTrue("Iterator should have been able to advance", iter.advance());
+ assertEquals("Iterator returned unexpected ConsumerNode", _sub1, iter.getNode().getConsumer());
+
+ //verify the iterator returns the 3rd consumers node and not the 2nd.
+ assertTrue("Iterator should have been able to advance", iter.advance());
+ assertEquals("Iterator returned unexpected ConsumerNode", _sub3, iter.getNode().getConsumer());
+ }
+
+ /**
+ * Tests that after the last node of the list is marked deleted but has not yet been removed,
+ * the iterator still skips it.
+ */
+ public void testIteratorSkipsDeletedFinalNode()
+ {
+ //'delete' but don't remove the node for the 3rd consumer
+ assertTrue("Deleting consumer node should have succeeded",
+ getNodeForConsumer(_subList, _sub3).delete());
+ assertNotNull("Should still have been a node present for the deleted 3rd consumer",
+ getNodeForConsumer(_subList, _sub3));
+
+ QueueConsumerList.ConsumerNodeIterator iter = _subList.iterator();
+
+ //verify the iterator returns the 1st consumers node
+ assertTrue("Iterator should have been able to advance", iter.advance());
+ assertEquals("Iterator returned unexpected ConsumerNode", _sub1, iter.getNode().getConsumer());
+
+ //verify the iterator returns the 2nd consumers node
+ assertTrue("Iterator should have been able to advance", iter.advance());
+ assertEquals("Iterator returned unexpected ConsumerNode", _sub2, iter.getNode().getConsumer());
+
+ //verify the iterator can no longer advance and does not return a consumer node
+ assertFalse("Iterator should not have been able to advance", iter.advance());
+ assertEquals("Iterator returned unexpected ConsumerNode", null, iter.getNode());
+ }
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
index ea2e29d40d..d1bc5effc0 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
@@ -24,15 +24,23 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.server.binding.Binding;
import org.apache.qpid.server.configuration.QueueConfiguration;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstance;
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.consumer.Consumer;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.store.StorableMessageMetaData;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collection;
import java.util.Collections;
+import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@@ -171,6 +179,8 @@ public class MockAMQQueue implements AMQQueue
return null;
}
+
+
public boolean isDurable()
{
return false;
@@ -202,32 +212,67 @@ public class MockAMQQueue implements AMQQueue
return _virtualhost;
}
- public String getName()
+ @Override
+ public boolean resend(final QueueEntry entry, final Consumer consumer) throws AMQException
{
- return _name;
+ return false;
+ }
+
+ @Override
+ public void addQueueDeleteTask(final Action task)
+ {
+
+ }
+
+ @Override
+ public void enqueue(final ServerMessage message, final Action action) throws AMQException
+ {
+
}
- public void registerSubscription(Subscription subscription, boolean exclusive) throws AMQException
+ @Override
+ public int compareTo(final Object o)
{
+ return 0;
+ }
+ @Override
+ public Consumer addConsumer(final ConsumerTarget target,
+ final FilterManager filters,
+ final Class messageClass,
+ final String consumerName,
+ final EnumSet options) throws AMQException
+ {
+ return new QueueConsumer(filters, messageClass, options.contains(Consumer.Option.ACQUIRES),
+ options.contains(Consumer.Option.SEES_REQUEUES), consumerName,
+ options.contains(Consumer.Option.TRANSIENT), target );
}
- public void unregisterSubscription(Subscription subscription) throws AMQException
+
+ public String getName()
{
+ return _name;
+ }
+ public int send(final ServerMessage message,
+ final InstanceProperties instanceProperties,
+ final ServerTransaction txn,
+ final Action postEnqueueAction)
+ {
+ return 0;
}
- public Collection<Subscription> getConsumers()
+ public Collection<QueueConsumer> getConsumers()
{
return Collections.emptyList();
}
- public void addSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ public void addConsumerRegistrationListener(final ConsumerRegistrationListener listener)
{
}
- public void removeSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ public void removeConsumerRegistrationListener(final ConsumerRegistrationListener listener)
{
}
@@ -242,7 +287,7 @@ public class MockAMQQueue implements AMQQueue
return 0;
}
- public boolean hasExclusiveSubscriber()
+ public boolean hasExclusiveConsumer()
{
return false;
}
@@ -293,50 +338,39 @@ public class MockAMQQueue implements AMQQueue
return getMessageCount();
}
- public void enqueue(ServerMessage message) throws AMQException
- {
- }
-
- public void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException
- {
- }
-
-
- public void enqueue(ServerMessage message, boolean sync, PostEnqueueAction action) throws AMQException
- {
- }
public void requeue(QueueEntry entry)
{
}
- public void requeue(QueueEntryImpl storeContext, Subscription subscription)
+ public void dequeue(QueueEntry entry)
{
}
- public void dequeue(QueueEntry entry, Subscription sub)
- {
- }
-
- public boolean resend(QueueEntry entry, Subscription subscription) throws AMQException
+ public boolean resend(QueueEntry entry, QueueConsumer consumer) throws AMQException
{
return false;
}
- public void addQueueDeleteTask(Task task)
+ @Override
+ public void removeQueueDeleteTask(final Action task)
{
+
}
- public void removeQueueDeleteTask(final Task task)
+ @Override
+ public void decrementUnackedMsgCount(final QueueEntry queueEntry)
{
+
}
- public List<QueueEntry> getMessagesOnTheQueue()
+ @Override
+ public List getMessagesOnTheQueue()
{
return null;
}
- public List<QueueEntry> getMessagesOnTheQueue(long fromMessageId, long toMessageId)
+ public List getMessagesOnTheQueue(long fromMessageId, long toMessageId)
{
return null;
}
@@ -356,7 +390,7 @@ public class MockAMQQueue implements AMQQueue
return null;
}
- public List<QueueEntry> getMessagesRangeOnTheQueue(long fromPosition, long toPosition)
+ public List getMessagesRangeOnTheQueue(long fromPosition, long toPosition)
{
return null;
}
@@ -427,12 +461,12 @@ public class MockAMQQueue implements AMQQueue
return null;
}
- public void flushSubscription(Subscription sub) throws AMQException
+ public void flushConsumer(Consumer sub) throws AMQException
{
}
- public void deliverAsync(Subscription sub)
+ public void deliverAsync(Consumer sub)
{
}
@@ -563,10 +597,6 @@ public class MockAMQQueue implements AMQQueue
return 0;
}
- public void decrementUnackedMsgCount(QueueEntry queueEntry)
- {
-
- }
public long getUnackedMessageCount()
{
@@ -610,4 +640,5 @@ public class MockAMQQueue implements AMQQueue
{
return null;
}
+
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockMessageInstance.java
index d3c866f747..386bb46044 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockMessageInstance.java
@@ -24,11 +24,15 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.server.filter.Filterable;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.util.StateChangeListener;
-public class MockQueueEntry implements QueueEntry
+public class MockMessageInstance implements MessageInstance<MockMessageInstance,Consumer>
{
private ServerMessage _message;
@@ -38,24 +42,28 @@ public class MockQueueEntry implements QueueEntry
return false;
}
- public boolean acquire(Subscription sub)
+ @Override
+ public int getMaximumDeliveryCount()
{
- return false;
+ return 0;
}
- public boolean acquiredBySubscription()
+ @Override
+ public int routeToAlternate(final Action<? super MessageInstance<?, ? extends Consumer>> action,
+ final ServerTransaction txn)
{
- return false;
+ return 0;
}
- public boolean isAcquiredBy(Subscription subscription)
+ public boolean acquiredByConsumer()
{
return false;
}
- public void addStateChangeListener(StateChangeListener listener)
+ @Override
+ public boolean isAcquiredBy(final Consumer consumer)
{
-
+ return false;
}
public void delete()
@@ -63,12 +71,13 @@ public class MockQueueEntry implements QueueEntry
}
- public int routeToAlternate(final BaseQueue.PostEnqueueAction action, final ServerTransaction txn)
+ public boolean expired() throws AMQException
{
- return 0;
+ return false;
}
- public boolean expired() throws AMQException
+ @Override
+ public boolean acquire(final Consumer sub)
{
return false;
}
@@ -78,7 +87,7 @@ public class MockQueueEntry implements QueueEntry
return false;
}
- public Subscription getDeliveredSubscription()
+ public Consumer getDeliveredConsumer()
{
return null;
}
@@ -93,11 +102,6 @@ public class MockQueueEntry implements QueueEntry
return _message;
}
- public AMQQueue getQueue()
- {
- return null;
- }
-
public long getSize()
{
return 0;
@@ -108,55 +112,40 @@ public class MockQueueEntry implements QueueEntry
return false;
}
-
- public boolean isQueueDeleted()
+ public void reject()
{
-
- return false;
}
-
- public boolean isRejectedBy(long subscriptionId)
+ @Override
+ public boolean isRejectedBy(final Consumer consumer)
{
-
return false;
}
- public void reject()
- {
-
-
- }
-
-
public void release()
{
-
-
}
-
- public boolean removeStateChangeListener(StateChangeListener listener)
+ @Override
+ public boolean resend() throws AMQException
{
-
return false;
}
+
public void setRedelivered()
{
-
-
}
public AMQMessageHeader getMessageHeader()
{
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ return null;
}
public boolean isPersistent()
{
- return false; //To change body of implemented methods use File | Settings | File Templates.
+ return false;
}
public boolean isRedelivered()
@@ -164,12 +153,6 @@ public class MockQueueEntry implements QueueEntry
return false;
}
- public int compareTo(QueueEntry o)
- {
-
- return 0;
- }
-
public void setMessage(ServerMessage msg)
{
_message = msg;
@@ -179,31 +162,32 @@ public class MockQueueEntry implements QueueEntry
{
return false;
}
-
- public QueueEntry getNextNode()
+ @Override
+ public int getDeliveryCount()
{
- return null;
+ return 0;
}
- public QueueEntry getNextValidEntry()
+ @Override
+ public void incrementDeliveryCount()
{
- return null;
}
@Override
- public int getDeliveryCount()
+ public void decrementDeliveryCount()
{
- return 0;
}
@Override
- public void incrementDeliveryCount()
+ public void addStateChangeListener(final StateChangeListener<? super MockMessageInstance, State> listener)
{
+
}
@Override
- public void decrementDeliveryCount()
+ public boolean removeStateChangeListener(final StateChangeListener<? super MockMessageInstance, State> listener)
{
+ return false;
}
@Override
@@ -217,4 +201,10 @@ public class MockQueueEntry implements QueueEntry
{
return InstanceProperties.EMPTY;
}
+
+ @Override
+ public TransactionLogResource getOwningResource()
+ {
+ return null;
+ }
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java
index e8c0470915..3db5d0fb62 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java
@@ -26,12 +26,16 @@ import static org.mockito.Mockito.when;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
+import java.util.Collections;
+import java.util.UUID;
+
public class PriorityQueueListTest extends QpidTestCase
{
private static final byte[] PRIORITIES = {4, 5, 5, 4};
- PriorityQueueList _list = new PriorityQueueList(null, 10);
+ PriorityQueueList _list;
private QueueEntry _priority4message1;
private QueueEntry _priority4message2;
@@ -42,6 +46,17 @@ public class PriorityQueueListTest extends QpidTestCase
{
QueueEntry[] entries = new QueueEntry[PRIORITIES.length];
+ PriorityQueue queue = new PriorityQueue(UUID.randomUUID(),
+ getName(),
+ false,
+ null,
+ false,
+ false,
+ mock(VirtualHost.class),
+ Collections.<String,Object>emptyMap(),
+ 10);
+ _list = queue.getEntries();
+
for (int i = 0; i < PRIORITIES.length; i++)
{
ServerMessage<?> message = mock(ServerMessage.class);
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueTest.java
index a468fa072b..56cd29b0bd 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueTest.java
@@ -24,15 +24,22 @@ import java.util.Collections;
import junit.framework.AssertionFailedError;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
import java.util.ArrayList;
+import java.util.EnumSet;
+
import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.consumer.Consumer;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class AMQPriorityQueueTest extends SimpleAMQQueueTest
+public class PriorityQueueTest extends SimpleAMQQueueTestBase
{
@Override
@@ -47,25 +54,25 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest
// Enqueue messages in order
SimpleAMQQueue queue = getQueue();
- queue.enqueue(createMessage(1L, (byte) 10));
- queue.enqueue(createMessage(2L, (byte) 4));
- queue.enqueue(createMessage(3L, (byte) 0));
+ queue.enqueue(createMessage(1L, (byte) 10), null);
+ queue.enqueue(createMessage(2L, (byte) 4), null);
+ queue.enqueue(createMessage(3L, (byte) 0), null);
// Enqueue messages in reverse order
- queue.enqueue(createMessage(4L, (byte) 0));
- queue.enqueue(createMessage(5L, (byte) 4));
- queue.enqueue(createMessage(6L, (byte) 10));
+ queue.enqueue(createMessage(4L, (byte) 0), null);
+ queue.enqueue(createMessage(5L, (byte) 4), null);
+ queue.enqueue(createMessage(6L, (byte) 10), null);
// Enqueue messages out of order
- queue.enqueue(createMessage(7L, (byte) 4));
- queue.enqueue(createMessage(8L, (byte) 10));
- queue.enqueue(createMessage(9L, (byte) 0));
+ queue.enqueue(createMessage(7L, (byte) 4), null);
+ queue.enqueue(createMessage(8L, (byte) 10), null);
+ queue.enqueue(createMessage(9L, (byte) 0), null);
// Register subscriber
- queue.registerSubscription(getSubscription(), false);
+ queue.addConsumer(getConsumer(), null, null, "test", EnumSet.noneOf(Consumer.Option.class));
Thread.sleep(150);
- ArrayList<QueueEntry> msgs = getSubscription().getMessages();
+ ArrayList<MessageInstance> msgs = getConsumer().getMessages();
try
{
assertEquals(1L, msgs.get(0).getMessage().getMessageNumber());
@@ -84,7 +91,7 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest
{
// Show message order on failure.
int index = 1;
- for (QueueEntry qe : msgs)
+ for (MessageInstance qe : msgs)
{
System.err.println(index + ":" + qe.getMessage().getMessageNumber());
index++;
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java
index 2b1e7f5e1f..b67b2dda32 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java
@@ -21,13 +21,19 @@ package org.apache.qpid.server.queue;
import junit.framework.TestCase;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.queue.QueueEntry.EntryState;
-import org.apache.qpid.server.subscription.MockSubscription;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.message.MessageInstance.EntryState;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.virtualhost.VirtualHost;
import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.UUID;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -57,6 +63,15 @@ public abstract class QueueEntryImplTestBase extends TestCase
_queueEntry3 = getQueueEntryImpl(3);
}
+
+ protected void mockLogging()
+ {
+ final LogActor logActor = mock(LogActor.class);
+ when(logActor.getRootMessageLogger()).thenReturn(mock(RootMessageLogger.class));
+ CurrentActor.setDefault(logActor);
+ }
+
+
public void testAcquire()
{
assertTrue("Queue entry should be in AVAILABLE state before invoking of acquire method",
@@ -113,11 +128,19 @@ public abstract class QueueEntryImplTestBase extends TestCase
*/
private void acquire()
{
- _queueEntry.acquire(new MockSubscription());
+ _queueEntry.acquire(newConsumer());
assertTrue("Queue entry should be in ACQUIRED state after invoking of acquire method",
_queueEntry.isAcquired());
}
+ private QueueConsumer newConsumer()
+ {
+ final ConsumerTarget target = mock(ConsumerTarget.class);
+ when(target.getSessionModel()).thenReturn(mock(AMQSessionModel.class));
+ final QueueConsumer consumer = new QueueConsumer(null,null,true,true,"mock",false,target);
+ return consumer;
+ }
+
/**
* A helper method to get entry state
*
@@ -140,36 +163,34 @@ public abstract class QueueEntryImplTestBase extends TestCase
}
/**
- * Tests rejecting a queue entry records the Subscription ID
- * for later verification by isRejectedBy(subscriptionId).
+ * Tests rejecting a queue entry records the Consumer ID
+ * for later verification by isRejectedBy(consumerId).
*/
public void testRejectAndRejectedBy()
{
- Subscription sub = new MockSubscription();
- long subId = sub.getSubscriptionID();
+ QueueConsumer sub = newConsumer();
- assertFalse("Queue entry should not yet have been rejected by the subscription", _queueEntry.isRejectedBy(subId));
- assertFalse("Queue entry should not yet have been acquired by a subscription", _queueEntry.isAcquired());
+ assertFalse("Queue entry should not yet have been rejected by the consumer", _queueEntry.isRejectedBy(sub));
+ assertFalse("Queue entry should not yet have been acquired by a consumer", _queueEntry.isAcquired());
- //acquire, reject, and release the message using the subscription
+ //acquire, reject, and release the message using the consumer
assertTrue("Queue entry should have been able to be acquired", _queueEntry.acquire(sub));
_queueEntry.reject();
_queueEntry.release();
//verify the rejection is recorded
- assertTrue("Queue entry should have been rejected by the subscription", _queueEntry.isRejectedBy(subId));
+ assertTrue("Queue entry should have been rejected by the consumer", _queueEntry.isRejectedBy(sub));
- //repeat rejection using a second subscription
- Subscription sub2 = new MockSubscription();
- long sub2Id = sub2.getSubscriptionID();
+ //repeat rejection using a second consumer
+ QueueConsumer sub2 = newConsumer();
- assertFalse("Queue entry should not yet have been rejected by the subscription", _queueEntry.isRejectedBy(sub2Id));
+ assertFalse("Queue entry should not yet have been rejected by the consumer", _queueEntry.isRejectedBy(sub2));
assertTrue("Queue entry should have been able to be acquired", _queueEntry.acquire(sub2));
_queueEntry.reject();
- //verify it still records being rejected by both subscriptions
- assertTrue("Queue entry should have been rejected by the subscription", _queueEntry.isRejectedBy(subId));
- assertTrue("Queue entry should have been rejected by the subscription", _queueEntry.isRejectedBy(sub2Id));
+ //verify it still records being rejected by both consumers
+ assertTrue("Queue entry should have been rejected by the consumer", _queueEntry.isRejectedBy(sub));
+ assertTrue("Queue entry should have been rejected by the consumer", _queueEntry.isRejectedBy(sub2));
}
/**
@@ -179,7 +200,9 @@ public abstract class QueueEntryImplTestBase extends TestCase
{
int numberOfEntries = 5;
QueueEntryImpl[] entries = new QueueEntryImpl[numberOfEntries];
- SimpleQueueEntryList queueEntryList = new SimpleQueueEntryList(new MockAMQQueue("test"));
+ StandardQueue queue = new StandardQueue(UUID.randomUUID(), getName(), false, null, false, false,
+ mock(VirtualHost.class), Collections.<String,Object>emptyMap());
+ OrderedQueueEntryList queueEntryList = queue.getEntries();
// create test entries
for(int i = 0; i < numberOfEntries ; i++)
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java
index a1bc9e50c7..3af268c189 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java
@@ -25,6 +25,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.consumer.Consumer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -32,20 +33,21 @@ import static org.mockito.Mockito.when;
/**
* Abstract test class for QueueEntryList implementations.
*/
-public abstract class QueueEntryListTestBase extends TestCase
+public abstract class QueueEntryListTestBase<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, L extends QueueEntryList<E,Q,L,C>, C extends Consumer> extends TestCase
{
- protected static final AMQQueue _testQueue = new MockAMQQueue("test");
- public abstract QueueEntryList<QueueEntry> getTestList();
- public abstract QueueEntryList<QueueEntry> getTestList(boolean newList);
+ public abstract L getTestList();
+ public abstract L getTestList(boolean newList);
public abstract long getExpectedFirstMsgId();
public abstract int getExpectedListLength();
public abstract ServerMessage getTestMessageToAdd() throws AMQException;
public void testGetQueue()
{
- assertEquals("Unexpected head entry returned by getHead()", getTestList().getQueue(), _testQueue);
+ assertEquals("Unexpected head entry returned by getHead()", getTestList().getQueue(), getTestQueue());
}
+ protected abstract Q getTestQueue();
+
/**
* Test to add a message with properties specific to the queue type.
* @see QueueEntryListTestBase#getTestList()
@@ -54,10 +56,10 @@ public abstract class QueueEntryListTestBase extends TestCase
*/
public void testAddSpecificMessage() throws AMQException
{
- final QueueEntryList<QueueEntry> list = getTestList();
+ final L list = getTestList();
list.add(getTestMessageToAdd());
- final QueueEntryIterator<?> iter = list.iterator();
+ final QueueEntryIterator<E,Q,L,C> iter = list.iterator();
int count = 0;
while(iter.advance())
{
@@ -75,11 +77,11 @@ public abstract class QueueEntryListTestBase extends TestCase
*/
public void testAddGenericMessage() throws AMQException
{
- final QueueEntryList<QueueEntry> list = getTestList();
+ final L list = getTestList();
final ServerMessage message = createServerMessage(666l);
list.add(message);
- final QueueEntryIterator<?> iter = list.iterator();
+ final QueueEntryIterator<E,Q,L,C> iter = list.iterator();
int count = 0;
while(iter.advance())
{
@@ -109,8 +111,8 @@ public abstract class QueueEntryListTestBase extends TestCase
*/
public void testListNext()
{
- final QueueEntryList<QueueEntry> entryList = getTestList();
- QueueEntry entry = entryList.getHead();
+ final L entryList = getTestList();
+ E entry = entryList.getHead();
int count = 0;
while(entryList.next(entry) != null)
{
@@ -127,7 +129,7 @@ public abstract class QueueEntryListTestBase extends TestCase
*/
public void testIterator()
{
- final QueueEntryIterator<?> iter = getTestList().iterator();
+ final QueueEntryIterator<E,Q,L,C> iter = getTestList().iterator();
int count = 0;
while(iter.advance())
{
@@ -145,10 +147,10 @@ public abstract class QueueEntryListTestBase extends TestCase
public void testDequeuedMessagedNotPresentInIterator() throws Exception
{
final int numberOfMessages = getExpectedListLength();
- final QueueEntryList<QueueEntry> entryList = getTestList();
+ final L entryList = getTestList();
// dequeue all even messages
- final QueueEntryIterator<?> it1 = entryList.iterator();
+ final QueueEntryIterator<E,Q,L,C> it1 = entryList.iterator();
int counter = 0;
while (it1.advance())
{
@@ -161,7 +163,7 @@ public abstract class QueueEntryListTestBase extends TestCase
}
// iterate and check that dequeued messages are not returned by iterator
- final QueueEntryIterator<?> it2 = entryList.iterator();
+ final QueueEntryIterator<E,Q,L,C> it2 = entryList.iterator();
int counter2 = 0;
while(it2.advance())
{
@@ -180,7 +182,7 @@ public abstract class QueueEntryListTestBase extends TestCase
*/
public void testGetHead()
{
- final QueueEntry head = getTestList().getHead();
+ final E head = getTestList().getHead();
assertNull("Head entry should not contain an actual message", head.getMessage());
assertEquals("Unexpected message id for first list entry", getExpectedFirstMsgId(), getTestList().next(head)
.getMessage().getMessageNumber());
@@ -192,16 +194,16 @@ public abstract class QueueEntryListTestBase extends TestCase
*/
public void testEntryDeleted()
{
- final QueueEntry head = getTestList().getHead();
+ final E head = getTestList().getHead();
- final QueueEntry first = getTestList().next(head);
+ final E first = getTestList().next(head);
first.delete();
- final QueueEntry second = getTestList().next(head);
+ final E second = getTestList().next(head);
assertNotSame("After deletion the next entry should be different", first.getMessage().getMessageNumber(), second
.getMessage().getMessageNumber());
- final QueueEntry third = getTestList().next(first);
+ final E third = getTestList().next(first);
assertEquals("After deletion the deleted nodes next node should be the same as the next from head", second
.getMessage().getMessageNumber(), third.getMessage().getMessageNumber());
}
@@ -215,11 +217,11 @@ public abstract class QueueEntryListTestBase extends TestCase
*/
public void testIteratorIgnoresDeletedFinalNode() throws Exception
{
- QueueEntryList<QueueEntry> list = getTestList(true);
+ L list = getTestList(true);
int i = 0;
- QueueEntry queueEntry1 = list.add(createServerMessage(i++));
- QueueEntry queueEntry2 = list.add(createServerMessage(i++));
+ E queueEntry1 = list.add(createServerMessage(i++));
+ E queueEntry2 = list.add(createServerMessage(i++));
assertSame(queueEntry2, list.next(queueEntry1));
assertNull(list.next(queueEntry2));
@@ -228,7 +230,7 @@ public abstract class QueueEntryListTestBase extends TestCase
queueEntry2.delete();
assertTrue("Deleting node should have succeeded", queueEntry2.isDeleted());
- QueueEntryIterator<QueueEntry> iter = list.iterator();
+ QueueEntryIterator<E,Q,L,C> iter = list.iterator();
//verify the iterator isn't 'atTail', can advance, and returns the 1st QueueEntry
assertFalse("Iterator should not have been 'atTail'", iter.atTail());
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SelfValidatingSortedQueueEntryList.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SelfValidatingSortedQueueEntryList.java
index 674af36b77..87182dc8dc 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SelfValidatingSortedQueueEntryList.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SelfValidatingSortedQueueEntryList.java
@@ -22,7 +22,7 @@ package org.apache.qpid.server.queue;
import junit.framework.Assert;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.queue.SortedQueueEntryImpl.Colour;
+import org.apache.qpid.server.queue.SortedQueueEntry.Colour;
/**
* Test extension of SortedQueueEntryList that provides data structure validation tests.
@@ -30,22 +30,28 @@ import org.apache.qpid.server.queue.SortedQueueEntryImpl.Colour;
*/
public class SelfValidatingSortedQueueEntryList extends SortedQueueEntryList
{
- public SelfValidatingSortedQueueEntryList(AMQQueue queue, String propertyName)
+ public SelfValidatingSortedQueueEntryList(SortedQueue queue, String propertyName)
{
super(queue, propertyName);
}
+ @Override
+ public SortedQueue getQueue()
+ {
+ return super.getQueue();
+ }
+
@Override /** Overridden to automatically check queue properties before and after. */
- public SortedQueueEntryImpl add(final ServerMessage message)
+ public SortedQueueEntry add(final ServerMessage message)
{
assertQueueProperties(); //before add
- final SortedQueueEntryImpl result = super.add(message);
+ final SortedQueueEntry result = super.add(message);
assertQueueProperties(); //after add
return result;
}
@Override /** Overridden to automatically check queue properties before and after. */
- public void entryDeleted(SortedQueueEntryImpl entry)
+ public void entryDeleted(SortedQueueEntry entry)
{
assertQueueProperties(); //before delete
super.entryDeleted(entry);
@@ -73,7 +79,7 @@ public class SelfValidatingSortedQueueEntryList extends SortedQueueEntryList
assertTreeIntegrity(getRoot());
}
- public void assertTreeIntegrity(final SortedQueueEntryImpl node)
+ public void assertTreeIntegrity(final SortedQueueEntry node)
{
if(node == null)
{
@@ -109,7 +115,7 @@ public class SelfValidatingSortedQueueEntryList extends SortedQueueEntryList
assertLeavesSameBlackPath(getRoot());
}
- public int assertLeavesSameBlackPath(final SortedQueueEntryImpl node)
+ public int assertLeavesSameBlackPath(final SortedQueueEntry node)
{
if(node == null)
{
@@ -133,7 +139,7 @@ public class SelfValidatingSortedQueueEntryList extends SortedQueueEntryList
assertChildrenOfRedAreBlack(getRoot());
}
- public void assertChildrenOfRedAreBlack(final SortedQueueEntryImpl node)
+ public void assertChildrenOfRedAreBlack(final SortedQueueEntry node)
{
if(node == null)
{
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTestBase.java
index b0e5a510b8..45001bda50 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTestBase.java
@@ -29,6 +29,8 @@ import static org.mockito.Matchers.contains;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
+import java.util.Arrays;
+import java.util.EnumSet;
import java.util.Map;
import org.apache.log4j.Logger;
@@ -38,13 +40,14 @@ import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.server.exchange.DirectExchange;
import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.UUIDGenerator;
-import org.apache.qpid.server.queue.BaseQueue.PostEnqueueAction;
import org.apache.qpid.server.queue.SimpleAMQQueue.QueueEntryFilter;
-import org.apache.qpid.server.subscription.MockSubscription;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.consumer.MockConsumer;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.util.BrokerTestHelper;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -52,20 +55,20 @@ import org.apache.qpid.test.utils.QpidTestCase;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-public class SimpleAMQQueueTest extends QpidTestCase
+abstract class SimpleAMQQueueTestBase<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> extends QpidTestCase
{
- private static final Logger _logger = Logger.getLogger(SimpleAMQQueueTest.class);
+ private static final Logger _logger = Logger.getLogger(SimpleAMQQueueTestBase.class);
- private SimpleAMQQueue _queue;
+
+ private Q _queue;
private VirtualHost _virtualHost;
private String _qname = "qname";
private String _owner = "owner";
private String _routingKey = "routing key";
private DirectExchange _exchange;
- private MockSubscription _subscription = new MockSubscription();
+ private MockConsumer _consumerTarget = new MockConsumer();
+ private QueueConsumer _consumer;
private Map<String,Object> _arguments = null;
@Override
@@ -76,7 +79,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
_virtualHost = BrokerTestHelper.createVirtualHost(getClass().getName());
- _queue = (SimpleAMQQueue) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner,
+ _queue = (Q) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner,
false, false, false, _arguments);
_exchange = (DirectExchange) _virtualHost.getExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME);
@@ -102,7 +105,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
_queue.stop();
try
{
- _queue = (SimpleAMQQueue) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), null,
+ _queue = (Q) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), null,
false, _owner, false,
false, false, _arguments);
assertNull("Queue was created", _queue);
@@ -113,24 +116,14 @@ public class SimpleAMQQueueTest extends QpidTestCase
e.getMessage().contains("name"));
}
- try
- {
- _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner, false,false, null, Collections.EMPTY_MAP);
- assertNull("Queue was created", _queue);
- }
- catch (IllegalArgumentException e)
- {
- assertTrue("Exception was not about missing vhost",
- e.getMessage().contains("Host"));
- }
-
- _queue = (SimpleAMQQueue) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(),
+ _queue = (Q) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(),
"differentName", false,
_owner, false,
false, false, _arguments);
assertNotNull("Queue was not created", _queue);
}
+
public void testGetVirtualHost()
{
assertEquals("Virtual host was wrong", _virtualHost, _queue.getVirtualHost());
@@ -145,11 +138,11 @@ public class SimpleAMQQueueTest extends QpidTestCase
assertTrue("Queue was not bound to key",
_exchange.isBound(_routingKey,_queue));
assertEquals("Exchange binding count", 1,
- _queue.getBindings().size());
+ _queue.getBindings().size());
assertEquals("Wrong exchange bound", _routingKey,
_queue.getBindings().get(0).getBindingKey());
assertEquals("Wrong exchange bound", _exchange,
- _queue.getBindings().get(0).getExchange());
+ _queue.getBindings().get(0).getExchange());
_exchange.removeBinding(_routingKey, _queue, Collections.EMPTY_MAP);
assertFalse("Routing key was still bound",
@@ -157,20 +150,21 @@ public class SimpleAMQQueueTest extends QpidTestCase
}
- public void testRegisterSubscriptionThenEnqueueMessage() throws AMQException
+ public void testRegisterConsumerThenEnqueueMessage() throws AMQException
{
- // Check adding a subscription adds it to the queue
- _queue.registerSubscription(_subscription, false);
- assertEquals("Subscription did not get queue", _queue,
- _subscription.getQueue());
+ ServerMessage messageA = createMessage(new Long(24));
+
+ // Check adding a consumer adds it to the queue
+ _consumer = _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
assertEquals("Queue does not have consumer", 1,
_queue.getConsumerCount());
assertEquals("Queue does not have active consumer", 1,
- _queue.getActiveConsumerCount());
+ _queue.getActiveConsumerCount());
// Check sending a message ends up with the subscriber
- ServerMessage messageA = createMessage(new Long(24));
- _queue.enqueue(messageA);
+ _queue.enqueue(messageA, null);
try
{
Thread.sleep(2000L);
@@ -178,45 +172,51 @@ public class SimpleAMQQueueTest extends QpidTestCase
catch(InterruptedException e)
{
}
- assertEquals(messageA, _subscription.getQueueContext().getLastSeenEntry().getMessage());
- assertNull(((QueueContext)_subscription.getQueueContext()).getReleasedEntry());
+ assertEquals(messageA, _consumer.getQueueContext().getLastSeenEntry().getMessage());
+ assertNull(_consumer.getQueueContext().getReleasedEntry());
- // Check removing the subscription removes it's information from the queue
- _queue.unregisterSubscription(_subscription);
- assertTrue("Subscription still had queue", _subscription.isClosed());
+ // Check removing the consumer removes it's information from the queue
+ _consumer.close();
+ assertTrue("Consumer still had queue", _consumerTarget.isClosed());
assertFalse("Queue still has consumer", 1 == _queue.getConsumerCount());
assertFalse("Queue still has active consumer",
- 1 == _queue.getActiveConsumerCount());
+ 1 == _queue.getActiveConsumerCount());
ServerMessage messageB = createMessage(new Long (25));
- _queue.enqueue(messageB);
- assertNull(_subscription.getQueueContext());
+ _queue.enqueue(messageB, null);
+ assertNull(_consumer.getQueueContext());
}
- public void testEnqueueMessageThenRegisterSubscription() throws AMQException, InterruptedException
+ public void testEnqueueMessageThenRegisterConsumer() throws AMQException, InterruptedException
{
ServerMessage messageA = createMessage(new Long(24));
- _queue.enqueue(messageA);
- _queue.registerSubscription(_subscription, false);
+ _queue.enqueue(messageA, null);
+ _consumer = _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
Thread.sleep(150);
- assertEquals(messageA, _subscription.getQueueContext().getLastSeenEntry().getMessage());
- assertNull("There should be no releasedEntry after an enqueue", ((QueueContext)_subscription.getQueueContext()).getReleasedEntry());
+ assertEquals(messageA, _consumer.getQueueContext().getLastSeenEntry().getMessage());
+ assertNull("There should be no releasedEntry after an enqueue",
+ _consumer.getQueueContext().getReleasedEntry());
}
/**
* Tests enqueuing two messages.
*/
- public void testEnqueueTwoMessagesThenRegisterSubscription() throws Exception
+ public void testEnqueueTwoMessagesThenRegisterConsumer() throws Exception
{
ServerMessage messageA = createMessage(new Long(24));
ServerMessage messageB = createMessage(new Long(25));
- _queue.enqueue(messageA);
- _queue.enqueue(messageB);
- _queue.registerSubscription(_subscription, false);
+ _queue.enqueue(messageA, null);
+ _queue.enqueue(messageB, null);
+ _consumer = _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
Thread.sleep(150);
- assertEquals(messageB, _subscription.getQueueContext().getLastSeenEntry().getMessage());
- assertNull("There should be no releasedEntry after enqueues", ((QueueContext)_subscription.getQueueContext()).getReleasedEntry());
+ assertEquals(messageB, _consumer.getQueueContext().getLastSeenEntry().getMessage());
+ assertNull("There should be no releasedEntry after enqueues",
+ _consumer.getQueueContext().getReleasedEntry());
}
/**
@@ -225,21 +225,19 @@ public class SimpleAMQQueueTest extends QpidTestCase
*/
public void testReleasedMessageIsResentToSubscriber() throws Exception
{
- _queue.registerSubscription(_subscription, false);
-
- final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
- PostEnqueueAction postEnqueueAction = new PostEnqueueAction()
- {
- public void onEnqueue(QueueEntry entry)
- {
- queueEntries.add(entry);
- }
- };
ServerMessage messageA = createMessage(new Long(24));
ServerMessage messageB = createMessage(new Long(25));
ServerMessage messageC = createMessage(new Long(26));
+
+ _consumer = _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
+ final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
+ EntryListAddingAction postEnqueueAction = new EntryListAddingAction(queueEntries);
+
/* Enqueue three messages */
_queue.enqueue(messageA, postEnqueueAction);
@@ -248,7 +246,9 @@ public class SimpleAMQQueueTest extends QpidTestCase
Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
- assertEquals("Unexpected total number of messages sent to subscription", 3, _subscription.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to consumer",
+ 3,
+ _consumerTarget.getMessages().size());
assertFalse("Redelivery flag should not be set", queueEntries.get(0).isRedelivered());
assertFalse("Redelivery flag should not be set", queueEntries.get(1).isRedelivered());
assertFalse("Redelivery flag should not be set", queueEntries.get(2).isRedelivered());
@@ -259,11 +259,14 @@ public class SimpleAMQQueueTest extends QpidTestCase
Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
- assertEquals("Unexpected total number of messages sent to subscription", 4, _subscription.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to consumer",
+ 4,
+ _consumerTarget.getMessages().size());
assertTrue("Redelivery flag should now be set", queueEntries.get(0).isRedelivered());
assertFalse("Redelivery flag should remain be unset", queueEntries.get(1).isRedelivered());
assertFalse("Redelivery flag should remain be unset",queueEntries.get(2).isRedelivered());
- assertNull("releasedEntry should be cleared after requeue processed", ((QueueContext)_subscription.getQueueContext()).getReleasedEntry());
+ assertNull("releasedEntry should be cleared after requeue processed",
+ _consumer.getQueueContext().getReleasedEntry());
}
/**
@@ -273,20 +276,17 @@ public class SimpleAMQQueueTest extends QpidTestCase
*/
public void testReleaseMessageThatBecomesExpiredIsNotRedelivered() throws Exception
{
- _queue.registerSubscription(_subscription, false);
+ ServerMessage messageA = createMessage(new Long(24));
+
+ _consumer = _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.SEES_REQUEUES,
+ Consumer.Option.ACQUIRES));
final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
- PostEnqueueAction postEnqueueAction = new PostEnqueueAction()
- {
- public void onEnqueue(QueueEntry entry)
- {
- queueEntries.add(entry);
- }
- };
+ EntryListAddingAction postEnqueueAction = new EntryListAddingAction(queueEntries);
/* Enqueue one message with expiration set for a short time in the future */
- ServerMessage messageA = createMessage(new Long(24));
int messageExpirationOffset = 200;
final long expiration = System.currentTimeMillis() + messageExpirationOffset;
when(messageA.getExpiration()).thenReturn(expiration);
@@ -296,7 +296,9 @@ public class SimpleAMQQueueTest extends QpidTestCase
int subFlushWaitTime = 150;
Thread.sleep(subFlushWaitTime); // Work done by SubFlushRunner/QueueRunner Threads
- assertEquals("Unexpected total number of messages sent to subscription", 1, _subscription.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to consumer",
+ 1,
+ _consumerTarget.getMessages().size());
assertFalse("Redelivery flag should not be set", queueEntries.get(0).isRedelivered());
/* Wait a little more to be sure that message will have expired, then release the first message only, causing it to be requeued */
@@ -306,9 +308,12 @@ public class SimpleAMQQueueTest extends QpidTestCase
Thread.sleep(subFlushWaitTime); // Work done by SubFlushRunner/QueueRunner Threads
assertTrue("Expecting the queue entry to be now expired", queueEntries.get(0).expired());
- assertEquals("Total number of messages sent should not have changed", 1, _subscription.getMessages().size());
+ assertEquals("Total number of messages sent should not have changed",
+ 1,
+ _consumerTarget.getMessages().size());
assertFalse("Redelivery flag should not be set", queueEntries.get(0).isRedelivered());
- assertNull("releasedEntry should be cleared after requeue processed", ((QueueContext)_subscription.getQueueContext()).getReleasedEntry());
+ assertNull("releasedEntry should be cleared after requeue processed",
+ _consumer.getQueueContext().getReleasedEntry());
}
@@ -320,21 +325,18 @@ public class SimpleAMQQueueTest extends QpidTestCase
*/
public void testReleasedOutOfComparableOrderAreRedelivered() throws Exception
{
- _queue.registerSubscription(_subscription, false);
-
- final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
- PostEnqueueAction postEnqueueAction = new PostEnqueueAction()
- {
- public void onEnqueue(QueueEntry entry)
- {
- queueEntries.add(entry);
- }
- };
ServerMessage messageA = createMessage(new Long(24));
ServerMessage messageB = createMessage(new Long(25));
ServerMessage messageC = createMessage(new Long(26));
+ _consumer = _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
+ final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
+ EntryListAddingAction postEnqueueAction = new EntryListAddingAction(queueEntries);
+
/* Enqueue three messages */
_queue.enqueue(messageA, postEnqueueAction);
@@ -343,7 +345,9 @@ public class SimpleAMQQueueTest extends QpidTestCase
Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
- assertEquals("Unexpected total number of messages sent to subscription", 3, _subscription.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to consumer",
+ 3,
+ _consumerTarget.getMessages().size());
assertFalse("Redelivery flag should not be set", queueEntries.get(0).isRedelivered());
assertFalse("Redelivery flag should not be set", queueEntries.get(1).isRedelivered());
assertFalse("Redelivery flag should not be set", queueEntries.get(2).isRedelivered());
@@ -355,37 +359,41 @@ public class SimpleAMQQueueTest extends QpidTestCase
Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
- assertEquals("Unexpected total number of messages sent to subscription", 5, _subscription.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to consumer",
+ 5,
+ _consumerTarget.getMessages().size());
assertTrue("Redelivery flag should now be set", queueEntries.get(0).isRedelivered());
assertFalse("Redelivery flag should remain be unset", queueEntries.get(1).isRedelivered());
assertTrue("Redelivery flag should now be set",queueEntries.get(2).isRedelivered());
- assertNull("releasedEntry should be cleared after requeue processed", ((QueueContext)_subscription.getQueueContext()).getReleasedEntry());
+ assertNull("releasedEntry should be cleared after requeue processed",
+ _consumer.getQueueContext().getReleasedEntry());
}
/**
- * Tests that a release requeues an entry for a queue with multiple subscriptions. Verifies that a
+ * Tests that a release requeues an entry for a queue with multiple consumers. Verifies that a
* requeue resends a message to a <i>single</i> subscriber.
*/
- public void testReleaseForQueueWithMultipleSubscriptions() throws Exception
+ public void testReleaseForQueueWithMultipleConsumers() throws Exception
{
- MockSubscription subscription1 = new MockSubscription();
- MockSubscription subscription2 = new MockSubscription();
+ ServerMessage messageA = createMessage(new Long(24));
+ ServerMessage messageB = createMessage(new Long(25));
- _queue.registerSubscription(subscription1, false);
- _queue.registerSubscription(subscription2, false);
+ MockConsumer target1 = new MockConsumer();
+ MockConsumer target2 = new MockConsumer();
- final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
- PostEnqueueAction postEnqueueAction = new PostEnqueueAction()
- {
- public void onEnqueue(QueueEntry entry)
- {
- queueEntries.add(entry);
- }
- };
- ServerMessage messageA = createMessage(new Long(24));
- ServerMessage messageB = createMessage(new Long(25));
+ QueueConsumer consumer1 = _queue.addConsumer(target1, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
+ QueueConsumer consumer2 = _queue.addConsumer(target2, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
+
+ final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
+ EntryListAddingAction postEnqueueAction = new EntryListAddingAction(queueEntries);
/* Enqueue two messages */
@@ -394,32 +402,40 @@ public class SimpleAMQQueueTest extends QpidTestCase
Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
- assertEquals("Unexpected total number of messages sent to both after enqueue", 2, subscription1.getMessages().size() + subscription2.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to both after enqueue",
+ 2,
+ target1.getMessages().size() + target2.getMessages().size());
/* Now release the first message only, causing it to be requeued */
queueEntries.get(0).release();
Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
- assertEquals("Unexpected total number of messages sent to both subscriptions after release", 3, subscription1.getMessages().size() + subscription2.getMessages().size());
- assertNull("releasedEntry should be cleared after requeue processed", ((QueueContext)subscription1.getQueueContext()).getReleasedEntry());
- assertNull("releasedEntry should be cleared after requeue processed", ((QueueContext)subscription2.getQueueContext()).getReleasedEntry());
+ assertEquals("Unexpected total number of messages sent to both consumers after release",
+ 3,
+ target1.getMessages().size() + target2.getMessages().size());
+ assertNull("releasedEntry should be cleared after requeue processed",
+ consumer1.getQueueContext().getReleasedEntry());
+ assertNull("releasedEntry should be cleared after requeue processed",
+ consumer2.getQueueContext().getReleasedEntry());
}
public void testExclusiveConsumer() throws AMQException
{
- // Check adding an exclusive subscription adds it to the queue
- _queue.registerSubscription(_subscription, true);
- assertEquals("Subscription did not get queue", _queue,
- _subscription.getQueue());
+ ServerMessage messageA = createMessage(new Long(24));
+ // Check adding an exclusive consumer adds it to the queue
+
+ _consumer = _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.EXCLUSIVE, Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
assertEquals("Queue does not have consumer", 1,
- _queue.getConsumerCount());
+ _queue.getConsumerCount());
assertEquals("Queue does not have active consumer", 1,
- _queue.getActiveConsumerCount());
+ _queue.getActiveConsumerCount());
// Check sending a message ends up with the subscriber
- ServerMessage messageA = createMessage(new Long(24));
- _queue.enqueue(messageA);
+ _queue.enqueue(messageA, null);
try
{
Thread.sleep(2000L);
@@ -427,14 +443,18 @@ public class SimpleAMQQueueTest extends QpidTestCase
catch (InterruptedException e)
{
}
- assertEquals(messageA, _subscription.getQueueContext().getLastSeenEntry().getMessage());
+ assertEquals(messageA, _consumer.getQueueContext().getLastSeenEntry().getMessage());
// Check we cannot add a second subscriber to the queue
- Subscription subB = new MockSubscription();
+ MockConsumer subB = new MockConsumer();
Exception ex = null;
try
{
- _queue.registerSubscription(subB, false);
+
+ _queue.addConsumer(subB, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
}
catch (AMQException e)
{
@@ -443,12 +463,18 @@ public class SimpleAMQQueueTest extends QpidTestCase
assertNotNull(ex);
// Check we cannot add an exclusive subscriber to a queue with an
- // existing subscription
- _queue.unregisterSubscription(_subscription);
- _queue.registerSubscription(_subscription, false);
+ // existing consumer
+ _consumer.close();
+ _consumer = _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
try
{
- _queue.registerSubscription(subB, true);
+
+ _consumer = _queue.addConsumer(subB, null, messageA.getClass(), "test",
+ EnumSet.of(Consumer.Option.EXCLUSIVE));
+
}
catch (AMQException e)
{
@@ -457,28 +483,34 @@ public class SimpleAMQQueueTest extends QpidTestCase
assertNotNull(ex);
}
- public void testAutoDeleteQueue() throws Exception
- {
- _queue.stop();
- _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, null, true, false, _virtualHost, Collections.EMPTY_MAP);
- _queue.setDeleteOnNoConsumers(true);
- _queue.registerSubscription(_subscription, false);
- ServerMessage message = createMessage(new Long(25));
- _queue.enqueue(message);
- _queue.unregisterSubscription(_subscription);
- assertTrue("Queue was not deleted when subscription was removed",
- _queue.isDeleted());
- }
public void testResend() throws Exception
{
- _queue.registerSubscription(_subscription, false);
Long id = new Long(26);
ServerMessage message = createMessage(id);
- _queue.enqueue(message);
- QueueEntry entry = _subscription.getQueueContext().getLastSeenEntry();
- entry.setRedelivered();
- _queue.resend(entry, _subscription);
+
+ _consumer = _queue.addConsumer(_consumerTarget, null, message.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES, Consumer.Option.SEES_REQUEUES));
+
+ _queue.enqueue(message, new Action<MessageInstance<?,? extends Consumer>>()
+ {
+ @Override
+ public void performAction(final MessageInstance<?,? extends Consumer> object)
+ {
+ QueueEntryImpl entry = (QueueEntryImpl) object;
+ entry.setRedelivered();
+ try
+ {
+ _consumer.resend(entry);
+ }
+ catch (AMQException e)
+ {
+ fail("Exception thrown: " + e.getMessage());
+ }
+ }
+ });
+
+
}
@@ -489,7 +521,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
ServerMessage message = createMessage(messageId);
// Put message on queue
- _queue.enqueue(message);
+ _queue.enqueue(message, null);
// Get message id
Long testmsgid = _queue.getMessagesOnTheQueue(1).get(0);
@@ -505,7 +537,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
Long messageId = new Long(i);
ServerMessage message = createMessage(messageId);
// Put message on queue
- _queue.enqueue(message);
+ _queue.enqueue(message, null);
}
// Get message ids
List<Long> msgids = _queue.getMessagesOnTheQueue(5);
@@ -526,7 +558,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
Long messageId = new Long(i);
ServerMessage message = createMessage(messageId);
// Put message on queue
- _queue.enqueue(message);
+ _queue.enqueue(message, null);
}
// Get message ids
List<Long> msgids = _queue.getMessagesOnTheQueue(5, 5);
@@ -547,12 +579,12 @@ public class SimpleAMQQueueTest extends QpidTestCase
Long messageId = new Long(i);
ServerMessage message = createMessage(messageId);
// Put message on queue
- _queue.enqueue(message);
+ _queue.enqueue(message, null);
}
// Get non-existent 0th QueueEntry & check returned list was empty
// (the position parameters in this method are indexed from 1)
- List<QueueEntry> entries = _queue.getMessagesRangeOnTheQueue(0, 0);
+ List<E> entries = _queue.getMessagesRangeOnTheQueue(0, 0);
assertTrue(entries.size() == 0);
// Check that when 'from' is 0 it is ignored and the range continues from 1
@@ -605,38 +637,28 @@ public class SimpleAMQQueueTest extends QpidTestCase
/**
* processQueue() is used when asynchronously delivering messages to
- * subscriptions which could not be delivered immediately during the
+ * consumers which could not be delivered immediately during the
* enqueue() operation.
*
* A defect within the method would mean that delivery of these messages may
* not occur should the Runner stop before all messages have been processed.
* Such a defect was discovered when Selectors were used such that one and
- * only one subscription can/will accept any given messages, but multiple
- * subscriptions are present, and one of the earlier subscriptions receives
+ * only one consumer can/will accept any given messages, but multiple
+ * consumers are present, and one of the earlier consumers receives
* more messages than the others.
*
* This test is to validate that the processQueue() method is able to
* correctly deliver all of the messages present for asynchronous delivery
- * to subscriptions in such a scenario.
+ * to consumers in such a scenario.
*/
public void testProcessQueueWithUniqueSelectors() throws Exception
{
- TestSimpleQueueEntryListFactory factory = new TestSimpleQueueEntryListFactory();
- SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "testQueue", false,"testOwner",
- false, false, _virtualHost, factory, null)
- {
- @Override
- public void deliverAsync(Subscription sub)
- {
- // do nothing, i.e prevent deliveries by the SubFlushRunner
- // when registering the new subscriptions
- }
- };
+ SimpleAMQQueue testQueue = createNonAsyncDeliverQueue();
// retrieve the QueueEntryList the queue creates and insert the test
// messages, thus avoiding straight-through delivery attempts during
//enqueue() process.
- QueueEntryList list = factory.getQueueEntryList();
+ QueueEntryList list = testQueue.getEntries();
assertNotNull("QueueEntryList should have been created", list);
QueueEntry msg1 = list.add(createMessage(1L));
@@ -645,25 +667,28 @@ public class SimpleAMQQueueTest extends QpidTestCase
QueueEntry msg4 = list.add(createMessage(4L));
QueueEntry msg5 = list.add(createMessage(5L));
- // Create lists of the entries each subscription should be interested
- // in.Bias over 50% of the messages to the first subscription so that
- // the later subscriptions reject them and report being done before
- // the first subscription as the processQueue method proceeds.
- List<QueueEntry> msgListSub1 = createEntriesList(msg1, msg2, msg3);
- List<QueueEntry> msgListSub2 = createEntriesList(msg4);
- List<QueueEntry> msgListSub3 = createEntriesList(msg5);
-
- MockSubscription sub1 = new MockSubscription(msgListSub1);
- MockSubscription sub2 = new MockSubscription(msgListSub2);
- MockSubscription sub3 = new MockSubscription(msgListSub3);
-
- // register the subscriptions
- testQueue.registerSubscription(sub1, false);
- testQueue.registerSubscription(sub2, false);
- testQueue.registerSubscription(sub3, false);
+ // Create lists of the entries each consumer should be interested
+ // in.Bias over 50% of the messages to the first consumer so that
+ // the later consumers reject them and report being done before
+ // the first consumer as the processQueue method proceeds.
+ List<String> msgListSub1 = createEntriesList(msg1, msg2, msg3);
+ List<String> msgListSub2 = createEntriesList(msg4);
+ List<String> msgListSub3 = createEntriesList(msg5);
+
+ MockConsumer sub1 = new MockConsumer(msgListSub1);
+ MockConsumer sub2 = new MockConsumer(msgListSub2);
+ MockConsumer sub3 = new MockConsumer(msgListSub3);
+
+ // register the consumers
+ testQueue.addConsumer(sub1, sub1.getFilters(), msg1.getMessage().getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES, Consumer.Option.SEES_REQUEUES));
+ testQueue.addConsumer(sub2, sub2.getFilters(), msg1.getMessage().getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES, Consumer.Option.SEES_REQUEUES));
+ testQueue.addConsumer(sub3, sub3.getFilters(), msg1.getMessage().getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES, Consumer.Option.SEES_REQUEUES));
//check that no messages have been delivered to the
- //subscriptions during registration
+ //consumers during registration
assertEquals("No messages should have been delivered yet", 0, sub1.getMessages().size());
assertEquals("No messages should have been delivered yet", 0, sub2.getMessages().size());
assertEquals("No messages should have been delivered yet", 0, sub3.getMessages().size());
@@ -680,9 +705,15 @@ public class SimpleAMQQueueTest extends QpidTestCase
});
// check expected messages delivered to correct consumers
- verifyReceivedMessages(msgListSub1, sub1.getMessages());
- verifyReceivedMessages(msgListSub2, sub2.getMessages());
- verifyReceivedMessages(msgListSub3, sub3.getMessages());
+ verifyReceivedMessages(Arrays.asList((MessageInstance)msg1,msg2,msg3), sub1.getMessages());
+ verifyReceivedMessages(Collections.singletonList((MessageInstance)msg4), sub2.getMessages());
+ verifyReceivedMessages(Collections.singletonList((MessageInstance)msg5), sub3.getMessages());
+ }
+
+ private SimpleAMQQueue createNonAsyncDeliverQueue()
+ {
+ TestSimpleQueueEntryListFactory factory = new TestSimpleQueueEntryListFactory();
+ return new NonAsyncDeliverQueue(factory, getVirtualHost());
}
/**
@@ -701,7 +732,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
dequeueMessage(_queue, dequeueMessageIndex);
// get messages on the queue
- List<QueueEntry> entries = _queue.getMessagesOnTheQueue();
+ List<E> entries = _queue.getMessagesOnTheQueue();
// assert queue entries
assertEquals(messageNumber - 1, entries.size());
@@ -738,9 +769,9 @@ public class SimpleAMQQueueTest extends QpidTestCase
dequeueMessage(_queue, dequeueMessageIndex);
// get messages on the queue with filter accepting all available messages
- List<QueueEntry> entries = _queue.getMessagesOnTheQueue(new QueueEntryFilter()
+ List<E> entries = _queue.getMessagesOnTheQueue(new QueueEntryFilter<E>()
{
- public boolean accept(QueueEntry entry)
+ public boolean accept(E entry)
{
return true;
}
@@ -792,12 +823,12 @@ public class SimpleAMQQueueTest extends QpidTestCase
_queue.deleteMessageFromTop();
//get queue entries
- List<QueueEntry> entries = _queue.getMessagesOnTheQueue();
+ List<E> entries = _queue.getMessagesOnTheQueue();
// assert queue entries
assertNotNull("Null is returned from getMessagesOnTheQueue", entries);
assertEquals("Expected " + (messageNumber - 2) + " number of messages but recieved " + entries.size(),
- messageNumber - 2, entries.size());
+ messageNumber - 2, entries.size());
assertEquals("Expected first entry with id 2", 2l,
(entries.get(0).getMessage()).getMessageNumber());
}
@@ -828,222 +859,13 @@ public class SimpleAMQQueueTest extends QpidTestCase
}
// get queue entries
- List<QueueEntry> entries = _queue.getMessagesOnTheQueue();
+ List<E> entries = _queue.getMessagesOnTheQueue();
// assert queue entries
assertNotNull(entries);
assertEquals(0, entries.size());
}
- /**
- * Tests whether dequeued entry is sent to subscriber in result of
- * invocation of {@link SimpleAMQQueue#processQueue(QueueRunner)}
- */
- public void testProcessQueueWithDequeuedEntry()
- {
- // total number of messages to send
- int messageNumber = 4;
- int dequeueMessageIndex = 1;
-
- // create queue with overridden method deliverAsync
- SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "test",
- false, "testOwner", false, false, _virtualHost, null)
- {
- @Override
- public void deliverAsync(Subscription sub)
- {
- // do nothing
- }
- };
-
- // put messages
- List<QueueEntry> entries = enqueueGivenNumberOfMessages(testQueue, messageNumber);
-
- // dequeue message
- dequeueMessage(testQueue, dequeueMessageIndex);
-
- // latch to wait for message receipt
- final CountDownLatch latch = new CountDownLatch(messageNumber -1);
-
- // create a subscription
- MockSubscription subscription = new MockSubscription()
- {
- /**
- * Send a message and decrement latch
- * @param entry
- * @param batch
- */
- public void send(QueueEntry entry, boolean batch) throws AMQException
- {
- super.send(entry, batch);
- latch.countDown();
- }
- };
-
- try
- {
- // subscribe
- testQueue.registerSubscription(subscription, false);
-
- // process queue
- testQueue.processQueue(new QueueRunner(testQueue)
- {
- public void run()
- {
- // do nothing
- }
- });
- }
- catch (AMQException e)
- {
- fail("Failure to process queue:" + e.getMessage());
- }
- // wait up to 1 minute for message receipt
- try
- {
- latch.await(1, TimeUnit.MINUTES);
- }
- catch (InterruptedException e1)
- {
- Thread.currentThread().interrupt();
- }
- List<QueueEntry> expected = createEntriesList(entries.get(0), entries.get(2), entries.get(3));
- verifyReceivedMessages(expected, subscription.getMessages());
- }
-
- /**
- * Tests that entry in dequeued state are not enqueued and not delivered to subscription
- */
- public void testEnqueueDequeuedEntry()
- {
- // create a queue where each even entry is considered a dequeued
- SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "test", false,
- "testOwner", false, false, _virtualHost, new QueueEntryListFactory()
- {
- public QueueEntryList createQueueEntryList(AMQQueue queue)
- {
- /**
- * Override SimpleQueueEntryList to create a dequeued
- * entries for messages with even id
- */
- return new SimpleQueueEntryList(queue)
- {
- /**
- * Entries with even message id are considered
- * dequeued!
- */
- protected SimpleQueueEntryImpl createQueueEntry(final ServerMessage message)
- {
- return new SimpleQueueEntryImpl(this, message)
- {
-
- public boolean isDeleted()
- {
- return (message.getMessageNumber() % 2 == 0);
- }
-
- public boolean isAvailable()
- {
- return !(message.getMessageNumber() % 2 == 0);
- }
-
- @Override
- public boolean acquire(Subscription sub)
- {
- if(message.getMessageNumber() % 2 == 0)
- {
- return false;
- }
- else
- {
- return super.acquire(sub);
- }
- }
- };
- }
- };
- }
- }, null);
- // create a subscription
- MockSubscription subscription = new MockSubscription();
-
- // register subscription
- try
- {
- queue.registerSubscription(subscription, false);
- }
- catch (AMQException e)
- {
- fail("Failure to register subscription:" + e.getMessage());
- }
-
- // put test messages into a queue
- putGivenNumberOfMessages(queue, 4);
-
- // assert received messages
- List<QueueEntry> messages = subscription.getMessages();
- assertEquals("Only 2 messages should be returned", 2, messages.size());
- assertEquals("ID of first message should be 1", 1l,
- (messages.get(0).getMessage()).getMessageNumber());
- assertEquals("ID of second message should be 3", 3l,
- (messages.get(1).getMessage()).getMessageNumber());
- }
-
- public void testActiveConsumerCount() throws Exception
- {
- final SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "testActiveConsumerCount", false,
- "testOwner", false, false, _virtualHost, new SimpleQueueEntryList.Factory(), null);
-
- //verify adding an active subscription increases the count
- final MockSubscription subscription1 = new MockSubscription();
- subscription1.setActive(true);
- assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount());
- queue.registerSubscription(subscription1, false);
- assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
-
- //verify adding an inactive subscription doesn't increase the count
- final MockSubscription subscription2 = new MockSubscription();
- subscription2.setActive(false);
- assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
- queue.registerSubscription(subscription2, false);
- assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
-
- //verify behaviour in face of expected state changes:
-
- //verify a subscription going suspended->active increases the count
- queue.stateChange(subscription2, Subscription.State.SUSPENDED, Subscription.State.ACTIVE);
- assertEquals("Unexpected active consumer count", 2, queue.getActiveConsumerCount());
-
- //verify a subscription going active->suspended decreases the count
- queue.stateChange(subscription2, Subscription.State.ACTIVE, Subscription.State.SUSPENDED);
- assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
-
- //verify a subscription going suspended->closed doesn't change the count
- queue.stateChange(subscription2, Subscription.State.SUSPENDED, Subscription.State.CLOSED);
- assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
-
- //verify a subscription going active->closed decreases the count
- queue.stateChange(subscription2, Subscription.State.ACTIVE, Subscription.State.CLOSED);
- assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount());
-
- //verify behaviour in face of unexpected state changes:
-
- //verify a subscription going closed->active increases the count
- queue.stateChange(subscription2, Subscription.State.CLOSED, Subscription.State.ACTIVE);
- assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
-
- //verify a subscription going active->active doesn't change the count
- queue.stateChange(subscription2, Subscription.State.ACTIVE, Subscription.State.ACTIVE);
- assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
-
- //verify a subscription going closed->suspended doesn't change the count
- queue.stateChange(subscription2, Subscription.State.CLOSED, Subscription.State.SUSPENDED);
- assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
-
- //verify a subscription going suspended->suspended doesn't change the count
- queue.stateChange(subscription2, Subscription.State.SUSPENDED, Subscription.State.SUSPENDED);
- assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
- }
public void testNotificationFiredOnEnqueue() throws Exception
{
@@ -1052,10 +874,10 @@ public class SimpleAMQQueueTest extends QpidTestCase
_queue.setNotificationListener(listener);
_queue.setMaximumMessageCount(2);
- _queue.enqueue(createMessage(new Long(24)));
+ _queue.enqueue(createMessage(new Long(24)), null);
verifyZeroInteractions(listener);
- _queue.enqueue(createMessage(new Long(25)));
+ _queue.enqueue(createMessage(new Long(25)), null);
verify(listener, atLeastOnce()).notifyClients(eq(NotificationCheck.MESSAGE_COUNT_ALERT), eq(_queue), contains("Maximum count on queue threshold"));
}
@@ -1064,9 +886,9 @@ public class SimpleAMQQueueTest extends QpidTestCase
{
AMQQueue.NotificationListener listener = mock(AMQQueue.NotificationListener.class);
- _queue.enqueue(createMessage(new Long(24)));
- _queue.enqueue(createMessage(new Long(25)));
- _queue.enqueue(createMessage(new Long(26)));
+ _queue.enqueue(createMessage(new Long(24)), null);
+ _queue.enqueue(createMessage(new Long(25)), null);
+ _queue.enqueue(createMessage(new Long(26)), null);
_queue.setNotificationListener(listener);
_queue.setMaximumMessageCount(2);
@@ -1088,12 +910,12 @@ public class SimpleAMQQueueTest extends QpidTestCase
* @param messageNumber
* number of messages to put into queue
*/
- private List<QueueEntry> enqueueGivenNumberOfMessages(AMQQueue queue, int messageNumber)
+ protected List<E> enqueueGivenNumberOfMessages(Q queue, int messageNumber)
{
putGivenNumberOfMessages(queue, messageNumber);
// make sure that all enqueued messages are on the queue
- List<QueueEntry> entries = queue.getMessagesOnTheQueue();
+ List<E> entries = queue.getMessagesOnTheQueue();
assertEquals(messageNumber, entries.size());
for (int i = 0; i < messageNumber; i++)
{
@@ -1114,16 +936,15 @@ public class SimpleAMQQueueTest extends QpidTestCase
* @param queue
* @param messageNumber
*/
- private void putGivenNumberOfMessages(AMQQueue queue, int messageNumber)
+ protected <T extends SimpleAMQQueue> void putGivenNumberOfMessages(T queue, int messageNumber)
{
for (int i = 0; i < messageNumber; i++)
{
// Create message
- Long messageId = new Long(i);
ServerMessage message = null;
try
{
- message = createMessage(messageId);
+ message = createMessage((long)i);
}
catch (AMQException e)
{
@@ -1132,7 +953,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
// Put message on queue
try
{
- queue.enqueue(message);
+ queue.enqueue(message,null);
}
catch (AMQException e)
{
@@ -1157,7 +978,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
* @param dequeueMessageIndex
* entry index to dequeue.
*/
- private QueueEntry dequeueMessage(AMQQueue queue, int dequeueMessageIndex)
+ protected QueueEntry dequeueMessage(AMQQueue queue, int dequeueMessageIndex)
{
List<QueueEntry> entries = queue.getMessagesOnTheQueue();
QueueEntry entry = entries.get(dequeueMessageIndex);
@@ -1167,37 +988,42 @@ public class SimpleAMQQueueTest extends QpidTestCase
return entry;
}
- private List<QueueEntry> createEntriesList(QueueEntry... entries)
+ private List<String> createEntriesList(QueueEntry... entries)
{
- ArrayList<QueueEntry> entriesList = new ArrayList<QueueEntry>();
+ ArrayList<String> entriesList = new ArrayList<String>();
for (QueueEntry entry : entries)
{
- entriesList.add(entry);
+ entriesList.add(entry.getMessage().getMessageHeader().getMessageId());
}
return entriesList;
}
- private void verifyReceivedMessages(List<QueueEntry> expected,
- List<QueueEntry> delivered)
+ protected void verifyReceivedMessages(List<MessageInstance> expected,
+ List<MessageInstance> delivered)
{
assertEquals("Consumer did not receive the expected number of messages",
expected.size(), delivered.size());
- for (QueueEntry msg : expected)
+ for (MessageInstance msg : expected)
{
assertTrue("Consumer did not receive msg: "
+ msg.getMessage().getMessageNumber(), delivered.contains(msg));
}
}
- public SimpleAMQQueue getQueue()
+ public Q getQueue()
{
return _queue;
}
- public MockSubscription getSubscription()
+ protected void setQueue(Q queue)
{
- return _subscription;
+ _queue = queue;
+ }
+
+ public MockConsumer getConsumer()
+ {
+ return _consumerTarget;
}
public Map<String,Object> getArguments()
@@ -1213,33 +1039,146 @@ public class SimpleAMQQueueTest extends QpidTestCase
protected ServerMessage createMessage(Long id) throws AMQException
{
+ AMQMessageHeader header = mock(AMQMessageHeader.class);
+ when(header.getMessageId()).thenReturn(String.valueOf(id));
ServerMessage message = mock(ServerMessage.class);
when(message.getMessageNumber()).thenReturn(id);
+ when(message.getMessageHeader()).thenReturn(header);
MessageReference ref = mock(MessageReference.class);
when(ref.getMessage()).thenReturn(message);
- AMQMessageHeader hdr = mock(AMQMessageHeader.class);
- when(message.getMessageHeader()).thenReturn(hdr);
when(message.newReference()).thenReturn(ref);
return message;
}
- class TestSimpleQueueEntryListFactory implements QueueEntryListFactory
+ private static class EntryListAddingAction implements Action<MessageInstance<?,? extends Consumer>>
+ {
+ private final ArrayList<QueueEntry> _queueEntries;
+
+ public EntryListAddingAction(final ArrayList<QueueEntry> queueEntries)
+ {
+ _queueEntries = queueEntries;
+ }
+
+ public void performAction(MessageInstance<?,? extends Consumer> entry)
+ {
+ _queueEntries.add((QueueEntry) entry);
+ }
+ }
+
+
+ public VirtualHost getVirtualHost()
+ {
+ return _virtualHost;
+ }
+
+ public String getQname()
+ {
+ return _qname;
+ }
+
+ public String getOwner()
+ {
+ return _owner;
+ }
+
+ public String getRoutingKey()
+ {
+ return _routingKey;
+ }
+
+ public DirectExchange getExchange()
+ {
+ return _exchange;
+ }
+
+ public MockConsumer getConsumerTarget()
{
- QueueEntryList _list;
+ return _consumerTarget;
+ }
+
- public QueueEntryList createQueueEntryList(AMQQueue queue)
+ static class TestSimpleQueueEntryListFactory implements QueueEntryListFactory<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList>
+ {
+
+ @Override
+ public NonAsyncDeliverList createQueueEntryList(final NonAsyncDeliverQueue queue)
+ {
+ return new NonAsyncDeliverList(queue);
+ }
+ }
+
+ private static class NonAsyncDeliverEntry extends OrderedQueueEntry<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList>
+ {
+
+ public NonAsyncDeliverEntry(final NonAsyncDeliverList queueEntryList)
+ {
+ super(queueEntryList);
+ }
+
+ public NonAsyncDeliverEntry(final NonAsyncDeliverList queueEntryList,
+ final ServerMessage message,
+ final long entryId)
+ {
+ super(queueEntryList, message, entryId);
+ }
+
+ public NonAsyncDeliverEntry(final NonAsyncDeliverList queueEntryList, final ServerMessage message)
+ {
+ super(queueEntryList, message);
+ }
+ }
+
+ private static class NonAsyncDeliverList extends OrderedQueueEntryList<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList>
+ {
+
+ private static final HeadCreator<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList> HEAD_CREATOR =
+ new HeadCreator<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList>()
+ {
+
+ @Override
+ public NonAsyncDeliverEntry createHead(final NonAsyncDeliverList list)
+ {
+ return new NonAsyncDeliverEntry(list);
+ }
+ };
+
+ public NonAsyncDeliverList(final NonAsyncDeliverQueue queue)
+ {
+ super(queue, HEAD_CREATOR);
+ }
+
+ @Override
+ protected NonAsyncDeliverEntry createQueueEntry(final ServerMessage<?> message)
+ {
+ return new NonAsyncDeliverEntry(this,message);
+ }
+ }
+
+
+ private static class NonAsyncDeliverQueue extends SimpleAMQQueue<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList>
+ {
+ public NonAsyncDeliverQueue(final TestSimpleQueueEntryListFactory factory, VirtualHost vhost)
{
- _list = new SimpleQueueEntryList(queue);
- return _list;
+ super(UUIDGenerator.generateRandomUUID(),
+ "testQueue",
+ false,
+ "testOwner",
+ false,
+ false,
+ vhost,
+ factory,
+ null);
}
- public QueueEntryList getQueueEntryList()
+ @Override
+ public void deliverAsync(QueueConsumer sub)
{
- return _list;
+ // do nothing, i.e prevent deliveries by the SubFlushRunner
+ // when registering the new consumers
}
}
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java
index 11ff7ed192..36425761be 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java
@@ -21,8 +21,14 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import java.util.UUID;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -30,7 +36,20 @@ import static org.mockito.Mockito.when;
public class SimpleQueueEntryImplTest extends QueueEntryImplTestBase
{
- private SimpleQueueEntryList queueEntryList = new SimpleQueueEntryList(new MockAMQQueue("test"));
+ private OrderedQueueEntryList queueEntryList;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ mockLogging();
+
+ StandardQueue queue = new StandardQueue(UUID.randomUUID(), "SimpleQueueEntryImplTest", false, null,false, false, mock(VirtualHost.class),null);
+
+ queueEntryList = queue.getEntries();
+
+ super.setUp();
+ }
+
public QueueEntryImpl getQueueEntryImpl(int msgId) throws AMQException
{
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java
index 7add2d4d43..b6b3843ad2 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java
@@ -21,20 +21,26 @@ package org.apache.qpid.server.queue;
import java.util.Collections;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Arrays;
+import java.util.UUID;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class SortedQueueEntryListTest extends QueueEntryListTestBase
+public class SortedQueueEntryListTest extends QueueEntryListTestBase<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>>
{
private static SelfValidatingSortedQueueEntryList _sqel;
+
public final static String keys[] = { " 73", " 18", " 11", "127", "166", "163", " 69", " 60", "191", "144",
" 17", "161", "145", "140", "157", " 47", "136", " 56", "176", " 81",
"195", " 96", " 2", " 68", "101", "141", "159", "187", "149", " 45",
@@ -62,16 +68,30 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
private final static String keysSorted[] = keys.clone();
+ private SortedQueue _testQueue;
+
@Override
protected void setUp() throws Exception
{
+ mockLogging();
+
+ // Create test list
+ _testQueue = new SortedQueue(UUID.randomUUID(), getName(), false, null, false,false, mock(VirtualHost.class), null, "KEY", new QueueEntryListFactory<SortedQueueEntry,SortedQueue,SortedQueueEntryList>()
+ {
+
+ @Override
+ public SortedQueueEntryList createQueueEntryList(final SortedQueue queue)
+ {
+ return new SelfValidatingSortedQueueEntryList(queue, "KEY");
+ }
+ });
+ _sqel = (SelfValidatingSortedQueueEntryList) _testQueue.getEntries();
+
super.setUp();
// Create result array
Arrays.sort(keysSorted);
- // Create test list
- _sqel = new SelfValidatingSortedQueueEntryList(_testQueue, "KEY");
// Build test list
long messageId = 0L;
@@ -83,14 +103,22 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
}
+ protected void mockLogging()
+ {
+ final LogActor logActor = mock(LogActor.class);
+ when(logActor.getRootMessageLogger()).thenReturn(mock(RootMessageLogger.class));
+ CurrentActor.setDefault(logActor);
+ }
+
+
@Override
- public QueueEntryList getTestList()
+ public SortedQueueEntryList getTestList()
{
return getTestList(false);
}
@Override
- public QueueEntryList getTestList(boolean newList)
+ public SortedQueueEntryList getTestList(boolean newList)
{
if(newList)
{
@@ -117,6 +145,12 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
return generateTestMessage(1, "test value");
}
+ @Override
+ protected SortedQueue getTestQueue()
+ {
+ return _testQueue;
+ }
+
private ServerMessage generateTestMessage(final long id, final String keyValue) throws AMQException
{
final ServerMessage message = mock(ServerMessage.class);
@@ -138,7 +172,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
super.testIterator();
// Test sorted order of list
- final QueueEntryIterator<?> iter = getTestList().iterator();
+ final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator();
int count = 0;
while(iter.advance())
{
@@ -147,12 +181,12 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
}
}
- private Object getSortedKeyValue(QueueEntryIterator<?> iter)
+ private Object getSortedKeyValue(QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter)
{
return (iter.getNode()).getMessage().getMessageHeader().getHeader("KEY");
}
- private Long getMessageId(QueueEntryIterator<?> iter)
+ private Long getMessageId(QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter)
{
return (iter.getNode()).getMessage().getMessageNumber();
}
@@ -169,7 +203,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
_sqel.add(msg);
}
- final QueueEntryIterator<?> iter = getTestList().iterator();
+ final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator();
int count=0;
while(iter.advance())
{
@@ -190,12 +224,13 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
_sqel.add(msg);
}
- final QueueEntryIterator<?> iter = getTestList().iterator();
+ final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator();
int count=0;
while(iter.advance())
{
assertNull("Sorted queue entry value is not as expected", getSortedKeyValue(iter));
- assertEquals("Message id not as expected", Long.valueOf(count++), getMessageId(iter)); }
+ assertEquals("Message id not as expected", Long.valueOf(count++), getMessageId(iter));
+ }
}
public void testAscendingSortKeys() throws Exception
@@ -211,7 +246,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
_sqel.add(msg);
}
- final QueueEntryIterator<?> iter = getTestList().iterator();
+ final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator();
int count=0;
while(iter.advance())
{
@@ -234,7 +269,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
_sqel.add(msg);
}
- final QueueEntryIterator<?> iter = getTestList().iterator();
+ final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator();
int count=0;
while(iter.advance())
{
@@ -251,7 +286,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
ServerMessage msg = generateTestMessage(1, "A");
_sqel.add(msg);
- SortedQueueEntryImpl entry = _sqel.next(_sqel.getHead());
+ SortedQueueEntry entry = _sqel.next(_sqel.getHead());
validateEntry(entry, "A", 1);
msg = generateTestMessage(2, "B");
@@ -271,7 +306,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
ServerMessage msg = generateTestMessage(1, "B");
_sqel.add(msg);
- SortedQueueEntryImpl entry = _sqel.next(_sqel.getHead());
+ SortedQueueEntry entry = _sqel.next(_sqel.getHead());
validateEntry(entry, "B", 1);
msg = generateTestMessage(2, "A");
@@ -290,7 +325,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
ServerMessage msg = generateTestMessage(1, "A");
_sqel.add(msg);
- SortedQueueEntryImpl entry = _sqel.next(_sqel.getHead());
+ SortedQueueEntry entry = _sqel.next(_sqel.getHead());
validateEntry(entry, "A", 1);
msg = generateTestMessage(2, "C");
@@ -322,7 +357,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
ServerMessage msg = generateTestMessage(1, "B");
_sqel.add(msg);
- SortedQueueEntryImpl entry = _sqel.next(_sqel.getHead());
+ SortedQueueEntry entry = _sqel.next(_sqel.getHead());
validateEntry(entry, "B", 1);
msg = generateTestMessage(2, "D");
@@ -362,7 +397,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
validateEntry(entry, "D", 2);
}
- private void validateEntry(final SortedQueueEntryImpl entry, final String expectedSortKey, final long expectedMessageId)
+ private void validateEntry(final SortedQueueEntry entry, final String expectedSortKey, final long expectedMessageId)
{
assertEquals("Sorted queue entry value is not as expected",
expectedSortKey, entry.getMessage().getMessageHeader().getHeader("KEY"));
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryImplTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryTest.java
index a84dd6c249..a406c1c26f 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryImplTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryTest.java
@@ -20,21 +20,41 @@
package org.apache.qpid.server.queue;
import java.util.Collections;
+import java.util.UUID;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.virtualhost.VirtualHost;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class SortedQueueEntryImplTest extends QueueEntryImplTestBase
+public class SortedQueueEntryTest extends QueueEntryImplTestBase
{
public final static String keys[] = { "CCC", "AAA", "BBB" };
- private SelfValidatingSortedQueueEntryList queueEntryList = new SelfValidatingSortedQueueEntryList(new MockAMQQueue("test"),"KEY");
+ private SelfValidatingSortedQueueEntryList _queueEntryList;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ mockLogging();
+ SortedQueue queue = new SortedQueue(UUID.randomUUID(), getName(), false, null, false,false, mock(VirtualHost.class), null, "KEY", new QueueEntryListFactory<SortedQueueEntry,SortedQueue,SortedQueueEntryList>()
+ {
+
+ @Override
+ public SortedQueueEntryList createQueueEntryList(final SortedQueue queue)
+ {
+ return new SelfValidatingSortedQueueEntryList(queue, "KEY");
+ }
+ });
+ _queueEntryList = (SelfValidatingSortedQueueEntryList) queue.getEntries();
+ super.setUp();
+ }
public QueueEntryImpl getQueueEntryImpl(int msgId) throws AMQException
{
@@ -48,7 +68,7 @@ public class SortedQueueEntryImplTest extends QueueEntryImplTestBase
final MessageReference reference = mock(MessageReference.class);
when(reference.getMessage()).thenReturn(message);
when(message.newReference()).thenReturn(reference);
- return queueEntryList.add(message);
+ return _queueEntryList.add(message);
}
public void testCompareTo()
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueEntryListTest.java
index ae282d5f37..c053957e2a 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueEntryListTest.java
@@ -23,16 +23,21 @@ package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.Collections;
import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class SimpleQueueEntryListTest extends QueueEntryListTestBase
+public class StandardQueueEntryListTest extends QueueEntryListTestBase<StandardQueueEntry, StandardQueue, StandardQueueEntryList, QueueConsumer<?,StandardQueueEntry, StandardQueue, StandardQueueEntryList>>
{
- private SimpleQueueEntryList _sqel;
+
+ private StandardQueue _testQueue;
+ private StandardQueueEntryList _sqel;
private static final String SCAVENGE_PROP = "qpid.queue.scavenge_count";
private String oldScavengeValue = null;
@@ -41,7 +46,10 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
protected void setUp()
{
oldScavengeValue = System.setProperty(SCAVENGE_PROP, "9");
- _sqel = new SimpleQueueEntryList(_testQueue);
+ _testQueue = new StandardQueue(UUID.randomUUID(),getName(),false,null,false,false,mock(VirtualHost.class),
+ Collections.<String,Object>emptyMap());
+
+ _sqel = _testQueue.getEntries();
for(int i = 1; i <= 100; i++)
{
final ServerMessage message = mock(ServerMessage.class);
@@ -69,17 +77,21 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
}
@Override
- public QueueEntryList getTestList()
+ public StandardQueueEntryList getTestList()
{
return getTestList(false);
}
@Override
- public QueueEntryList getTestList(boolean newList)
+ public StandardQueueEntryList getTestList(boolean newList)
{
if(newList)
{
- return new SimpleQueueEntryList(_testQueue);
+ StandardQueue queue =
+ new StandardQueue(UUID.randomUUID(), getName(), false, null, false, false, mock(VirtualHost.class),
+ Collections.<String, Object>emptyMap());
+
+ return queue.getEntries();
}
else
{
@@ -107,9 +119,15 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
return msg;
}
+ @Override
+ protected StandardQueue getTestQueue()
+ {
+ return _testQueue;
+ }
+
public void testScavenge() throws Exception
{
- SimpleQueueEntryList sqel = new SimpleQueueEntryList(null);
+ OrderedQueueEntryList sqel = new StandardQueueEntryList(null);
ConcurrentHashMap<Integer,QueueEntry> entriesMap = new ConcurrentHashMap<Integer,QueueEntry>();
@@ -126,7 +144,7 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
entriesMap.put(i,bleh);
}
- SimpleQueueEntryImpl head = sqel.getHead();
+ OrderedQueueEntry head = sqel.getHead();
//We shall now delete some specific messages mid-queue that will lead to
//requiring a scavenge once the requested threshold of 9 deletes is passed
@@ -172,10 +190,10 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
return entry.isDeleted() && !wasDeleted;
}
- private void verifyDeletedButPresentBeforeScavenge(SimpleQueueEntryImpl head, long messageId)
+ private void verifyDeletedButPresentBeforeScavenge(OrderedQueueEntry head, long messageId)
{
//Use the head to get the initial entry in the queue
- SimpleQueueEntryImpl entry = head.getNextNode();
+ OrderedQueueEntry entry = head.getNextNode();
for(long i = 1; i < messageId ; i++)
{
@@ -186,10 +204,10 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
assertTrue("Entry should have been deleted", entry.isDeleted());
}
- private void verifyAllDeletedMessagedNotPresent(SimpleQueueEntryImpl head, Map<Integer,QueueEntry> remainingMessages)
+ private void verifyAllDeletedMessagedNotPresent(OrderedQueueEntry head, Map<Integer,QueueEntry> remainingMessages)
{
//Use the head to get the initial entry in the queue
- SimpleQueueEntryImpl entry = head.getNextNode();
+ OrderedQueueEntry entry = head.getNextNode();
assertNotNull("Initial entry should not have been null", entry);
@@ -211,8 +229,8 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
public void testGettingNextElement()
{
final int numberOfEntries = 5;
- final SimpleQueueEntryImpl[] entries = new SimpleQueueEntryImpl[numberOfEntries];
- final SimpleQueueEntryList queueEntryList = new SimpleQueueEntryList(new MockAMQQueue("test"));
+ final OrderedQueueEntry[] entries = new OrderedQueueEntry[numberOfEntries];
+ final OrderedQueueEntryList queueEntryList = getTestList(true);
// create test entries
for(int i = 0; i < numberOfEntries; i++)
@@ -228,7 +246,7 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
// test getNext for not acquired entries
for(int i = 0; i < numberOfEntries; i++)
{
- final SimpleQueueEntryImpl next = entries[i].getNextValidEntry();
+ final OrderedQueueEntry next = entries[i].getNextValidEntry();
if(i < numberOfEntries - 1)
{
@@ -248,7 +266,7 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
entries[2].acquire();
entries[2].delete();
- SimpleQueueEntryImpl next = entries[2].getNextValidEntry();
+ OrderedQueueEntry next = entries[2].getNextValidEntry();
assertEquals("expected forth entry", entries[3], next);
next = next.getNextValidEntry();
assertEquals("expected fifth entry", entries[4], next);
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java
new file mode 100644
index 0000000000..27fac12ac0
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java
@@ -0,0 +1,363 @@
+/*
+ *
+ * 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.queue;
+
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.consumer.MockConsumer;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class StandardQueueTest extends SimpleAMQQueueTestBase<StandardQueueEntry, StandardQueue, StandardQueueEntryList>
+{
+
+ public void testCreationFailsWithNoVhost()
+ {
+ try
+ {
+ setQueue(new StandardQueue(UUIDGenerator.generateRandomUUID(), getQname(), false, getOwner(), false,false, null, getArguments()));
+ assertNull("Queue was created", getQueue());
+ }
+ catch (IllegalArgumentException e)
+ {
+ assertTrue("Exception was not about missing vhost",
+ e.getMessage().contains("Host"));
+ }
+ }
+
+
+ public void testAutoDeleteQueue() throws Exception
+ {
+ getQueue().stop();
+ setQueue(new StandardQueue(UUIDGenerator.generateRandomUUID(), getQname(), false, null, true, false, getVirtualHost(), Collections.<String,Object>emptyMap()));
+ getQueue().setDeleteOnNoConsumers(true);
+
+ ServerMessage message = createMessage(25l);
+ QueueConsumer consumer =
+ getQueue().addConsumer(getConsumerTarget(), null, message.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
+ getQueue().enqueue(message, null);
+ consumer.close();
+ assertTrue("Queue was not deleted when consumer was removed",
+ getQueue().isDeleted());
+ }
+
+ public void testActiveConsumerCount() throws Exception
+ {
+ final StandardQueue queue = new StandardQueue(UUIDGenerator.generateRandomUUID(), "testActiveConsumerCount", false,
+ "testOwner", false, false, getVirtualHost(), null);
+
+ //verify adding an active consumer increases the count
+ final MockConsumer consumer1 = new MockConsumer();
+ consumer1.setActive(true);
+ consumer1.setState(ConsumerTarget.State.ACTIVE);
+ assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount());
+ queue.addConsumer(consumer1,
+ null,
+ createMessage(-1l).getClass(),
+ "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+ assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
+
+ //verify adding an inactive consumer doesn't increase the count
+ final MockConsumer consumer2 = new MockConsumer();
+ consumer2.setActive(false);
+ consumer2.setState(ConsumerTarget.State.SUSPENDED);
+ assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
+ queue.addConsumer(consumer2,
+ null,
+ createMessage(-1l).getClass(),
+ "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+ assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
+
+ //verify behaviour in face of expected state changes:
+
+ //verify a consumer going suspended->active increases the count
+ consumer2.setState(ConsumerTarget.State.ACTIVE);
+ assertEquals("Unexpected active consumer count", 2, queue.getActiveConsumerCount());
+
+ //verify a consumer going active->suspended decreases the count
+ consumer2.setState(ConsumerTarget.State.SUSPENDED);
+ assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
+
+ //verify a consumer going suspended->closed doesn't change the count
+ consumer2.setState(ConsumerTarget.State.CLOSED);
+ assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
+
+ //verify a consumer going active->active doesn't change the count
+ consumer1.setState(ConsumerTarget.State.ACTIVE);
+ assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
+
+ consumer1.setState(ConsumerTarget.State.SUSPENDED);
+ assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount());
+
+ //verify a consumer going suspended->suspended doesn't change the count
+ consumer1.setState(ConsumerTarget.State.SUSPENDED);
+ assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount());
+
+ consumer1.setState(ConsumerTarget.State.ACTIVE);
+ assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
+
+ //verify a consumer going active->closed decreases the count
+ consumer1.setState(ConsumerTarget.State.CLOSED);
+ assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount());
+
+ }
+
+
+ /**
+ * Tests that entry in dequeued state are not enqueued and not delivered to consumer
+ */
+ public void testEnqueueDequeuedEntry()
+ {
+ // create a queue where each even entry is considered a dequeued
+ SimpleAMQQueue queue = new DequeuedQueue(UUIDGenerator.generateRandomUUID(), "test", false,
+ "testOwner", false, false, getVirtualHost(), null);
+ // create a consumer
+ MockConsumer consumer = new MockConsumer();
+
+ // register consumer
+ try
+ {
+ queue.addConsumer(consumer,
+ null,
+ createMessage(-1l).getClass(),
+ "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+ }
+ catch (AMQException e)
+ {
+ fail("Failure to register consumer:" + e.getMessage());
+ }
+
+ // put test messages into a queue
+ putGivenNumberOfMessages(queue, 4);
+
+ // assert received messages
+ List<MessageInstance> messages = consumer.getMessages();
+ assertEquals("Only 2 messages should be returned", 2, messages.size());
+ assertEquals("ID of first message should be 1", 1l,
+ (messages.get(0).getMessage()).getMessageNumber());
+ assertEquals("ID of second message should be 3", 3l,
+ (messages.get(1).getMessage()).getMessageNumber());
+ }
+
+ /**
+ * Tests whether dequeued entry is sent to subscriber in result of
+ * invocation of {@link SimpleAMQQueue#processQueue(QueueRunner)}
+ */
+ public void testProcessQueueWithDequeuedEntry()
+ {
+ // total number of messages to send
+ int messageNumber = 4;
+ int dequeueMessageIndex = 1;
+
+ // create queue with overridden method deliverAsync
+ StandardQueue testQueue = new StandardQueue(UUIDGenerator.generateRandomUUID(), "test",
+ false, "testOwner", false, false, getVirtualHost(), null)
+ {
+ @Override
+ public void deliverAsync(QueueConsumer sub)
+ {
+ // do nothing
+ }
+ };
+
+ // put messages
+ List<StandardQueueEntry> entries = enqueueGivenNumberOfMessages(testQueue, messageNumber);
+
+ // dequeue message
+ dequeueMessage(testQueue, dequeueMessageIndex);
+
+ // latch to wait for message receipt
+ final CountDownLatch latch = new CountDownLatch(messageNumber -1);
+
+ // create a consumer
+ MockConsumer consumer = new MockConsumer()
+ {
+ /**
+ * Send a message and decrement latch
+ * @param entry
+ * @param batch
+ */
+ public void send(MessageInstance entry, boolean batch) throws AMQException
+ {
+ super.send(entry, batch);
+ latch.countDown();
+ }
+ };
+
+ try
+ {
+ // subscribe
+ testQueue.addConsumer(consumer,
+ null,
+ entries.get(0).getMessage().getClass(),
+ "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
+ // process queue
+ testQueue.processQueue(new QueueRunner(testQueue)
+ {
+ public void run()
+ {
+ // do nothing
+ }
+ });
+ }
+ catch (AMQException e)
+ {
+ fail("Failure to process queue:" + e.getMessage());
+ }
+ // wait up to 1 minute for message receipt
+ try
+ {
+ latch.await(1, TimeUnit.MINUTES);
+ }
+ catch (InterruptedException e1)
+ {
+ Thread.currentThread().interrupt();
+ }
+ List<MessageInstance> expected = Arrays.asList((MessageInstance) entries.get(0), entries.get(2), entries.get(3));
+ verifyReceivedMessages(expected, consumer.getMessages());
+ }
+
+
+ private static class DequeuedQueue extends SimpleAMQQueue<DequeuedQueueEntry, DequeuedQueue, DequeuedQueueEntryList>
+ {
+
+ public DequeuedQueue(final UUID id,
+ final String queueName,
+ final boolean durable,
+ final String owner,
+ final boolean autoDelete,
+ final boolean exclusive,
+ final VirtualHost virtualHost,
+ final Map<String, Object> arguments)
+ {
+ super(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, new DequeuedQueueEntryListFactory(), arguments);
+ }
+ }
+ private static class DequeuedQueueEntryListFactory implements QueueEntryListFactory<DequeuedQueueEntry, DequeuedQueue, DequeuedQueueEntryList>
+ {
+ public DequeuedQueueEntryList createQueueEntryList(DequeuedQueue queue)
+ {
+ /**
+ * Override SimpleQueueEntryList to create a dequeued
+ * entries for messages with even id
+ */
+ return new DequeuedQueueEntryList(queue);
+ }
+
+
+ }
+
+ private static class DequeuedQueueEntryList extends OrderedQueueEntryList<DequeuedQueueEntry, DequeuedQueue, DequeuedQueueEntryList>
+ {
+ private static final HeadCreator<DequeuedQueueEntry,DequeuedQueue,DequeuedQueueEntryList> HEAD_CREATOR =
+ new HeadCreator<DequeuedQueueEntry,DequeuedQueue,DequeuedQueueEntryList>()
+ {
+
+ @Override
+ public DequeuedQueueEntry createHead(final DequeuedQueueEntryList list)
+ {
+ return new DequeuedQueueEntry(list);
+ }
+ };
+
+ public DequeuedQueueEntryList(final DequeuedQueue queue)
+ {
+ super(queue, HEAD_CREATOR);
+ }
+
+ /**
+ * Entries with even message id are considered
+ * dequeued!
+ */
+ protected DequeuedQueueEntry createQueueEntry(final ServerMessage message)
+ {
+ return new DequeuedQueueEntry(this, message);
+ }
+
+
+ }
+
+ private static class DequeuedQueueEntry extends OrderedQueueEntry<DequeuedQueueEntry,DequeuedQueue,DequeuedQueueEntryList>
+ {
+
+ private final ServerMessage _message;
+
+ private DequeuedQueueEntry(final DequeuedQueueEntryList queueEntryList)
+ {
+ super(queueEntryList);
+ _message = null;
+ }
+
+ public DequeuedQueueEntry(DequeuedQueueEntryList list, final ServerMessage message)
+ {
+ super(list, message);
+ _message = message;
+ }
+
+ public boolean isDeleted()
+ {
+ return (_message.getMessageNumber() % 2 == 0);
+ }
+
+ public boolean isAvailable()
+ {
+ return !(_message.getMessageNumber() % 2 == 0);
+ }
+
+ @Override
+ public boolean acquire(QueueConsumer<?,DequeuedQueueEntry,DequeuedQueue,DequeuedQueueEntryList> sub)
+ {
+ if(_message.getMessageNumber() % 2 == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return super.acquire(sub);
+ }
+ }
+ }
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
index 3dfe057285..d3ee938586 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
@@ -464,7 +464,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
}
@Override
- public TransactionLogResource getQueue()
+ public TransactionLogResource getResource()
{
return _queue;
}
@@ -505,7 +505,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
{
return false;
}
- if (_queue == null && other.getQueue() != null)
+ if (_queue == null && other.getResource() != null)
{
return false;
}
@@ -513,7 +513,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
{
return false;
}
- return _queue.getId().equals(other.getQueue().getId());
+ return _queue.getId().equals(other.getResource().getId());
}
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java
index 7cc3c50199..daf2640bba 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java
@@ -158,6 +158,12 @@ public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase imple
return _transactionResource;
}
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
+
private static class TestMessage implements EnqueueableMessage
{
private final StoredMessage<?> _handle;
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMessageMetaData.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMessageMetaData.java
index a52b9f8d14..e14b41b221 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMessageMetaData.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMessageMetaData.java
@@ -26,7 +26,6 @@ import java.nio.ByteBuffer;
import org.apache.qpid.framing.EncodingUtils;
import org.apache.qpid.server.plugin.MessageMetaDataType;
-import org.apache.qpid.server.store.StorableMessageMetaData;
import org.apache.qpid.server.util.ByteBufferOutputStream;
public class TestMessageMetaData implements StorableMessageMetaData
@@ -72,7 +71,7 @@ public class TestMessageMetaData implements StorableMessageMetaData
}
@Override
- public int writeToBuffer(int offsetInMetaData, ByteBuffer dest)
+ public int writeToBuffer(ByteBuffer dest)
{
int oldPosition = dest.position();
try
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/SubscriptionListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/SubscriptionListTest.java
deleted file mode 100644
index cd5b178464..0000000000
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/SubscriptionListTest.java
+++ /dev/null
@@ -1,429 +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.server.subscription;
-
-import org.apache.qpid.server.subscription.SubscriptionList.SubscriptionNode;
-import org.apache.qpid.server.subscription.SubscriptionList.SubscriptionNodeIterator;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class SubscriptionListTest extends QpidTestCase
-{
- private SubscriptionList _subList;
- private MockSubscription _sub1;
- private MockSubscription _sub2;
- private MockSubscription _sub3;
- private SubscriptionNode _node;
-
- protected void setUp()
- {
- _subList = new SubscriptionList();
-
- _sub1 = new MockSubscription();
- _sub2 = new MockSubscription();
- _sub3 = new MockSubscription();
-
- _subList.add(_sub1);
- _subList.add(_sub2);
- _subList.add(_sub3);
-
- _node = _subList.getHead();
- }
-
- /**
- * Test that if the first (non-head) node in the list is deleted (but is still present),
- * it is not returned when searching through the list for the next viable node, and the
- * subsequent viable node is returned instead.
- */
- public void testFindNextSkipsFirstDeletedNode()
- {
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub1).delete());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 2nd subscription", _sub2, _node.getSubscription());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 3rd subscription", _sub3, _node.getSubscription());
- }
-
- /**
- * Test that if a central node in the list is deleted (but is still present),
- * it is not returned when searching through the list for the next viable node,
- * and the subsequent viable node is returned instead.
- */
- public void testFindNextSkipsCentralDeletedNode()
- {
- assertNotNull("Returned node should not be null", _node = _node.findNext());
-
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub2).delete());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 3rd subscription", _sub3, _node.getSubscription());
- }
-
- /**
- * Test that if the last node in the list is deleted (but is still present),
- * it is not returned when searching through the list for the next viable node,
- * and null is returned instead.
- */
- public void testFindNextSkipsLastDeletedNode()
- {
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 1st subscription", _sub1, _node.getSubscription());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 2nd subscription", _sub2, _node.getSubscription());
-
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub3).delete());
-
- assertNull("Returned node should be null", _node = _node.findNext());
- }
-
- /**
- * Test that if multiple nodes in the list are deleted (but still present), they
- * are not returned when searching through the list for the next viable node,
- * and the subsequent viable node is returned instead.
- */
- public void testFindNextSkipsMultipleDeletedNode()
- {
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub1).delete());
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub2).delete());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 3rd subscription", _sub3, _node.getSubscription());
- }
-
- /**
- * Test that if a node in the list is marked 'deleted' it is still present in the list
- * until actually removed. counter-test to verify above testing of getNext() method.
- */
- public void testDeletedNodeStillPresent()
- {
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub1).delete());
-
- assertNotNull("Node marked deleted should still be present", getNodeForSubscription(_subList, _sub1));
- assertEquals("All 3 nodes are still expected to be present", 3, countNodes(_subList));
- }
-
- /**
- * Traverses the list nodes in a non-mutating fashion, returning the first node which matches the given
- * Subscription, or null if none is found.
- */
- private SubscriptionNode getNodeForSubscription(final SubscriptionList list, final Subscription sub)
- {
- SubscriptionNode node = list.getHead();
- while (node != null && node.getSubscription() != sub)
- {
- node = node.nextNode();
- }
-
- return node;
- }
-
- /**
- * Counts the number of (non-head) nodes in the list.
- */
- private int countNodes(final SubscriptionList list)
- {
- SubscriptionNode node = list.getHead();
- int count;
- for(count = -1; node != null; count++)
- {
- node = node.nextNode();
- }
-
- return count;
- }
-
- /**
- * Tests that the head is returned as expected, and isn't the node for the first subscription.
- */
- public void testGetHead()
- {
- assertNotNull("List head should be non null", _node);
- assertNotSame("Head should not be node for first subscription",
- _node, getNodeForSubscription(_subList, _sub1));
- }
-
- /**
- * Tests that the size is returned correctly in the face of additions and removals.
- */
- public void testGetSize()
- {
- SubscriptionList subList = new SubscriptionList();
-
- assertEquals("Unexpected size result", 0, subList.size());
-
- Subscription sub1 = new MockSubscription();
- Subscription sub2 = new MockSubscription();
- Subscription sub3 = new MockSubscription();
-
- subList.add(sub1);
- assertEquals("Unexpected size result", 1, subList.size());
-
- subList.add(sub2);
- assertEquals("Unexpected size result", 2, subList.size());
-
- subList.add(sub3);
- assertEquals("Unexpected size result", 3, subList.size());
-
- assertTrue("Removing subscription from list should have succeeded", subList.remove(sub1));
- assertEquals("Unexpected size result", 2, subList.size());
-
- assertTrue("Removing subscription from list should have succeeded", subList.remove(sub2));
- assertEquals("Unexpected size result", 1, subList.size());
-
- assertTrue("Removing subscription from list should have succeeded", subList.remove(sub3));
- assertEquals("Unexpected size result", 0, subList.size());
- }
-
- /**
- * Test that if the first (non-head) node in the list is removed it is no longer
- * present in the node structure of the list at all.
- */
- public void testRemoveFirstNode()
- {
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub1));
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub1));
- assertNull("Should not have been a node present for the removed subscription", getNodeForSubscription(_subList, _sub1));
- assertEquals("Unexpected number of nodes", 2, countNodes(_subList));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub2));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub3));
- }
-
- /**
- * Test that if a central node in the list is removed it is no longer
- * present in the node structure of the list at all.
- */
- public void testRemoveCentralNode()
- {
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub2));
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub2));
- assertNull("Should not have been a node present for the removed subscription", getNodeForSubscription(_subList, _sub2));
- assertEquals("Unexpected number of nodes", 2, countNodes(_subList));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub1));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub3));
- }
-
- /**
- * Test that if the subscription contained in the last node of the list is removed
- * it is no longer present in the node structure of the list at all. However,
- * as the last node in the structure can't actually be removed a dummy will instead
- * be present.
- */
- public void testRemoveLastNode()
- {
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub3));
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub3));
- assertNull("Should not have been a node present for the removed subscription", getNodeForSubscription(_subList, _sub3));
-
- //We actually expect 3 nodes to remain this time, because the last node cant be removed for thread safety reasons,
- //however a dummy final node can be used as substitute to allow removal of the subscription node.
- assertEquals("Unexpected number of nodes", 2 + 1, countNodes(_subList));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub1));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub2));
- }
-
- /**
- * Test that if the subscription not contained in the list is requested to be removed
- * that the removal fails
- */
- public void testRemoveNonexistentNode()
- {
- Subscription sub4 = new MockSubscription();
- assertNull("Should not have been a node present for the subscription", getNodeForSubscription(_subList, sub4));
- assertFalse("Removing subscription node should not have succeeded", _subList.remove(sub4));
- assertEquals("Unexpected number of nodes", 3, countNodes(_subList));
- }
-
- /**
- * Test that if a subscription node which occurs later in the main list than the marked node is
- * removed from the list after the marked node is also removed, then the marker node doesn't
- * serve to retain the subsequent nodes in the list structure (and thus memory) despite their
- * removal.
- */
- public void testDeletedMarkedNodeDoesntLeakSubsequentlyDeletedNodes()
- {
- //get the nodes out the list for the 1st and 3rd subscriptions
- SubscriptionNode sub1Node = getNodeForSubscription(_subList, _sub1);
- assertNotNull("Should have been a node present for the subscription", sub1Node);
- SubscriptionNode sub3Node = getNodeForSubscription(_subList, _sub3);
- assertNotNull("Should have been a node present for the subscription", sub3Node);
-
- //mark the first subscription node
- assertTrue("should have succeeded in updating the marked node",
- _subList.updateMarkedNode(_subList.getMarkedNode(), sub1Node));
-
- //remove the 1st subscription from the list
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub1));
- //verify the 1st subscription is no longer the marker node (replaced by a dummy), or in the main list structure
- assertNotSame("Unexpected marker node", sub1Node, _subList.getMarkedNode());
- assertNull("Should not have been a node present in the list structure for the marked-but-removed sub1 node",
- getNodeForSubscription(_subList, _sub1));
-
- //remove the 2nd subscription from the list
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub2));
-
- //verify the marker node isn't leaking subsequently removed nodes, by ensuring the very next node
- //in its list structure is now the 3rd subscription (since the 2nd was removed too)
- assertEquals("Unexpected next node", sub3Node, _subList.getMarkedNode().nextNode());
-
- //remove the 3rd and final/tail subscription
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub3));
-
- //verify the marker node isn't leaking subsequently removed nodes, by ensuring the very next node
- //in its list structure is now the dummy tail (since the 3rd subscription was removed, and a dummy
- //tail was inserted) and NOT the 3rd sub node.
- assertNotSame("Unexpected next node", sub3Node, _subList.getMarkedNode().nextNode());
- assertTrue("Unexpected next node", _subList.getMarkedNode().nextNode().isDeleted());
- assertNull("Next non-deleted node from the marker should now be the list end, i.e. null", _subList.getMarkedNode().findNext());
- }
-
- /**
- * Test that the marked node 'findNext' behaviour is as expected after a subscription is added
- * to the list following the tail subscription node being removed while it is the marked node.
- * That is, that the new subscriptions node is returned by getMarkedNode().findNext().
- */
- public void testMarkedNodeFindsNewSubscriptionAfterRemovingTailWhilstMarked()
- {
- //get the node out the list for the 3rd subscription
- SubscriptionNode sub3Node = getNodeForSubscription(_subList, _sub3);
- assertNotNull("Should have been a node present for the subscription", sub3Node);
-
- //mark the 3rd subscription node
- assertTrue("should have succeeded in updating the marked node",
- _subList.updateMarkedNode(_subList.getMarkedNode(), sub3Node));
-
- //verify calling findNext on the marked node returns null, i.e. the end of the list has been reached
- assertEquals("Unexpected node after marked node", null, _subList.getMarkedNode().findNext());
-
- //remove the 3rd(marked) subscription from the list
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub3));
-
- //add a new 4th subscription to the list
- Subscription sub4 = new MockSubscription();
- _subList.add(sub4);
-
- //get the node out the list for the 4th subscription
- SubscriptionNode sub4Node = getNodeForSubscription(_subList, sub4);
- assertNotNull("Should have been a node present for the subscription", sub4Node);
-
- //verify the marked node (which is now a dummy substitute for the 3rd subscription) returns
- //the 4th subscriptions node as the next non-deleted node.
- assertEquals("Unexpected next node", sub4Node, _subList.getMarkedNode().findNext());
- }
-
- /**
- * Test that setting the marked node to null doesn't cause problems during remove operations
- */
- public void testRemoveWithNullMarkedNode()
- {
- //set the marker to null
- assertTrue("should have succeeded in updating the marked node",
- _subList.updateMarkedNode(_subList.getMarkedNode(), null));
-
- //remove the 1st subscription from the main list
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub1));
-
- //verify the 1st subscription is no longer in the main list structure
- assertNull("Should not have been a node present in the main list structure for sub1",
- getNodeForSubscription(_subList, _sub1));
- assertEquals("Unexpected number of nodes", 2, countNodes(_subList));
- }
-
- /**
- * Tests that after the first (non-head) node of the list is marked deleted but has not
- * yet been removed, the iterator still skips it.
- */
- public void testIteratorSkipsFirstDeletedNode()
- {
- //'delete' but don't remove the node for the 1st subscription
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub1).delete());
- assertNotNull("Should still have been a node present for the deleted subscription",
- getNodeForSubscription(_subList, _sub1));
-
- SubscriptionNodeIterator iter = _subList.iterator();
-
- //verify the iterator returns the 2nd subscriptions node
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub2, iter.getNode().getSubscription());
-
- //verify the iterator returns the 3rd subscriptions node and not the 2nd.
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub3, iter.getNode().getSubscription());
- }
-
- /**
- * Tests that after a central node of the list is marked deleted but has not yet been removed,
- * the iterator still skips it.
- */
- public void testIteratorSkipsCentralDeletedNode()
- {
- //'delete' but don't remove the node for the 2nd subscription
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub2).delete());
- assertNotNull("Should still have been a node present for the deleted subscription",
- getNodeForSubscription(_subList, _sub2));
-
- SubscriptionNodeIterator iter = _subList.iterator();
-
- //verify the iterator returns the 1st subscriptions node
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub1, iter.getNode().getSubscription());
-
- //verify the iterator returns the 3rd subscriptions node and not the 2nd.
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub3, iter.getNode().getSubscription());
- }
-
- /**
- * Tests that after the last node of the list is marked deleted but has not yet been removed,
- * the iterator still skips it.
- */
- public void testIteratorSkipsDeletedFinalNode()
- {
- //'delete' but don't remove the node for the 3rd subscription
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub3).delete());
- assertNotNull("Should still have been a node present for the deleted 3rd subscription",
- getNodeForSubscription(_subList, _sub3));
-
- SubscriptionNodeIterator iter = _subList.iterator();
-
- //verify the iterator returns the 1st subscriptions node
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub1, iter.getNode().getSubscription());
-
- //verify the iterator returns the 2nd subscriptions node
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub2, iter.getNode().getSubscription());
-
- //verify the iterator can no longer advance and does not return a subscription node
- assertFalse("Iterator should not have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", null, iter.getNode());
- }
-}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java
index 3c66a4c94b..993e9ee4a8 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java
@@ -20,12 +20,13 @@
*/
package org.apache.qpid.server.txn;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.MockAMQQueue;
-import org.apache.qpid.server.queue.MockQueueEntry;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.MockMessageInstance;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.txn.MockStoreTransaction.TransactionState;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -47,7 +48,7 @@ public class AutoCommitTransactionTest extends QpidTestCase
private MessageStore _transactionLog;
private AMQQueue _queue;
private List<AMQQueue> _queues;
- private Collection<QueueEntry> _queueEntries;
+ private Collection<MessageInstance> _queueEntries;
private ServerMessage _message;
private MockAction _action;
private MockStoreTransaction _storeTransaction;
@@ -373,9 +374,9 @@ public class AutoCommitTransactionTest extends QpidTestCase
assertFalse("Rollback action must be fired", _action.isRollbackActionFired());
}
- private Collection<QueueEntry> createTestQueueEntries(boolean[] queueDurableFlags, boolean[] messagePersistentFlags)
+ private Collection<MessageInstance> createTestQueueEntries(boolean[] queueDurableFlags, boolean[] messagePersistentFlags)
{
- Collection<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
+ Collection<MessageInstance> queueEntries = new ArrayList<MessageInstance>();
assertTrue("Boolean arrays must be the same length", queueDurableFlags.length == messagePersistentFlags.length);
@@ -384,7 +385,7 @@ public class AutoCommitTransactionTest extends QpidTestCase
final AMQQueue queue = createTestAMQQueue(queueDurableFlags[i]);
final ServerMessage message = createTestMessage(messagePersistentFlags[i]);
- queueEntries.add(new MockQueueEntry()
+ queueEntries.add(new MockMessageInstance()
{
@Override
@@ -394,7 +395,7 @@ public class AutoCommitTransactionTest extends QpidTestCase
}
@Override
- public AMQQueue getQueue()
+ public TransactionLogResource getOwningResource()
{
return queue;
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java
index f3f5e00346..bdfdb55c7e 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java
@@ -20,12 +20,13 @@
*/
package org.apache.qpid.server.txn;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.MockAMQQueue;
-import org.apache.qpid.server.queue.MockQueueEntry;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.MockMessageInstance;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.txn.MockStoreTransaction.TransactionState;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -46,7 +47,7 @@ public class LocalTransactionTest extends QpidTestCase
private AMQQueue _queue;
private List<AMQQueue> _queues;
- private Collection<QueueEntry> _queueEntries;
+ private Collection<MessageInstance> _queueEntries;
private ServerMessage _message;
private MockAction _action1;
private MockAction _action2;
@@ -597,9 +598,9 @@ public class LocalTransactionTest extends QpidTestCase
assertEquals("Transaction update time should be reset after rollback", 0, _transaction.getTransactionUpdateTime());
}
- private Collection<QueueEntry> createTestQueueEntries(boolean[] queueDurableFlags, boolean[] messagePersistentFlags)
+ private Collection<MessageInstance> createTestQueueEntries(boolean[] queueDurableFlags, boolean[] messagePersistentFlags)
{
- Collection<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
+ Collection<MessageInstance> queueEntries = new ArrayList<MessageInstance>();
assertTrue("Boolean arrays must be the same length", queueDurableFlags.length == messagePersistentFlags.length);
@@ -608,7 +609,7 @@ public class LocalTransactionTest extends QpidTestCase
final AMQQueue queue = createTestAMQQueue(queueDurableFlags[i]);
final ServerMessage message = createTestMessage(messagePersistentFlags[i]);
- queueEntries.add(new MockQueueEntry()
+ queueEntries.add(new MockMessageInstance()
{
@Override
@@ -618,7 +619,7 @@ public class LocalTransactionTest extends QpidTestCase
}
@Override
- public AMQQueue getQueue()
+ public TransactionLogResource getOwningResource()
{
return queue;
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
index a7eb619d21..9671cd7a80 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
@@ -44,8 +44,8 @@ import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.logging.actors.TestLogActor;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.SubjectCreator;
import org.apache.qpid.server.stats.StatisticsGatherer;
@@ -180,9 +180,9 @@ public class BrokerTestHelper
return factory.createExchange("amp.direct", "direct", false, false);
}
- public static SimpleAMQQueue createQueue(String queueName, VirtualHost virtualHost) throws AMQException
+ public static AMQQueue createQueue(String queueName, VirtualHost virtualHost) throws AMQException
{
- SimpleAMQQueue queue = (SimpleAMQQueue) virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), queueName, false, null,
+ AMQQueue queue = virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), queueName, false, null,
false, false, false, Collections.<String, Object>emptyMap());
return queue;
}
diff --git a/qpid/java/broker-plugins/access-control/pom.xml b/qpid/java/broker-plugins/access-control/pom.xml
index c63618380c..0c92129325 100644
--- a/qpid/java/broker-plugins/access-control/pom.xml
+++ b/qpid/java/broker-plugins/access-control/pom.xml
@@ -16,15 +16,19 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-access-control</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Access Control Broker Plug-in</name>
+ <description>Access Control broker plug-in</description>
<properties>
<generated-logmessages-dir>${project.build.directory}/generated-sources/generated-logmessages</generated-logmessages-dir>
@@ -34,29 +38,27 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/pom.xml b/qpid/java/broker-plugins/amqp-0-10-protocol/pom.xml
index 6bfce64240..c2ef3bff33 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/pom.xml
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/pom.xml
@@ -16,50 +16,50 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-amqp-0-10-protocol</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 0-10 Protocol Plug-in</name>
+ <description>AMQP 0-10 protocol broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java
new file mode 100644
index 0000000000..114095bace
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java
@@ -0,0 +1,587 @@
+/*
+ *
+ * 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.protocol.v0_10;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.ChannelMessages;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.plugin.MessageConverter;
+import org.apache.qpid.server.protocol.MessageConverterRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.consumer.AbstractConsumerTarget;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.transport.*;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class ConsumerTarget_0_10 extends AbstractConsumerTarget implements FlowCreditManager.FlowCreditManagerListener
+{
+
+ private static final Option[] BATCHED = new Option[] { Option.BATCH };
+
+ private final AtomicBoolean _deleted = new AtomicBoolean(false);
+ private final String _name;
+
+
+ private FlowCreditManager_0_10 _creditManager;
+
+ private final MessageAcceptMode _acceptMode;
+ private final MessageAcquireMode _acquireMode;
+ private MessageFlowMode _flowMode;
+ private final ServerSession _session;
+ private final AtomicBoolean _stopped = new AtomicBoolean(true);
+
+ private final AtomicLong _unacknowledgedCount = new AtomicLong(0);
+ private final AtomicLong _unacknowledgedBytes = new AtomicLong(0);
+
+ private final Map<String, Object> _arguments;
+ private int _deferredMessageCredit;
+ private long _deferredSizeCredit;
+ private Consumer _consumer;
+
+
+ public ConsumerTarget_0_10(ServerSession session,
+ String name,
+ MessageAcceptMode acceptMode,
+ MessageAcquireMode acquireMode,
+ MessageFlowMode flowMode,
+ FlowCreditManager_0_10 creditManager,
+ Map<String, Object> arguments)
+ {
+ super(State.SUSPENDED);
+ _session = session;
+ _postIdSettingAction = new AddMessageDispositionListenerAction(session);
+ _acceptMode = acceptMode;
+ _acquireMode = acquireMode;
+ _creditManager = creditManager;
+ _flowMode = flowMode;
+ _creditManager.addStateListener(this);
+ _arguments = arguments == null ? Collections.<String, Object> emptyMap() :
+ Collections.<String, Object> unmodifiableMap(arguments);
+ _name = name;
+ }
+
+ public Consumer getConsumer()
+ {
+ return _consumer;
+ }
+
+ public boolean isSuspended()
+ {
+ return getState()!=State.ACTIVE || _deleted.get() || _session.isClosing() || _session.getConnectionModel().isStopped(); // TODO check for Session suspension
+ }
+
+ public boolean close()
+ {
+ boolean closed = false;
+ State state = getState();
+
+ final Consumer consumer = getConsumer();
+ if(consumer != null)
+ {
+ consumer.getSendLock();
+ }
+ try
+ {
+ while(!closed && state != State.CLOSED)
+ {
+ closed = updateState(state, State.CLOSED);
+ if(!closed)
+ {
+ state = getState();
+ }
+ }
+ _creditManager.removeListener(this);
+ }
+ finally
+ {
+ if(consumer != null)
+ {
+ consumer.releaseSendLock();
+ }
+ }
+
+ return closed;
+
+ }
+
+ public void creditStateChanged(boolean hasCredit)
+ {
+
+ if(hasCredit)
+ {
+ if(!updateState(State.SUSPENDED, State.ACTIVE))
+ {
+ // this is a hack to get round the issue of increasing bytes credit
+ getStateListener().stateChanged(this, State.ACTIVE, State.ACTIVE);
+ }
+ }
+ else
+ {
+ updateState(State.ACTIVE, State.SUSPENDED);
+ }
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+
+ public static class AddMessageDispositionListenerAction implements Runnable
+ {
+ private MessageTransfer _xfr;
+ private ServerSession.MessageDispositionChangeListener _action;
+ private ServerSession _session;
+
+ public AddMessageDispositionListenerAction(ServerSession session)
+ {
+ _session = session;
+ }
+
+ public void setXfr(MessageTransfer xfr)
+ {
+ _xfr = xfr;
+ }
+
+ public void setAction(ServerSession.MessageDispositionChangeListener action)
+ {
+ _action = action;
+ }
+
+ public void run()
+ {
+ if(_action != null)
+ {
+ _session.onMessageDispositionChange(_xfr, _action);
+ }
+ }
+ }
+
+ private final AddMessageDispositionListenerAction _postIdSettingAction;
+
+ public void send(final MessageInstance entry, boolean batch) throws AMQException
+ {
+ ServerMessage serverMsg = entry.getMessage();
+
+
+ MessageTransfer xfr;
+
+ DeliveryProperties deliveryProps;
+ MessageProperties messageProps = null;
+
+ MessageTransferMessage msg;
+
+ if(serverMsg instanceof MessageTransferMessage)
+ {
+
+ msg = (MessageTransferMessage) serverMsg;
+
+ }
+ else
+ {
+ MessageConverter converter =
+ MessageConverterRegistry.getConverter(serverMsg.getClass(), MessageTransferMessage.class);
+
+
+ msg = (MessageTransferMessage) converter.convert(serverMsg, _session.getVirtualHost());
+ }
+ DeliveryProperties origDeliveryProps = msg.getHeader() == null ? null : msg.getHeader().getDeliveryProperties();
+ messageProps = msg.getHeader() == null ? null : msg.getHeader().getMessageProperties();
+
+ deliveryProps = new DeliveryProperties();
+ if(origDeliveryProps != null)
+ {
+ if(origDeliveryProps.hasDeliveryMode())
+ {
+ deliveryProps.setDeliveryMode(origDeliveryProps.getDeliveryMode());
+ }
+ if(origDeliveryProps.hasExchange())
+ {
+ deliveryProps.setExchange(origDeliveryProps.getExchange());
+ }
+ if(origDeliveryProps.hasExpiration())
+ {
+ deliveryProps.setExpiration(origDeliveryProps.getExpiration());
+ }
+ if(origDeliveryProps.hasPriority())
+ {
+ deliveryProps.setPriority(origDeliveryProps.getPriority());
+ }
+ if(origDeliveryProps.hasRoutingKey())
+ {
+ deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey());
+ }
+ if(origDeliveryProps.hasTimestamp())
+ {
+ deliveryProps.setTimestamp(origDeliveryProps.getTimestamp());
+ }
+ if(origDeliveryProps.hasTtl())
+ {
+ deliveryProps.setTtl(origDeliveryProps.getTtl());
+ }
+
+
+ }
+
+ deliveryProps.setRedelivered(entry.isRedelivered());
+
+ Header header = new Header(deliveryProps, messageProps, msg.getHeader() == null ? null : msg.getHeader().getNonStandardProperties());
+
+
+ xfr = batch ? new MessageTransfer(getConsumer().getName(),_acceptMode,_acquireMode,header,msg.getBody(), BATCHED)
+ : new MessageTransfer(getConsumer().getName(),_acceptMode,_acquireMode,header,msg.getBody());
+
+ if(_acceptMode == MessageAcceptMode.NONE && _acquireMode != MessageAcquireMode.PRE_ACQUIRED)
+ {
+ xfr.setCompletionListener(new MessageAcceptCompletionListener(this, _session, entry, _flowMode == MessageFlowMode.WINDOW));
+ }
+ else if(_flowMode == MessageFlowMode.WINDOW)
+ {
+ xfr.setCompletionListener(new Method.CompletionListener()
+ {
+ public void onComplete(Method method)
+ {
+ deferredAddCredit(1, entry.getMessage().getSize());
+ }
+ });
+ }
+
+
+ _postIdSettingAction.setXfr(xfr);
+ if(_acceptMode == MessageAcceptMode.EXPLICIT)
+ {
+ _postIdSettingAction.setAction(new ExplicitAcceptDispositionChangeListener(entry, this));
+ }
+ else if(_acquireMode != MessageAcquireMode.PRE_ACQUIRED)
+ {
+ _postIdSettingAction.setAction(new ImplicitAcceptDispositionChangeListener(entry, this));
+ }
+ else
+ {
+ _postIdSettingAction.setAction(null);
+ }
+
+
+ _session.sendMessage(xfr, _postIdSettingAction);
+ entry.incrementDeliveryCount();
+ if(_acceptMode == MessageAcceptMode.NONE && _acquireMode == MessageAcquireMode.PRE_ACQUIRED)
+ {
+ forceDequeue(entry, false);
+ }
+ else if(_acquireMode == MessageAcquireMode.PRE_ACQUIRED)
+ {
+ recordUnacknowledged(entry);
+ }
+
+ }
+
+ void recordUnacknowledged(MessageInstance entry)
+ {
+ _unacknowledgedCount.incrementAndGet();
+ _unacknowledgedBytes.addAndGet(entry.getMessage().getSize());
+ }
+
+ private void deferredAddCredit(final int deferredMessageCredit, final long deferredSizeCredit)
+ {
+ _deferredMessageCredit += deferredMessageCredit;
+ _deferredSizeCredit += deferredSizeCredit;
+
+ }
+
+ public void flushCreditState(boolean strict)
+ {
+ if(strict || !isSuspended() || _deferredMessageCredit >= 200
+ || !(_creditManager instanceof WindowCreditManager)
+ || ((WindowCreditManager)_creditManager).getMessageCreditLimit() < 400 )
+ {
+ _creditManager.restoreCredit(_deferredMessageCredit, _deferredSizeCredit);
+ _deferredMessageCredit = 0;
+ _deferredSizeCredit = 0l;
+ }
+ }
+
+ private void forceDequeue(final MessageInstance entry, final boolean restoreCredit)
+ {
+ AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(_session.getVirtualHost().getMessageStore());
+ dequeueTxn.dequeue(entry.getOwningResource(), entry.getMessage(),
+ new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ if (restoreCredit)
+ {
+ restoreCredit(entry.getMessage());
+ }
+ entry.delete();
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ }
+
+ void reject(final MessageInstance entry)
+ {
+ entry.setRedelivered();
+ entry.routeToAlternate(null, null);
+ if(entry.isAcquiredBy(getConsumer()))
+ {
+ entry.delete();
+ }
+ }
+
+ void release(final MessageInstance entry, final boolean setRedelivered)
+ {
+ if (setRedelivered)
+ {
+ entry.setRedelivered();
+ }
+
+ if (getSessionModel().isClosing() || !setRedelivered)
+ {
+ entry.decrementDeliveryCount();
+ }
+
+ if (isMaxDeliveryLimitReached(entry))
+ {
+ sendToDLQOrDiscard(entry);
+ }
+ else
+ {
+ entry.release();
+ }
+ }
+
+ protected void sendToDLQOrDiscard(MessageInstance entry)
+ {
+ final LogActor logActor = CurrentActor.get();
+ final ServerMessage msg = entry.getMessage();
+
+ int requeues = entry.routeToAlternate(new Action<MessageInstance>()
+ {
+ @Override
+ public void performAction(final MessageInstance requeueEntry)
+ {
+ logActor.message( ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(),
+ requeueEntry.getOwningResource().getName()));
+ }
+ }, null);
+
+ if (requeues == 0)
+ {
+ TransactionLogResource owningResource = entry.getOwningResource();
+ if(owningResource instanceof AMQQueue)
+ {
+ final AMQQueue queue = (AMQQueue)owningResource;
+ final Exchange alternateExchange = queue.getAlternateExchange();
+
+ if(alternateExchange != null)
+ {
+ logActor.message( ChannelMessages.DISCARDMSG_NOROUTE(msg.getMessageNumber(),
+ alternateExchange.getName()));
+ }
+ else
+ {
+ logActor.message(ChannelMessages.DISCARDMSG_NOALTEXCH(msg.getMessageNumber(),
+ queue.getName(),
+ msg.getRoutingKey()));
+ }
+ }
+ }
+ }
+
+ private boolean isMaxDeliveryLimitReached(MessageInstance entry)
+ {
+ final int maxDeliveryLimit = entry.getMaximumDeliveryCount();
+ return (maxDeliveryLimit > 0 && entry.getDeliveryCount() >= maxDeliveryLimit);
+ }
+
+ public void queueDeleted()
+ {
+ _deleted.set(true);
+ }
+
+ public boolean allocateCredit(ServerMessage message)
+ {
+ return _creditManager.useCreditForMessage(message.getSize());
+ }
+
+ public void restoreCredit(ServerMessage message)
+ {
+ _creditManager.restoreCredit(1, message.getSize());
+ }
+
+ public FlowCreditManager_0_10 getCreditManager()
+ {
+ return _creditManager;
+ }
+
+
+ public void stop()
+ {
+ try
+ {
+ getConsumer().getSendLock();
+
+ updateState(State.ACTIVE, State.SUSPENDED);
+ _stopped.set(true);
+ FlowCreditManager_0_10 creditManager = getCreditManager();
+ creditManager.clearCredit();
+ }
+ finally
+ {
+ getConsumer().releaseSendLock();
+ }
+ }
+
+ public void addCredit(MessageCreditUnit unit, long value)
+ {
+ FlowCreditManager_0_10 creditManager = getCreditManager();
+
+ switch (unit)
+ {
+ case MESSAGE:
+
+ creditManager.addCredit(value, 0L);
+ break;
+ case BYTE:
+ creditManager.addCredit(0l, value);
+ break;
+ }
+
+ _stopped.set(false);
+
+ if(creditManager.hasCredit())
+ {
+ updateState(State.SUSPENDED, State.ACTIVE);
+ }
+
+ }
+
+ public void setFlowMode(MessageFlowMode flowMode)
+ {
+
+
+ _creditManager.removeListener(this);
+
+ switch(flowMode)
+ {
+ case CREDIT:
+ _creditManager = new CreditCreditManager(0l,0l);
+ break;
+ case WINDOW:
+ _creditManager = new WindowCreditManager(0l,0l);
+ break;
+ default:
+ throw new RuntimeException("Unknown message flow mode: " + flowMode);
+ }
+ _flowMode = flowMode;
+ updateState(State.ACTIVE, State.SUSPENDED);
+
+ _creditManager.addStateListener(this);
+
+ }
+
+ public boolean isStopped()
+ {
+ return _stopped.get();
+ }
+
+ public void acknowledge(MessageInstance entry)
+ {
+ // TODO Fix Store Context / cleanup
+ if(entry.isAcquiredBy(getConsumer()))
+ {
+ _unacknowledgedBytes.addAndGet(-entry.getMessage().getSize());
+ _unacknowledgedCount.decrementAndGet();
+ entry.delete();
+ }
+ }
+
+ public void flush() throws AMQException
+ {
+ flushCreditState(true);
+ getConsumer().flush();
+ stop();
+ }
+
+ public ServerSession getSessionModel()
+ {
+ return _session;
+ }
+
+ public boolean isDurable()
+ {
+ return false;
+ }
+
+ public Map<String, Object> getArguments()
+ {
+ return _arguments;
+ }
+
+ public void queueEmpty()
+ {
+ }
+
+ public void flushBatched()
+ {
+ _session.getConnection().flush();
+ }
+
+
+ @Override
+ public void consumerAdded(final Consumer sub)
+ {
+ _consumer = sub;
+ }
+
+ @Override
+ public void consumerRemoved(final Consumer sub)
+ {
+ }
+
+ public long getUnacknowledgedBytes()
+ {
+ return _unacknowledgedBytes.longValue();
+ }
+
+ public long getUnacknowledgedMessages()
+ {
+ return _unacknowledgedCount.longValue();
+ }
+}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java
index 4b38b8a1a3..4420709a91 100755
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java
@@ -22,7 +22,7 @@ package org.apache.qpid.server.protocol.v0_10;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.MessageInstance;
class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener
@@ -30,21 +30,20 @@ class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
private static final Logger _logger = Logger.getLogger(ExplicitAcceptDispositionChangeListener.class);
- private final QueueEntry _entry;
- private final Subscription_0_10 _sub;
+ private final MessageInstance _entry;
+ private final ConsumerTarget_0_10 _target;
- public ExplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10)
+ public ExplicitAcceptDispositionChangeListener(MessageInstance entry, ConsumerTarget_0_10 target)
{
_entry = entry;
- _sub = subscription_0_10;
+ _target = target;
}
public void onAccept()
{
- final Subscription_0_10 subscription = getSubscription();
- if(subscription != null && _entry.isAcquiredBy(_sub))
+ if(_target != null && _entry.isAcquiredBy(_target.getConsumer()))
{
- subscription.getSessionModel().acknowledge(subscription, _entry);
+ _target.getSessionModel().acknowledge(_target, _entry);
}
else
{
@@ -55,10 +54,9 @@ class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
public void onRelease(boolean setRedelivered)
{
- final Subscription_0_10 subscription = getSubscription();
- if(subscription != null && _entry.isAcquiredBy(_sub))
+ if(_target != null && _entry.isAcquiredBy(_target.getConsumer()))
{
- subscription.release(_entry, setRedelivered);
+ _target.release(_entry, setRedelivered);
}
else
{
@@ -68,10 +66,9 @@ class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
public void onReject()
{
- final Subscription_0_10 subscription = getSubscription();
- if(subscription != null && _entry.isAcquiredBy(_sub))
+ if(_target != null && _entry.isAcquiredBy(_target.getConsumer()))
{
- subscription.reject(_entry);
+ _target.reject(_entry);
}
else
{
@@ -82,12 +79,8 @@ class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
public boolean acquire()
{
- return _entry.acquire(getSubscription());
+ return _entry.acquire(_target.getConsumer());
}
- private Subscription_0_10 getSubscription()
- {
- return _sub;
- }
}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java
index ce0155b789..c459364dbb 100755
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java
@@ -22,20 +22,20 @@ package org.apache.qpid.server.protocol.v0_10;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.MessageInstance;
class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener
{
private static final Logger _logger = Logger.getLogger(ImplicitAcceptDispositionChangeListener.class);
- private final QueueEntry _entry;
- private Subscription_0_10 _sub;
+ private final MessageInstance _entry;
+ private ConsumerTarget_0_10 _target;
- public ImplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10)
+ public ImplicitAcceptDispositionChangeListener(MessageInstance entry, ConsumerTarget_0_10 target)
{
_entry = entry;
- _sub = subscription_0_10;
+ _target = target;
}
public void onAccept()
@@ -45,9 +45,9 @@ class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
public void onRelease(boolean setRedelivered)
{
- if(_entry.isAcquiredBy(_sub))
+ if(_entry.isAcquiredBy(_target.getConsumer()))
{
- getSubscription().release(_entry, setRedelivered);
+ _target.release(_entry, setRedelivered);
}
else
{
@@ -57,9 +57,9 @@ class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
public void onReject()
{
- if(_entry.isAcquiredBy(_sub))
+ if(_entry.isAcquiredBy(_target.getConsumer()))
{
- getSubscription().reject(_entry);
+ _target.reject(_entry);
}
else
{
@@ -70,19 +70,15 @@ class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
public boolean acquire()
{
- boolean acquired = _entry.acquire(getSubscription());
+ boolean acquired = _entry.acquire(_target.getConsumer());
if(acquired)
{
- getSubscription().recordUnacknowledged(_entry);
+ _target.recordUnacknowledged(_entry);
}
return acquired;
}
- public Subscription_0_10 getSubscription()
- {
- return _sub;
- }
}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java
index f5f2a8d43f..cd1146ac0b 100755
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java
@@ -21,17 +21,17 @@
package org.apache.qpid.server.protocol.v0_10;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.transport.Method;
public class MessageAcceptCompletionListener implements Method.CompletionListener
{
- private final Subscription_0_10 _sub;
- private final QueueEntry _entry;
+ private final ConsumerTarget_0_10 _sub;
+ private final MessageInstance _entry;
private final ServerSession _session;
private boolean _restoreCredit;
- public MessageAcceptCompletionListener(Subscription_0_10 sub, ServerSession session, QueueEntry entry, boolean restoreCredit)
+ public MessageAcceptCompletionListener(ConsumerTarget_0_10 sub, ServerSession session, MessageInstance entry, boolean restoreCredit)
{
super();
_sub = sub;
@@ -44,9 +44,9 @@ public class MessageAcceptCompletionListener implements Method.CompletionListene
{
if(_restoreCredit)
{
- _sub.restoreCredit(_entry);
+ _sub.restoreCredit(_entry.getMessage());
}
- if(_entry.isAcquiredBy(_sub))
+ if(_entry.isAcquiredBy(_sub.getConsumer()))
{
_session.acknowledge(_sub, _entry);
}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java
new file mode 100644
index 0000000000..37bbd810b4
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java
@@ -0,0 +1,156 @@
+/*
+ *
+ * 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.protocol.v0_10;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.plugin.MessageConverter;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageDeliveryPriority;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.typedmessage.TypedBytesContentReader;
+import org.apache.qpid.typedmessage.TypedBytesFormatException;
+
+import java.io.EOFException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+public class MessageConverter_Internal_to_v0_10 implements MessageConverter<InternalMessage, MessageTransferMessage>
+{
+ @Override
+ public Class<InternalMessage> getInputClass()
+ {
+ return InternalMessage.class;
+ }
+
+ @Override
+ public Class<MessageTransferMessage> getOutputClass()
+ {
+ return MessageTransferMessage.class;
+ }
+
+ @Override
+ public MessageTransferMessage convert(InternalMessage serverMsg, VirtualHost vhost)
+ {
+ return new MessageTransferMessage(convertToStoredMessage(serverMsg), null);
+ }
+
+ private StoredMessage<MessageMetaData_0_10> convertToStoredMessage(final InternalMessage serverMsg)
+ {
+ final byte[] messageContent = MessageConverter_v0_10.convertToBody(serverMsg.getMessageBody());
+ final MessageMetaData_0_10 messageMetaData_0_10 = convertMetaData(serverMsg,
+ MessageConverter_v0_10.getBodyMimeType(
+ serverMsg.getMessageBody()),
+ messageContent.length);
+
+ return new StoredMessage<MessageMetaData_0_10>()
+ {
+ @Override
+ public MessageMetaData_0_10 getMetaData()
+ {
+ return messageMetaData_0_10;
+ }
+
+ @Override
+ public long getMessageNumber()
+ {
+ return serverMsg.getMessageNumber();
+ }
+
+ @Override
+ public void addContent(int offsetInMessage, ByteBuffer src)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getContent(int offsetInMessage, ByteBuffer dst)
+ {
+ int size = messageContent.length - offsetInMessage;
+ if(dst.remaining() < size)
+ {
+ size = dst.remaining();
+ }
+ ByteBuffer buf = ByteBuffer.wrap(messageContent, offsetInMessage, size);
+ dst.put(buf);
+ return size;
+ }
+
+ @Override
+ public ByteBuffer getContent(int offsetInMessage, int size)
+ {
+ return ByteBuffer.wrap(messageContent, offsetInMessage, size);
+ }
+
+ @Override
+ public StoreFuture flushToStore()
+ {
+ return StoreFuture.IMMEDIATE_FUTURE;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ private MessageMetaData_0_10 convertMetaData(ServerMessage serverMsg, final String bodyMimeType, final int size)
+ {
+ DeliveryProperties deliveryProps = new DeliveryProperties();
+ MessageProperties messageProps = new MessageProperties();
+
+
+
+ deliveryProps.setExpiration(serverMsg.getExpiration());
+ deliveryProps.setPriority(MessageDeliveryPriority.get(serverMsg.getMessageHeader().getPriority()));
+ deliveryProps.setRoutingKey(serverMsg.getRoutingKey());
+ deliveryProps.setTimestamp(serverMsg.getMessageHeader().getTimestamp());
+
+ messageProps.setContentEncoding(serverMsg.getMessageHeader().getEncoding());
+ messageProps.setContentLength(size);
+ messageProps.setContentType(bodyMimeType);
+ if(serverMsg.getMessageHeader().getCorrelationId() != null)
+ {
+ messageProps.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId().getBytes());
+ }
+
+ Header header = new Header(deliveryProps, messageProps, null);
+ return new MessageMetaData_0_10(header, size, serverMsg.getArrivalTime());
+ }
+
+
+ @Override
+ public String getType()
+ {
+ return "Internal to v0-10";
+ }
+}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java
index 5244a7f51b..32ecc6bd0e 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java
@@ -20,7 +20,14 @@
*/
package org.apache.qpid.server.protocol.v0_10;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Map;
+
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.plugin.MessageConverter;
import org.apache.qpid.server.store.StoreFuture;
@@ -30,9 +37,13 @@ import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.transport.Header;
import org.apache.qpid.transport.MessageDeliveryPriority;
import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.codec.BBEncoder;
public class MessageConverter_v0_10 implements MessageConverter<ServerMessage, MessageTransferMessage>
{
+
+ public static final Charset UTF_8 = Charset.forName("UTF-8");
+
@Override
public Class<ServerMessage> getInputClass()
{
@@ -129,6 +140,79 @@ public class MessageConverter_v0_10 implements MessageConverter<ServerMessage, M
return new MessageMetaData_0_10(header, size, serverMsg.getArrivalTime());
}
+
+ public static byte[] convertToBody(Object object)
+ {
+ if(object instanceof String)
+ {
+ return ((String)object).getBytes(UTF_8);
+ }
+ else if(object instanceof byte[])
+ {
+ return (byte[]) object;
+ }
+ else if(object instanceof Map)
+ {
+ BBEncoder encoder = new BBEncoder(1024);
+ encoder.writeMap((Map)object);
+ ByteBuffer buf = encoder.segment();
+ int remaining = buf.remaining();
+ byte[] data = new byte[remaining];
+ buf.get(data);
+ return data;
+
+ }
+ else if(object instanceof List)
+ {
+ BBEncoder encoder = new BBEncoder(1024);
+ encoder.writeList((List) object);
+ ByteBuffer buf = encoder.segment();
+ int remaining = buf.remaining();
+ byte[] data = new byte[remaining];
+ buf.get(data);
+ return data;
+ }
+ else
+ {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ try
+ {
+ ObjectOutputStream os = new ObjectOutputStream(bytesOut);
+ os.writeObject(object);
+ return bytesOut.toByteArray();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public static String getBodyMimeType(Object object)
+ {
+ if(object instanceof String)
+ {
+ return "text/plain";
+ }
+ else if(object instanceof byte[])
+ {
+ return "application/octet-stream";
+ }
+ else if(object instanceof Map)
+ {
+ return "amqp/map";
+ }
+ else if(object instanceof List)
+ {
+ return "amqp/list";
+ }
+ else
+ {
+ return "application/java-object-stream";
+ }
+ }
+
+
@Override
public String getType()
{
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10_to_Internal.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10_to_Internal.java
new file mode 100644
index 0000000000..bc5f8899f2
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10_to_Internal.java
@@ -0,0 +1,271 @@
+/*
+ *
+ * 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.protocol.v0_10;
+
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.message.internal.InternalMessageMetaData;
+import org.apache.qpid.server.plugin.MessageConverter;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageDeliveryPriority;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.ReplyTo;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.typedmessage.TypedBytesContentReader;
+import org.apache.qpid.typedmessage.TypedBytesFormatException;
+
+import java.io.EOFException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+
+public class MessageConverter_v0_10_to_Internal implements MessageConverter<MessageTransferMessage, InternalMessage>
+{
+ @Override
+ public Class<MessageTransferMessage> getInputClass()
+ {
+ return MessageTransferMessage.class;
+ }
+
+ @Override
+ public Class<InternalMessage> getOutputClass()
+ {
+ return InternalMessage.class;
+ }
+
+ @Override
+ public InternalMessage convert(MessageTransferMessage serverMessage, VirtualHost vhost)
+ {
+ final String mimeType = serverMessage.getMessageHeader().getMimeType();
+ byte[] data = new byte[(int) serverMessage.getSize()];
+ serverMessage.getContent(ByteBuffer.wrap(data), 0);
+
+ Object body = convertMessageBody(mimeType, data);
+ MessageProperties messageProps = serverMessage.getHeader().getMessageProperties();
+ AMQMessageHeader fixedHeader = new DelegatingMessageHeader(serverMessage.getMessageHeader(), messageProps == null ? null : messageProps.getReplyTo());
+ return InternalMessage.convert(serverMessage.getMessageNumber(), serverMessage.isPersistent(), fixedHeader, body);
+ }
+
+ private static class DelegatingMessageHeader implements AMQMessageHeader
+ {
+ private final AMQMessageHeader _delegate;
+ private final ReplyTo _replyTo;
+
+
+ private DelegatingMessageHeader(final AMQMessageHeader delegate, final ReplyTo replyTo)
+ {
+ _delegate = delegate;
+ _replyTo = replyTo;
+ }
+
+ @Override
+ public String getCorrelationId()
+ {
+ return _delegate.getCorrelationId();
+ }
+
+ @Override
+ public long getExpiration()
+ {
+ return _delegate.getExpiration();
+ }
+
+ @Override
+ public String getUserId()
+ {
+ return _delegate.getUserId();
+ }
+
+ @Override
+ public String getAppId()
+ {
+ return _delegate.getAppId();
+ }
+
+ @Override
+ public String getMessageId()
+ {
+ return _delegate.getMessageId();
+ }
+
+ @Override
+ public String getMimeType()
+ {
+ return _delegate.getMimeType();
+ }
+
+ @Override
+ public String getEncoding()
+ {
+ return _delegate.getEncoding();
+ }
+
+ @Override
+ public byte getPriority()
+ {
+ return _delegate.getPriority();
+ }
+
+ @Override
+ public long getTimestamp()
+ {
+ return _delegate.getTimestamp();
+ }
+
+ @Override
+ public String getType()
+ {
+ return _delegate.getType();
+ }
+
+ @Override
+ public String getReplyTo()
+ {
+ return _replyTo == null
+ ? null
+ : _replyTo.getExchange() == null || _replyTo.getExchange().equals("")
+ ? _replyTo.getRoutingKey()
+ : _replyTo.getRoutingKey() == null || _replyTo.getRoutingKey().equals("")
+ ? _replyTo.getExchange()
+ : _replyTo.getExchange() + "/" + _replyTo.getRoutingKey();
+ }
+
+ @Override
+ public Object getHeader(final String name)
+ {
+ return _delegate.getHeader(name);
+ }
+
+ @Override
+ public boolean containsHeaders(final Set<String> names)
+ {
+ return _delegate.containsHeaders(names);
+ }
+
+ @Override
+ public boolean containsHeader(final String name)
+ {
+ return _delegate.containsHeader(name);
+ }
+
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ return _delegate.getHeaderNames();
+ }
+ }
+
+ private static Object convertMessageBody(String mimeType, byte[] data)
+ {
+ if("text/plain".equals(mimeType) || "text/xml".equals(mimeType))
+ {
+ String text = new String(data);
+ return text;
+ }
+ else if("jms/map-message".equals(mimeType))
+ {
+ TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data));
+
+ LinkedHashMap map = new LinkedHashMap();
+ final int entries = reader.readIntImpl();
+ for (int i = 0; i < entries; i++)
+ {
+ try
+ {
+ String propName = reader.readStringImpl();
+ Object value = reader.readObject();
+
+ map.put(propName, value);
+ }
+ catch (EOFException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ catch (TypedBytesFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+
+ }
+
+ return map;
+
+ }
+ else if("amqp/map".equals(mimeType))
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(data));
+ final Map<String,Object> map = decoder.readMap();
+
+ return map;
+
+ }
+ else if("amqp/list".equals(mimeType))
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(data));
+ return decoder.readList();
+ }
+ else if("jms/stream-message".equals(mimeType))
+ {
+ TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data));
+
+ List list = new ArrayList();
+ while (reader.remaining() != 0)
+ {
+ try
+ {
+ list.add(reader.readObject());
+ }
+ catch (TypedBytesFormatException e)
+ {
+ throw new RuntimeException(e); // TODO - Implement
+ }
+ catch (EOFException e)
+ {
+ throw new RuntimeException(e); // TODO - Implement
+ }
+ }
+ return list;
+ }
+ else
+ {
+ return data;
+
+ }
+ }
+
+ @Override
+ public String getType()
+ {
+ return "v0-10 to Internal";
+ }
+}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java
index 2e74621814..687331e51d 100755
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java
@@ -141,7 +141,7 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData
return buf;
}
- public int writeToBuffer(int offsetInMetaData, ByteBuffer dest)
+ public int writeToBuffer(ByteBuffer dest)
{
ByteBuffer buf = _encoded;
@@ -153,7 +153,7 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData
buf = buf.duplicate();
- buf.position(offsetInMetaData);
+ buf.position(0);
if(dest.remaining() < buf.limit())
{
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java
index a15fea1200..c85a415ce5 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java
@@ -282,8 +282,8 @@ public class ServerConnectionDelegate extends ServerDelegate
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)
+ final Collection<ConsumerTarget_0_10> subs = ssn.getSubscriptions();
+ for (ConsumerTarget_0_10 subscription_0_10 : subs)
{
subscription_0_10.stop();
}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java
index bae5616042..87a02b99c1 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java
@@ -46,7 +46,7 @@ import org.apache.qpid.AMQStoreException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.TransactionTimeoutHelper;
import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction;
-import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.logging.LogMessage;
import org.apache.qpid.server.logging.LogSubject;
@@ -55,15 +55,16 @@ import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.logging.messages.ChannelMessages;
import org.apache.qpid.server.logging.subjects.ChannelLogSubject;
import org.apache.qpid.server.message.InstanceProperties;
-import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.CapacityChecker;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.BaseQueue;
-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.store.StoreFuture;
+import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.txn.AlreadyKnownDtxException;
import org.apache.qpid.server.txn.AsyncAutoCommitTransaction;
import org.apache.qpid.server.txn.DistributedTransaction;
@@ -77,6 +78,7 @@ 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.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.*;
import org.slf4j.Logger;
@@ -104,14 +106,7 @@ public class ServerSession extends Session
private final AtomicBoolean _blocking = new AtomicBoolean(false);
private ChannelLogSubject _logSubject;
private final AtomicInteger _outstandingCredit = new AtomicInteger(UNLIMITED_CREDIT);
- private final BaseQueue.PostEnqueueAction _checkCapacityAction = new BaseQueue.PostEnqueueAction()
- {
- @Override
- public void onEnqueue(final QueueEntry entry)
- {
- entry.getQueue().checkCapacity(ServerSession.this);
- }
- };
+ private final CheckCapacityAction _checkCapacityAction = new CheckCapacityAction();
public static interface MessageDispositionChangeListener
{
@@ -126,12 +121,6 @@ public class ServerSession extends Session
}
- public static interface Task
- {
- public void doTask(ServerSession session);
- }
-
-
private final SortedMap<Integer, MessageDispositionChangeListener> _messageDispositionListenerMap =
new ConcurrentSkipListMap<Integer, MessageDispositionChangeListener>();
@@ -142,9 +131,9 @@ public class ServerSession extends Session
private final AtomicLong _txnRejects = new AtomicLong(0);
private final AtomicLong _txnCount = new AtomicLong(0);
- private Map<String, Subscription_0_10> _subscriptions = new ConcurrentHashMap<String, Subscription_0_10>();
+ private Map<String, ConsumerTarget_0_10> _subscriptions = new ConcurrentHashMap<String, ConsumerTarget_0_10>();
- private final List<Task> _taskList = new CopyOnWriteArrayList<Task>();
+ private final List<Action<ServerSession>> _taskList = new CopyOnWriteArrayList<Action<ServerSession>>();
private final TransactionTimeoutHelper _transactionTimeoutHelper;
@@ -194,7 +183,7 @@ public class ServerSession extends Session
public int enqueue(final MessageTransferMessage message,
final InstanceProperties instanceProperties,
- final Exchange exchange)
+ final MessageDestination exchange)
{
if(_outstandingCredit.get() != UNLIMITED_CREDIT
&& _outstandingCredit.decrementAndGet() == (Integer.MAX_VALUE - PRODUCER_CREDIT_TOPUP_THRESHOLD))
@@ -386,9 +375,9 @@ public class ServerSession extends Session
}
_messageDispositionListenerMap.clear();
- for (Task task : _taskList)
+ for (Action<ServerSession> task : _taskList)
{
- task.doTask(this);
+ task.performAction(this);
}
LogMessage operationalLoggingMessage = _forcedCloseLogMessage.get();
@@ -405,9 +394,9 @@ public class ServerSession extends Session
// Broker shouldn't block awaiting close - thus do override this method to do nothing
}
- public void acknowledge(final Subscription_0_10 sub, final QueueEntry entry)
+ public void acknowledge(final ConsumerTarget_0_10 sub, final MessageInstance entry)
{
- _transaction.dequeue(entry.getQueue(), entry.getMessage(),
+ _transaction.dequeue(entry.getOwningResource(), entry.getMessage(),
new ServerTransaction.Action()
{
@@ -426,42 +415,26 @@ public class ServerSession extends Session
});
}
- public Collection<Subscription_0_10> getSubscriptions()
+ public Collection<ConsumerTarget_0_10> getSubscriptions()
{
return _subscriptions.values();
}
- public void register(String destination, Subscription_0_10 sub)
+ public void register(String destination, ConsumerTarget_0_10 sub)
{
_subscriptions.put(destination == null ? NULL_DESTINATION : destination, sub);
}
- public Subscription_0_10 getSubscription(String destination)
+ public ConsumerTarget_0_10 getSubscription(String destination)
{
return _subscriptions.get(destination == null ? NULL_DESTINATION : destination);
}
- public void unregister(Subscription_0_10 sub)
+ public void unregister(ConsumerTarget_0_10 sub)
{
_subscriptions.remove(sub.getName());
- try
- {
- sub.getSendLock();
- AMQQueue queue = sub.getQueue();
- if(queue != null)
- {
- queue.unregisterSubscription(sub);
- }
- }
- catch (AMQException e)
- {
- // TODO
- _logger.error("Failed to unregister subscription :" + e.getMessage(), e);
- }
- finally
- {
- sub.releaseSendLock();
- }
+ sub.close();
+
}
public boolean isTransactional()
@@ -638,12 +611,12 @@ public class ServerSession extends Session
return getConnection().getAuthorizedSubject();
}
- public void addSessionCloseTask(Task task)
+ public void addSessionCloseTask(Action<ServerSession> task)
{
_taskList.add(task);
}
- public void removeSessionCloseTask(Task task)
+ public void removeSessionCloseTask(Action<ServerSession> task)
{
_taskList.remove(task);
}
@@ -829,8 +802,8 @@ public class ServerSession extends Session
void unregisterSubscriptions()
{
- final Collection<Subscription_0_10> subscriptions = getSubscriptions();
- for (Subscription_0_10 subscription_0_10 : subscriptions)
+ final Collection<ConsumerTarget_0_10> subscriptions = getSubscriptions();
+ for (ConsumerTarget_0_10 subscription_0_10 : subscriptions)
{
unregister(subscription_0_10);
}
@@ -838,8 +811,8 @@ public class ServerSession extends Session
void stopSubscriptions()
{
- final Collection<Subscription_0_10> subscriptions = getSubscriptions();
- for (Subscription_0_10 subscription_0_10 : subscriptions)
+ final Collection<ConsumerTarget_0_10> subscriptions = getSubscriptions();
+ for (ConsumerTarget_0_10 subscription_0_10 : subscriptions)
{
subscription_0_10.stop();
}
@@ -848,58 +821,14 @@ public class ServerSession extends Session
public void receivedComplete()
{
- final Collection<Subscription_0_10> subscriptions = getSubscriptions();
- for (Subscription_0_10 subscription_0_10 : subscriptions)
+ final Collection<ConsumerTarget_0_10> subscriptions = getSubscriptions();
+ for (ConsumerTarget_0_10 subscription_0_10 : subscriptions)
{
subscription_0_10.flushCreditState(false);
}
awaitCommandCompletion();
}
- private class PostEnqueueAction implements ServerTransaction.Action
- {
-
- private final MessageReference<MessageTransferMessage> _reference;
- private final List<? extends BaseQueue> _queues;
- private final boolean _transactional;
-
- public PostEnqueueAction(List<? extends BaseQueue> queues, MessageTransferMessage message, final boolean transactional)
- {
- _reference = message.newReference();
- _transactional = transactional;
- _queues = queues;
- }
-
- public void postCommit()
- {
- for(int i = 0; i < _queues.size(); i++)
- {
- try
- {
- BaseQueue queue = _queues.get(i);
- queue.enqueue(_reference.getMessage(), _transactional, null);
- if(queue instanceof AMQQueue)
- {
- ((AMQQueue)queue).checkCapacity(ServerSession.this);
- }
-
- }
- catch (AMQException e)
- {
- // TODO
- throw new RuntimeException(e);
- }
- }
- _reference.release();
- }
-
- public void onRollback()
- {
- // NO-OP
- _reference.release();
- }
- }
-
public int getUnacknowledgedMessageCount()
{
return _messageDispositionListenerMap.size();
@@ -999,4 +928,16 @@ public class ServerSession extends Session
return getId().compareTo(o.getId());
}
+ private class CheckCapacityAction<C extends Consumer> implements Action<MessageInstance<?,C>>
+ {
+ @Override
+ public void performAction(final MessageInstance<?,C> entry)
+ {
+ TransactionLogResource queue = entry.getOwningResource();
+ if(queue instanceof CapacityChecker)
+ {
+ ((CapacityChecker)queue).checkCapacity(ServerSession.this);
+ }
+ }
+ }
}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
index 72cce5e472..d4fb2761a4 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.protocol.v0_10;
+import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.UUID;
import org.apache.log4j.Logger;
@@ -34,7 +35,9 @@ import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.filter.FilterManagerFactory;
import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageDestination;
import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.plugin.ExchangeType;
@@ -45,6 +48,7 @@ import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoreFuture;
import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.txn.AlreadyKnownDtxException;
import org.apache.qpid.server.txn.DtxNotSelectedException;
import org.apache.qpid.server.txn.IncorrectDtxStateException;
@@ -55,6 +59,7 @@ 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.util.Action;
import org.apache.qpid.server.virtualhost.ExchangeExistsException;
import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException;
import org.apache.qpid.server.virtualhost.RequiredExchangeException;
@@ -193,7 +198,7 @@ public class ServerSessionDelegate extends SessionDelegate
String queueName = method.getQueue();
VirtualHost vhost = getVirtualHost(session);
- final AMQQueue queue = vhost.getQueue(queueName);
+ final MessageSource queue = vhost.getMessageSource(queueName);
if(queue == null)
{
@@ -214,9 +219,9 @@ public class ServerSessionDelegate extends SessionDelegate
ServerSession s = (ServerSession) session;
queue.setExclusiveOwningSession(s);
- ((ServerSession) session).addSessionCloseTask(new ServerSession.Task()
+ ((ServerSession) session).addSessionCloseTask(new Action<ServerSession>()
{
- public void doTask(ServerSession session)
+ public void performAction(ServerSession session)
{
if(queue.getExclusiveOwningSession() == session)
{
@@ -228,9 +233,9 @@ public class ServerSessionDelegate extends SessionDelegate
if(queue.getAuthorizationHolder() == null)
{
queue.setAuthorizationHolder(s);
- ((ServerSession) session).addSessionCloseTask(new ServerSession.Task()
+ ((ServerSession) session).addSessionCloseTask(new Action<ServerSession>()
{
- public void doTask(ServerSession session)
+ public void performAction(ServerSession session)
{
if(queue.getAuthorizationHolder() == session)
{
@@ -254,25 +259,42 @@ public class ServerSessionDelegate extends SessionDelegate
return;
}
- Subscription_0_10 sub = new Subscription_0_10((ServerSession)session,
- destination,
- method.getAcceptMode(),
- method.getAcquireMode(),
- MessageFlowMode.WINDOW,
- creditManager,
- filterManager,
- method.getArguments());
+ ConsumerTarget_0_10 target = new ConsumerTarget_0_10((ServerSession)session, destination,
+ method.getAcceptMode(),
+ method.getAcquireMode(),
+ MessageFlowMode.WINDOW,
+ creditManager,
+ method.getArguments()
+ );
- ((ServerSession)session).register(destination, sub);
+ ((ServerSession)session).register(destination, target);
try
{
- queue.registerSubscription(sub, method.getExclusive());
+ EnumSet<Consumer.Option> options = EnumSet.noneOf(Consumer.Option.class);
+ if(method.getAcquireMode() == MessageAcquireMode.PRE_ACQUIRED)
+ {
+ options.add(Consumer.Option.ACQUIRES);
+ }
+ if(method.getAcquireMode() != MessageAcquireMode.NOT_ACQUIRED || method.getAcceptMode() == MessageAcceptMode.EXPLICIT)
+ {
+ options.add(Consumer.Option.SEES_REQUEUES);
+ }
+ if(method.getExclusive())
+ {
+ options.add(Consumer.Option.EXCLUSIVE);
+ }
+ Consumer sub =
+ queue.addConsumer(target,
+ filterManager,
+ MessageTransferMessage.class,
+ destination,
+ options);
}
- catch (AMQQueue.ExistingExclusiveSubscription existing)
+ catch (AMQQueue.ExistingExclusiveConsumer existing)
{
exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an exclusive consumer");
}
- catch (AMQQueue.ExistingSubscriptionPreventsExclusive exclusive)
+ catch (AMQQueue.ExistingConsumerPreventsExclusive exclusive)
{
exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an existing consumer - can't subscribe exclusively");
}
@@ -288,7 +310,7 @@ public class ServerSessionDelegate extends SessionDelegate
@Override
public void messageTransfer(Session ssn, final MessageTransfer xfr)
{
- final Exchange exchange = getExchangeForMessage(ssn, xfr);
+ final MessageDestination exchange = getDestinationForMessage(ssn, xfr);
final DeliveryProperties delvProps = xfr.getHeader() == null ? null : xfr.getHeader().getDeliveryProperties();
if(delvProps != null && delvProps.hasTtl() && !delvProps.hasExpiration())
@@ -307,7 +329,6 @@ public class ServerSessionDelegate extends SessionDelegate
return;
}
- final Exchange exchangeInUse;
final MessageStore store = getVirtualHost(ssn).getMessageStore();
final StoredMessage<MessageMetaData_0_10> storeMessage = createStoreMessage(xfr, messageMetaData, store);
final ServerSession serverSession = (ServerSession) ssn;
@@ -393,7 +414,7 @@ public class ServerSessionDelegate extends SessionDelegate
{
String destination = method.getDestination();
- Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+ ConsumerTarget_0_10 sub = ((ServerSession)session).getSubscription(destination);
if(sub == null)
{
@@ -401,12 +422,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
else
{
- AMQQueue queue = sub.getQueue();
((ServerSession)session).unregister(sub);
- if(!queue.isDeleted() && queue.isExclusive() && queue.getConsumerCount() == 0)
- {
- queue.setAuthorizationHolder(null);
- }
}
}
@@ -415,7 +431,7 @@ public class ServerSessionDelegate extends SessionDelegate
{
String destination = method.getDestination();
- Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+ ConsumerTarget_0_10 sub = ((ServerSession)session).getSubscription(destination);
if(sub == null)
{
@@ -822,24 +838,24 @@ public class ServerSessionDelegate extends SessionDelegate
return getVirtualHost(session).getExchange(exchangeName);
}
- private Exchange getExchangeForMessage(Session ssn, MessageTransfer xfr)
+ private MessageDestination getDestinationForMessage(Session ssn, MessageTransfer xfr)
{
VirtualHost virtualHost = getVirtualHost(ssn);
- Exchange exchange;
+ MessageDestination destination;
if(xfr.hasDestination())
{
- exchange = virtualHost.getExchange(xfr.getDestination());
- if(exchange == null)
+ destination = virtualHost.getMessageDestination(xfr.getDestination());
+ if(destination == null)
{
- exchange = virtualHost.getDefaultExchange();
+ destination = virtualHost.getDefaultExchange();
}
}
else
{
- exchange = virtualHost.getDefaultExchange();
+ destination = virtualHost.getDefaultExchange();
}
- return exchange;
+ return destination;
}
private VirtualHost getVirtualHost(Session session)
@@ -1257,9 +1273,9 @@ public class ServerSessionDelegate extends SessionDelegate
if (autoDelete && exclusive)
{
final AMQQueue q = queue;
- final ServerSession.Task deleteQueueTask = new ServerSession.Task()
+ final Action<ServerSession> deleteQueueTask = new Action<ServerSession>()
{
- public void doTask(ServerSession session)
+ public void performAction(ServerSession session)
{
try
{
@@ -1273,9 +1289,9 @@ public class ServerSessionDelegate extends SessionDelegate
};
final ServerSession s = (ServerSession) session;
s.addSessionCloseTask(deleteQueueTask);
- queue.addQueueDeleteTask(new AMQQueue.Task()
+ queue.addQueueDeleteTask(new Action<AMQQueue>()
{
- public void doTask(AMQQueue queue) throws AMQException
+ public void performAction(AMQQueue queue)
{
s.removeSessionCloseTask(deleteQueueTask);
}
@@ -1284,9 +1300,9 @@ public class ServerSessionDelegate extends SessionDelegate
if (exclusive)
{
final AMQQueue q = queue;
- final ServerSession.Task removeExclusive = new ServerSession.Task()
+ final Action<ServerSession> removeExclusive = new Action<ServerSession>()
{
- public void doTask(ServerSession session)
+ public void performAction(ServerSession session)
{
q.setAuthorizationHolder(null);
q.setExclusiveOwningSession(null);
@@ -1295,9 +1311,9 @@ public class ServerSessionDelegate extends SessionDelegate
final ServerSession s = (ServerSession) session;
q.setExclusiveOwningSession(s);
s.addSessionCloseTask(removeExclusive);
- queue.addQueueDeleteTask(new AMQQueue.Task()
+ queue.addQueueDeleteTask(new Action<AMQQueue>()
{
- public void doTask(AMQQueue queue) throws AMQException
+ public void performAction(AMQQueue queue)
{
s.removeSessionCloseTask(removeExclusive);
}
@@ -1469,7 +1485,7 @@ public class ServerSessionDelegate extends SessionDelegate
{
String destination = sfm.getDestination();
- Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+ ConsumerTarget_0_10 sub = ((ServerSession)session).getSubscription(destination);
if(sub == null)
{
@@ -1486,7 +1502,7 @@ public class ServerSessionDelegate extends SessionDelegate
{
String destination = stop.getDestination();
- Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+ ConsumerTarget_0_10 sub = ((ServerSession)session).getSubscription(destination);
if(sub == null)
{
@@ -1504,7 +1520,7 @@ public class ServerSessionDelegate extends SessionDelegate
{
String destination = flow.getDestination();
- Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+ ConsumerTarget_0_10 sub = ((ServerSession)session).getSubscription(destination);
if(sub == null)
{
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java
deleted file mode 100644
index 357b565365..0000000000
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java
+++ /dev/null
@@ -1,944 +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.server.protocol.v0_10;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.filter.FilterManager;
-import org.apache.qpid.server.flow.FlowCreditManager;
-import org.apache.qpid.server.logging.LogActor;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.GenericActor;
-import org.apache.qpid.server.logging.messages.ChannelMessages;
-import org.apache.qpid.server.logging.messages.SubscriptionMessages;
-import org.apache.qpid.server.model.Queue;
-import org.apache.qpid.server.plugin.MessageConverter;
-import org.apache.qpid.server.protocol.MessageConverterRegistry;
-import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.BaseQueue;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.txn.AutoCommitTransaction;
-import org.apache.qpid.server.txn.ServerTransaction;
-import org.apache.qpid.transport.DeliveryProperties;
-import org.apache.qpid.transport.Header;
-import org.apache.qpid.transport.MessageAcceptMode;
-import org.apache.qpid.transport.MessageAcquireMode;
-import org.apache.qpid.transport.MessageCreditUnit;
-import org.apache.qpid.transport.MessageFlowMode;
-import org.apache.qpid.transport.MessageProperties;
-import org.apache.qpid.transport.MessageTransfer;
-import org.apache.qpid.transport.Method;
-import org.apache.qpid.transport.Option;
-import org.apache.qpid.transport.Struct;
-
-import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.QUEUE_FORMAT;
-import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SUBSCRIPTION_FORMAT;
-
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener, LogSubject
-{
- private final long _subscriptionID;
-
- private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
-
- private static final Option[] BATCHED = new Option[] { Option.BATCH };
-
- private final Lock _stateChangeLock = new ReentrantLock();
-
- private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE);
- private volatile AMQQueue.Context _queueContext;
- private final AtomicBoolean _deleted = new AtomicBoolean(false);
-
-
- private FlowCreditManager_0_10 _creditManager;
-
- private StateListener _stateListener = new StateListener()
- {
-
- public void stateChange(Subscription sub, State oldState, State newState)
- {
- CurrentActor.get().message(SubscriptionMessages.STATE(newState.toString()));
- }
- };
- private AMQQueue _queue;
- private final String _destination;
- private boolean _noLocal;
- private final FilterManager _filters;
- private final MessageAcceptMode _acceptMode;
- private final MessageAcquireMode _acquireMode;
- private MessageFlowMode _flowMode;
- private final ServerSession _session;
- private final AtomicBoolean _stopped = new AtomicBoolean(true);
- private static final Struct[] EMPTY_STRUCT_ARRAY = new Struct[0];
-
- private LogActor _logActor;
- private final Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
- private String _traceExclude;
- private String _trace;
- private final long _createTime = System.currentTimeMillis();
- private final AtomicLong _deliveredCount = new AtomicLong(0);
- private final AtomicLong _deliveredBytes = new AtomicLong(0);
- private final AtomicLong _unacknowledgedCount = new AtomicLong(0);
- private final AtomicLong _unacknowledgedBytes = new AtomicLong(0);
-
- private final Map<String, Object> _arguments;
- private int _deferredMessageCredit;
- private long _deferredSizeCredit;
-
-
- public Subscription_0_10(ServerSession session, String destination, MessageAcceptMode acceptMode,
- MessageAcquireMode acquireMode,
- MessageFlowMode flowMode,
- FlowCreditManager_0_10 creditManager,
- FilterManager filters,Map<String, Object> arguments)
- {
- _subscriptionID = SUB_ID_GENERATOR.getAndIncrement();
- _session = session;
- _postIdSettingAction = new AddMessageDispositionListenerAction(session);
- _destination = destination;
- _acceptMode = acceptMode;
- _acquireMode = acquireMode;
- _creditManager = creditManager;
- _flowMode = flowMode;
- _filters = filters;
- _creditManager.addStateListener(this);
- _arguments = arguments == null ? Collections.<String, Object> emptyMap() :
- Collections.<String, Object> unmodifiableMap(arguments);
- _state.set(_creditManager.hasCredit() ? State.ACTIVE : State.SUSPENDED);
-
- }
-
- public void setNoLocal(boolean noLocal)
- {
- _noLocal = noLocal;
- }
-
- public AMQQueue getQueue()
- {
- return _queue;
- }
-
- public QueueEntry.SubscriptionAcquiredState getOwningState()
- {
- return _owningState;
- }
-
- public void setQueue(AMQQueue queue, boolean exclusive)
- {
- if(getQueue() != null)
- {
- throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue());
- }
- _queue = queue;
-
- _traceExclude = (String) queue.getAttribute(Queue.FEDERATION_EXCLUDES);
- _trace = (String) queue.getAttribute(Queue.FEDERATION_ID);
- String filterLogString = null;
-
- _logActor = GenericActor.getInstance(this);
- if (CurrentActor.get().getRootMessageLogger().isMessageEnabled(_logActor, this, SubscriptionMessages.CREATE_LOG_HIERARCHY))
- {
- filterLogString = getFilterLogString();
- CurrentActor.get().message(this, SubscriptionMessages.CREATE(filterLogString, queue.isDurable() && exclusive,
- filterLogString.length() > 0));
- }
- }
-
- public String getConsumerName()
- {
- return _destination;
- }
-
- public boolean isSuspended()
- {
- return !isActive() || _deleted.get() || _session.isClosing() || _session.getConnectionModel().isStopped(); // TODO check for Session suspension
- }
-
- public boolean hasInterest(QueueEntry entry)
- {
-
-
-
- //check that the message hasn't been rejected
- if (entry.isRejectedBy(getSubscriptionID()))
- {
-
- return false;
- }
-
- if (entry.getMessage() instanceof MessageTransferMessage)
- {
- if(_noLocal)
- {
- Object connectionRef = ((MessageTransferMessage)entry.getMessage()).getConnectionReference();
- if (connectionRef != null && connectionRef == _session.getReference())
- {
- return false;
- }
- }
- }
- else
- {
- // no interest in messages we can't convert
- if(MessageConverterRegistry.getConverter(entry.getMessage().getClass(), MessageTransferMessage.class)==null)
- {
- return false;
- }
- }
-
-
- return checkFilters(entry);
-
-
- }
-
- private boolean checkFilters(QueueEntry entry)
- {
- return (_filters == null) || _filters.allAllow(entry.asFilterable());
- }
-
- public boolean isClosed()
- {
- return getState() == State.CLOSED;
- }
-
- public boolean isBrowser()
- {
- return _acquireMode == MessageAcquireMode.NOT_ACQUIRED;
- }
-
- public boolean seesRequeues()
- {
- return _acquireMode != MessageAcquireMode.NOT_ACQUIRED || _acceptMode == MessageAcceptMode.EXPLICIT;
- }
-
- public void close()
- {
- boolean closed = false;
- State state = getState();
-
- _stateChangeLock.lock();
- try
- {
- while(!closed && state != State.CLOSED)
- {
- closed = _state.compareAndSet(state, State.CLOSED);
- if(!closed)
- {
- state = getState();
- }
- else
- {
- _stateListener.stateChange(this,state, State.CLOSED);
- }
- }
- _creditManager.removeListener(this);
- CurrentActor.get().message(getLogSubject(), SubscriptionMessages.CLOSE());
- }
- finally
- {
- _stateChangeLock.unlock();
- }
-
-
-
- }
-
- public Long getDelivered()
- {
- return _deliveredCount.get();
- }
-
- public void creditStateChanged(boolean hasCredit)
- {
-
- if(hasCredit)
- {
- if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE))
- {
- _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE);
- }
- else
- {
- // this is a hack to get round the issue of increasing bytes credit
- _stateListener.stateChange(this, State.ACTIVE, State.ACTIVE);
- }
- }
- else
- {
- if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
- {
- _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
- }
- }
- }
-
-
- public static class AddMessageDispositionListenerAction implements Runnable
- {
- private MessageTransfer _xfr;
- private ServerSession.MessageDispositionChangeListener _action;
- private ServerSession _session;
-
- public AddMessageDispositionListenerAction(ServerSession session)
- {
- _session = session;
- }
-
- public void setXfr(MessageTransfer xfr)
- {
- _xfr = xfr;
- }
-
- public void setAction(ServerSession.MessageDispositionChangeListener action)
- {
- _action = action;
- }
-
- public void run()
- {
- if(_action != null)
- {
- _session.onMessageDispositionChange(_xfr, _action);
- }
- }
- }
-
- private final AddMessageDispositionListenerAction _postIdSettingAction;
-
- public void send(final QueueEntry entry, boolean batch) throws AMQException
- {
- ServerMessage serverMsg = entry.getMessage();
-
-
- MessageTransfer xfr;
-
- DeliveryProperties deliveryProps;
- MessageProperties messageProps = null;
-
- MessageTransferMessage msg;
-
- if(serverMsg instanceof MessageTransferMessage)
- {
-
- msg = (MessageTransferMessage) serverMsg;
-
- }
- else
- {
- MessageConverter converter =
- MessageConverterRegistry.getConverter(serverMsg.getClass(), MessageTransferMessage.class);
-
-
- msg = (MessageTransferMessage) converter.convert(serverMsg, getQueue().getVirtualHost());
- }
- DeliveryProperties origDeliveryProps = msg.getHeader() == null ? null : msg.getHeader().getDeliveryProperties();
- messageProps = msg.getHeader() == null ? null : msg.getHeader().getMessageProperties();
-
- deliveryProps = new DeliveryProperties();
- if(origDeliveryProps != null)
- {
- if(origDeliveryProps.hasDeliveryMode())
- {
- deliveryProps.setDeliveryMode(origDeliveryProps.getDeliveryMode());
- }
- if(origDeliveryProps.hasExchange())
- {
- deliveryProps.setExchange(origDeliveryProps.getExchange());
- }
- if(origDeliveryProps.hasExpiration())
- {
- deliveryProps.setExpiration(origDeliveryProps.getExpiration());
- }
- if(origDeliveryProps.hasPriority())
- {
- deliveryProps.setPriority(origDeliveryProps.getPriority());
- }
- if(origDeliveryProps.hasRoutingKey())
- {
- deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey());
- }
- if(origDeliveryProps.hasTimestamp())
- {
- deliveryProps.setTimestamp(origDeliveryProps.getTimestamp());
- }
- if(origDeliveryProps.hasTtl())
- {
- deliveryProps.setTtl(origDeliveryProps.getTtl());
- }
-
-
- }
-
- deliveryProps.setRedelivered(entry.isRedelivered());
-
- if(_trace != null && messageProps == null)
- {
- messageProps = new MessageProperties();
- }
-
- Header header = new Header(deliveryProps, messageProps, msg.getHeader() == null ? null : msg.getHeader().getNonStandardProperties());
-
-
- xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody(), BATCHED)
- : new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody());
-
- boolean excludeDueToFederation = false;
-
- if(_trace != null)
- {
- if(!messageProps.hasApplicationHeaders())
- {
- messageProps.setApplicationHeaders(new HashMap<String,Object>());
- }
- Map<String,Object> appHeaders = messageProps.getApplicationHeaders();
- String trace = (String) appHeaders.get("x-qpid.trace");
- if(trace == null)
- {
- trace = _trace;
- }
- else
- {
- if(_traceExclude != null)
- {
- excludeDueToFederation = Arrays.asList(trace.split(",")).contains(_traceExclude);
- }
- trace+=","+_trace;
- }
- appHeaders.put("x-qpid.trace",trace);
- }
-
- if(!excludeDueToFederation)
- {
- if(_acceptMode == MessageAcceptMode.NONE && _acquireMode != MessageAcquireMode.PRE_ACQUIRED)
- {
- xfr.setCompletionListener(new MessageAcceptCompletionListener(this, _session, entry, _flowMode == MessageFlowMode.WINDOW));
- }
- else if(_flowMode == MessageFlowMode.WINDOW)
- {
- xfr.setCompletionListener(new Method.CompletionListener()
- {
- public void onComplete(Method method)
- {
- deferredAddCredit(1, entry.getSize());
- }
- });
- }
-
-
- _postIdSettingAction.setXfr(xfr);
- if(_acceptMode == MessageAcceptMode.EXPLICIT)
- {
- _postIdSettingAction.setAction(new ExplicitAcceptDispositionChangeListener(entry, this));
- }
- else if(_acquireMode != MessageAcquireMode.PRE_ACQUIRED)
- {
- _postIdSettingAction.setAction(new ImplicitAcceptDispositionChangeListener(entry, this));
- }
- else
- {
- _postIdSettingAction.setAction(null);
- }
-
-
- _session.sendMessage(xfr, _postIdSettingAction);
- entry.incrementDeliveryCount();
- _deliveredCount.incrementAndGet();
- _deliveredBytes.addAndGet(entry.getSize());
- if(_acceptMode == MessageAcceptMode.NONE && _acquireMode == MessageAcquireMode.PRE_ACQUIRED)
- {
- forceDequeue(entry, false);
- }
- else if(_acquireMode == MessageAcquireMode.PRE_ACQUIRED)
- {
- recordUnacknowledged(entry);
- }
- }
- else
- {
- forceDequeue(entry, _flowMode == MessageFlowMode.WINDOW);
-
- }
- }
-
- void recordUnacknowledged(QueueEntry entry)
- {
- _unacknowledgedCount.incrementAndGet();
- _unacknowledgedBytes.addAndGet(entry.getSize());
- }
-
- private void deferredAddCredit(final int deferredMessageCredit, final long deferredSizeCredit)
- {
- _deferredMessageCredit += deferredMessageCredit;
- _deferredSizeCredit += deferredSizeCredit;
-
- }
-
- public void flushCreditState(boolean strict)
- {
- if(strict || !isSuspended() || _deferredMessageCredit >= 200
- || !(_creditManager instanceof WindowCreditManager)
- || ((WindowCreditManager)_creditManager).getMessageCreditLimit() < 400 )
- {
- _creditManager.restoreCredit(_deferredMessageCredit, _deferredSizeCredit);
- _deferredMessageCredit = 0;
- _deferredSizeCredit = 0l;
- }
- }
-
- private void forceDequeue(final QueueEntry entry, final boolean restoreCredit)
- {
- AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore());
- dequeueTxn.dequeue(entry.getQueue(), entry.getMessage(),
- new ServerTransaction.Action()
- {
- public void postCommit()
- {
- if (restoreCredit)
- {
- restoreCredit(entry);
- }
- entry.delete();
- }
-
- public void onRollback()
- {
-
- }
- });
- }
-
- void reject(final QueueEntry entry)
- {
- entry.setRedelivered();
- entry.routeToAlternate(null, null);
- if(entry.isAcquiredBy(this))
- {
- entry.delete();
- }
- }
-
- void release(final QueueEntry entry, final boolean setRedelivered)
- {
- if (setRedelivered)
- {
- entry.setRedelivered();
- }
-
- if (getSessionModel().isClosing() || !setRedelivered)
- {
- entry.decrementDeliveryCount();
- }
-
- if (isMaxDeliveryLimitReached(entry))
- {
- sendToDLQOrDiscard(entry);
- }
- else
- {
- entry.release();
- }
- }
-
- protected void sendToDLQOrDiscard(QueueEntry entry)
- {
- final LogActor logActor = CurrentActor.get();
- final ServerMessage msg = entry.getMessage();
-
- int requeues = entry.routeToAlternate(new BaseQueue.PostEnqueueAction()
- {
- @Override
- public void onEnqueue(final QueueEntry requeueEntry)
- {
- logActor.message( ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(),
- requeueEntry.getQueue().getName()));
- }
- }, null);
-
- if (requeues == 0)
- {
- final AMQQueue queue = entry.getQueue();
- final Exchange alternateExchange = queue.getAlternateExchange();
-
- if(alternateExchange != null)
- {
- logActor.message( ChannelMessages.DISCARDMSG_NOROUTE(msg.getMessageNumber(),
- alternateExchange.getName()));
- }
- else
- {
- logActor.message(ChannelMessages.DISCARDMSG_NOALTEXCH(msg.getMessageNumber(),
- queue.getName(),
- msg.getRoutingKey()));
- }
- }
- }
-
- private boolean isMaxDeliveryLimitReached(QueueEntry entry)
- {
- final int maxDeliveryLimit = entry.getQueue().getMaximumDeliveryCount();
- return (maxDeliveryLimit > 0 && entry.getDeliveryCount() >= maxDeliveryLimit);
- }
-
- public void queueDeleted(AMQQueue queue)
- {
- _deleted.set(true);
- }
-
- public boolean wouldSuspend(QueueEntry entry)
- {
- return !_creditManager.useCreditForMessage(entry.getMessage().getSize());
- }
-
- public boolean trySendLock()
- {
- return _stateChangeLock.tryLock();
- }
-
-
- public void getSendLock()
- {
- _stateChangeLock.lock();
- }
-
- public void releaseSendLock()
- {
- _stateChangeLock.unlock();
- }
-
- public void restoreCredit(QueueEntry queueEntry)
- {
- _creditManager.restoreCredit(1, queueEntry.getSize());
- }
-
- public void onDequeue(QueueEntry queueEntry)
- {
- // no-op for 0-10, credit restored by completing command.
- }
-
- public void releaseQueueEntry(QueueEntry queueEntry)
- {
- // no-op for 0-10, credit restored by completing command.
- }
-
- public void setStateListener(StateListener listener)
- {
- _stateListener = listener;
- }
-
- public State getState()
- {
- return _state.get();
- }
-
- public AMQQueue.Context getQueueContext()
- {
- return _queueContext;
- }
-
- public void setQueueContext(AMQQueue.Context queueContext)
- {
- _queueContext = queueContext;
- }
-
- public boolean isActive()
- {
- return getState() == State.ACTIVE;
- }
-
- public void set(String key, Object value)
- {
- _properties.put(key, value);
- }
-
- public Object get(String key)
- {
- return _properties.get(key);
- }
-
-
- public FlowCreditManager_0_10 getCreditManager()
- {
- return _creditManager;
- }
-
-
- public void stop()
- {
- try
- {
- getSendLock();
-
- if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
- {
- _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
- }
- _stopped.set(true);
- FlowCreditManager_0_10 creditManager = getCreditManager();
- creditManager.clearCredit();
- }
- finally
- {
- releaseSendLock();
- }
- }
-
- public void addCredit(MessageCreditUnit unit, long value)
- {
- FlowCreditManager_0_10 creditManager = getCreditManager();
-
- switch (unit)
- {
- case MESSAGE:
-
- creditManager.addCredit(value, 0L);
- break;
- case BYTE:
- creditManager.addCredit(0l, value);
- break;
- }
-
- _stopped.set(false);
-
- if(creditManager.hasCredit())
- {
- if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE))
- {
- _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE);
- }
- }
-
- }
-
- public void setFlowMode(MessageFlowMode flowMode)
- {
-
-
- _creditManager.removeListener(this);
-
- switch(flowMode)
- {
- case CREDIT:
- _creditManager = new CreditCreditManager(0l,0l);
- break;
- case WINDOW:
- _creditManager = new WindowCreditManager(0l,0l);
- break;
- default:
- throw new RuntimeException("Unknown message flow mode: " + flowMode);
- }
- _flowMode = flowMode;
- if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
- {
- _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
- }
-
- _creditManager.addStateListener(this);
-
- }
-
- public boolean isStopped()
- {
- return _stopped.get();
- }
-
- public boolean acquires()
- {
- return _acquireMode == MessageAcquireMode.PRE_ACQUIRED;
- }
-
- public void acknowledge(QueueEntry entry)
- {
- // TODO Fix Store Context / cleanup
- if(entry.isAcquiredBy(this))
- {
- _unacknowledgedBytes.addAndGet(-entry.getSize());
- _unacknowledgedCount.decrementAndGet();
- entry.delete();
- }
- }
-
- public void flush() throws AMQException
- {
- flushCreditState(true);
- _queue.flushSubscription(this);
- stop();
- }
-
- public long getSubscriptionID()
- {
- return _subscriptionID;
- }
-
- public LogActor getLogActor()
- {
- return _logActor;
- }
-
- public boolean isTransient()
- {
- return false;
- }
-
- public ServerSession getSessionModel()
- {
- return _session;
- }
-
- public boolean isBrowsing()
- {
- return _acquireMode == MessageAcquireMode.NOT_ACQUIRED;
- }
-
- public boolean isExclusive()
- {
- return getQueue().hasExclusiveSubscriber();
- }
-
- public boolean isDurable()
- {
- return false;
- }
-
-
- public boolean isExplicitAcknowledge()
- {
- return _acceptMode == MessageAcceptMode.EXPLICIT;
- }
-
- public String getCreditMode()
- {
- return _flowMode.toString();
- }
-
- public String getName()
- {
- return _destination;
- }
-
- public Map<String, Object> getArguments()
- {
- return _arguments;
- }
-
- public boolean isSessionTransactional()
- {
- return _session.isTransactional();
- }
-
- public void queueEmpty()
- {
- }
-
- public long getCreateTime()
- {
- return _createTime;
- }
-
- public String toLogString()
- {
- String queueInfo = MessageFormat.format(QUEUE_FORMAT, _queue.getVirtualHost().getName(),
- _queue.getName());
- String result = "[" + MessageFormat.format(SUBSCRIPTION_FORMAT, getSubscriptionID()) + "("
- // queueString is "vh(/{0})/qu({1}) " so need to trim
- + queueInfo.substring(0, queueInfo.length() - 1) + ")" + "] ";
- return result;
- }
-
- private String getFilterLogString()
- {
- StringBuilder filterLogString = new StringBuilder();
- String delimiter = ", ";
- boolean hasEntries = false;
- if (_filters != null && _filters.hasFilters())
- {
- filterLogString.append(_filters.toString());
- hasEntries = true;
- }
-
- if (isBrowser())
- {
- if (hasEntries)
- {
- filterLogString.append(delimiter);
- }
- filterLogString.append("Browser");
- hasEntries = true;
- }
-
- if (isDurable())
- {
- if (hasEntries)
- {
- filterLogString.append(delimiter);
- }
- filterLogString.append("Durable");
- hasEntries = true;
- }
-
- return filterLogString.toString();
- }
-
- public LogSubject getLogSubject()
- {
- return (LogSubject) this;
- }
-
-
- public void flushBatched()
- {
- _session.getConnection().flush();
- }
-
- public long getBytesOut()
- {
- return _deliveredBytes.longValue();
- }
-
- public long getMessagesOut()
- {
- return _deliveredCount.longValue();
- }
-
- public long getUnacknowledgedBytes()
- {
- return _unacknowledgedBytes.longValue();
- }
-
- public long getUnacknowledgedMessages()
- {
- return _unacknowledgedCount.longValue();
- }
-}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter
index 995b0fabdc..dd115905a4 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter
@@ -17,3 +17,5 @@
# under the License.
#
org.apache.qpid.server.protocol.v0_10.MessageConverter_v0_10
+org.apache.qpid.server.protocol.v0_10.MessageConverter_Internal_to_v0_10
+org.apache.qpid.server.protocol.v0_10.MessageConverter_v0_10_to_Internal
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/pom.xml b/qpid/java/broker-plugins/amqp-0-8-protocol/pom.xml
index 0d8c8be3dd..3bbd624e65 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/pom.xml
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/pom.xml
@@ -16,43 +16,45 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-amqp-0-8-protocol</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 0-8 Protocol Broker Plug-in</name>
+ <description>AMQP 0-8, 0-9 and 0-9-1 protocol broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
index c6d4151628..8becdf853b 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
@@ -21,19 +21,7 @@
package org.apache.qpid.server.protocol.v0_8;
import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.UUID;
+import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
@@ -42,6 +30,7 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.framing.AMQMethodBody;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
@@ -55,6 +44,10 @@ import org.apache.qpid.server.TransactionTimeoutHelper;
import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction;
import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.filter.FilterManager;
+import org.apache.qpid.server.filter.FilterManagerFactory;
+import org.apache.qpid.server.filter.FilterSupport;
+import org.apache.qpid.server.filter.SimpleFilterManager;
import org.apache.qpid.server.flow.FlowCreditManager;
import org.apache.qpid.server.flow.Pre0_10CreditManager;
import org.apache.qpid.server.logging.LogActor;
@@ -66,25 +59,28 @@ import org.apache.qpid.server.logging.messages.ChannelMessages;
import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.logging.subjects.ChannelLogSubject;
import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.protocol.CapacityChecker;
import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoreFuture;
import org.apache.qpid.server.store.StoredMessage;
-import org.apache.qpid.server.subscription.ClientDeliveryMethod;
-import org.apache.qpid.server.subscription.RecordDeliveryMethod;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.txn.AsyncAutoCommitTransaction;
import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.LocalTransaction.ActivityTimeAccessor;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.TransportException;
@@ -122,7 +118,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
private IncomingMessage _currentMessage;
/** Maps from consumer tag to subscription instance. Allows us to unsubscribe from a queue. */
- private final Map<AMQShortString, Subscription> _tag2SubscriptionMap = new HashMap<AMQShortString, Subscription>();
+ private final Map<AMQShortString, ConsumerTarget_0_8> _tag2SubscriptionTargetMap = new HashMap<AMQShortString, ConsumerTarget_0_8>();
private final MessageStore _messageStore;
@@ -155,7 +151,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
private volatile boolean _rollingBack;
private static final Runnable NULL_TASK = new Runnable() { public void run() {} };
- private List<QueueEntry> _resendList = new ArrayList<QueueEntry>();
+ private List<MessageInstance> _resendList = new ArrayList<MessageInstance>();
private static final
AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible.");
private long _createTime = System.currentTimeMillis();
@@ -266,7 +262,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
return _channelId;
}
- public void setPublishFrame(MessagePublishInfo info, final Exchange e) throws AMQSecurityException
+ public void setPublishFrame(MessagePublishInfo info, final MessageDestination e) throws AMQSecurityException
{
String routingKey = info.getRoutingKey() == null ? null : info.getRoutingKey().asString();
SecurityManager securityManager = getVirtualHost().getSecurityManager();
@@ -275,7 +271,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
throw new AMQSecurityException("Permission denied: " + e.getName());
}
_currentMessage = new IncomingMessage(info);
- _currentMessage.setExchange(e);
+ _currentMessage.setMessageDestination(e);
}
public void publishContentHeader(ContentHeaderBody contentHeaderBody)
@@ -360,7 +356,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
}
};
- int enqueues = _currentMessage.getExchange().send(amqMessage, instanceProperties, _transaction,
+ int enqueues = _currentMessage.getDestination().send(amqMessage, instanceProperties, _transaction,
immediate ? _immediateAction : _capacityCheckAction);
if(enqueues == 0)
{
@@ -497,41 +493,64 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
}
- public Subscription getSubscription(AMQShortString subscription)
+ public Consumer getSubscription(AMQShortString tag)
{
- return _tag2SubscriptionMap.get(subscription);
+ final ConsumerTarget_0_8 target = _tag2SubscriptionTargetMap.get(tag);
+ return target == null ? null : target.getConsumer();
}
/**
* Subscribe to a queue. We register all subscriptions in the channel so that if the channel is closed we can clean
* up all subscriptions, even if the client does not explicitly unsubscribe from all queues.
*
+ *
* @param tag the tag chosen by the client (if null, server will generate one)
- * @param queue the queue to subscribe to
+ * @param source the queue to subscribe to
* @param acks Are acks enabled for this subscriber
* @param filters Filters to apply to this subscriber
*
- * @param noLocal Flag stopping own messages being received.
* @param exclusive Flag requesting exclusive access to the queue
* @return the consumer tag. This is returned to the subscriber and used in subsequent unsubscribe requests
*
* @throws AMQException if something goes wrong
*/
- public AMQShortString subscribeToQueue(AMQShortString tag, AMQQueue queue, boolean acks,
- FieldTable filters, boolean noLocal, boolean exclusive) throws AMQException
+ public AMQShortString consumeFromSource(AMQShortString tag, MessageSource source, boolean acks,
+ FieldTable filters, boolean exclusive, boolean noLocal) throws AMQException
{
if (tag == null)
{
tag = new AMQShortString("sgen_" + getNextConsumerTag());
}
- if (_tag2SubscriptionMap.containsKey(tag))
+ if (_tag2SubscriptionTargetMap.containsKey(tag))
{
throw new AMQException("Consumer already exists with same tag: " + tag);
}
- Subscription subscription =
- SubscriptionFactoryImpl.INSTANCE.createSubscription(_channelId, _session, tag, acks, filters, noLocal, _creditManager);
+ ConsumerTarget_0_8 target;
+ EnumSet<Consumer.Option> options = EnumSet.noneOf(Consumer.Option.class);
+
+ if(filters != null && Boolean.TRUE.equals(filters.get(AMQPFilterTypes.NO_CONSUME.getValue())))
+ {
+ target = ConsumerTarget_0_8.createBrowserTarget(this, tag, filters, _creditManager);
+ }
+ else if(acks)
+ {
+ target = ConsumerTarget_0_8.createAckTarget(this, tag, filters, _creditManager);
+ options.add(Consumer.Option.ACQUIRES);
+ options.add(Consumer.Option.SEES_REQUEUES);
+ }
+ else
+ {
+ target = ConsumerTarget_0_8.createNoAckTarget(this, tag, filters, _creditManager);
+ options.add(Consumer.Option.ACQUIRES);
+ options.add(Consumer.Option.SEES_REQUEUES);
+ }
+
+ if(exclusive)
+ {
+ options.add(Consumer.Option.EXCLUSIVE);
+ }
// So to keep things straight we put before the call and catch all exceptions from the register and tidy up.
@@ -539,20 +558,34 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
// so calling _cT2QM.remove before we have done put which was after the register succeeded.
// So to keep things straight we put before the call and catch all exceptions from the register and tidy up.
- _tag2SubscriptionMap.put(tag, subscription);
+ _tag2SubscriptionTargetMap.put(tag, target);
try
{
- queue.registerSubscription(subscription, exclusive);
+ FilterManager filterManager = FilterManagerFactory.createManager(FieldTable.convertToMap(filters));
+ if(noLocal)
+ {
+ if(filterManager == null)
+ {
+ filterManager = new SimpleFilterManager();
+ }
+ filterManager.add(new FilterSupport.NoLocalFilter(source));
+ }
+ Consumer sub =
+ source.addConsumer(target,
+ filterManager,
+ AMQMessage.class,
+ AMQShortString.toString(tag),
+ options);
}
catch (AMQException e)
{
- _tag2SubscriptionMap.remove(tag);
+ _tag2SubscriptionTargetMap.remove(tag);
throw e;
}
catch (RuntimeException e)
{
- _tag2SubscriptionMap.remove(tag);
+ _tag2SubscriptionTargetMap.remove(tag);
throw e;
}
return tag;
@@ -567,18 +600,11 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
public boolean unsubscribeConsumer(AMQShortString consumerTag) throws AMQException
{
- Subscription sub = _tag2SubscriptionMap.remove(consumerTag);
+ ConsumerTarget_0_8 target = _tag2SubscriptionTargetMap.remove(consumerTag);
+ Consumer sub = target == null ? null : target.getConsumer();
if (sub != null)
{
- try
- {
- sub.getSendLock();
- sub.getQueue().unregisterSubscription(sub);
- }
- finally
- {
- sub.releaseSendLock();
- }
+ sub.close();
return true;
}
else
@@ -633,7 +659,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
{
if (_logger.isInfoEnabled())
{
- if (!_tag2SubscriptionMap.isEmpty())
+ if (!_tag2SubscriptionTargetMap.isEmpty())
{
_logger.info("Unsubscribing all consumers on channel " + toString());
}
@@ -643,28 +669,21 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
}
}
- for (Map.Entry<AMQShortString, Subscription> me : _tag2SubscriptionMap.entrySet())
+ for (Map.Entry<AMQShortString, ConsumerTarget_0_8> me : _tag2SubscriptionTargetMap.entrySet())
{
if (_logger.isInfoEnabled())
{
_logger.info("Unsubscribing consumer '" + me.getKey() + "' on channel " + toString());
}
- Subscription sub = me.getValue();
+ Consumer sub = me.getValue().getConsumer();
- try
- {
- sub.getSendLock();
- sub.getQueue().unregisterSubscription(sub);
- }
- finally
- {
- sub.releaseSendLock();
- }
+
+ sub.close();
}
- _tag2SubscriptionMap.clear();
+ _tag2SubscriptionTargetMap.clear();
}
/**
@@ -673,24 +692,15 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
* @param entry the record of the message on the queue that was delivered
* @param deliveryTag the delivery tag used when delivering the message (see protocol spec for description of the
* delivery tag)
- * @param subscription The consumer that is to acknowledge this message.
+ * @param consumer The consumer that is to acknowledge this message.
*/
- public void addUnacknowledgedMessage(QueueEntry entry, long deliveryTag, Subscription subscription)
+ public void addUnacknowledgedMessage(MessageInstance entry, long deliveryTag, Consumer consumer)
{
if (_logger.isDebugEnabled())
{
- if (entry.getQueue() == null)
- {
- _logger.debug("Adding unacked message with a null queue:" + entry);
- }
- else
- {
- if (_logger.isDebugEnabled())
- {
_logger.debug(debugIdentity() + " Adding unacked message(" + entry.getMessage().toString() + " DT:" + deliveryTag
- + ") with a queue(" + entry.getQueue() + ") for " + subscription);
- }
- }
+ + ") for " + consumer + " on " + entry.getOwningResource().getName());
+
}
_unacknowledgedMessageMap.add(deliveryTag, entry);
@@ -713,7 +723,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
public void requeue() throws AMQException
{
// we must create a new map since all the messages will get a new delivery tag when they are redelivered
- Collection<QueueEntry> messagesToBeDelivered = _unacknowledgedMessageMap.cancelAllMessages();
+ Collection<MessageInstance> messagesToBeDelivered = _unacknowledgedMessageMap.cancelAllMessages();
if (!messagesToBeDelivered.isEmpty())
{
@@ -724,21 +734,13 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
}
- for (QueueEntry unacked : messagesToBeDelivered)
+ for (MessageInstance unacked : messagesToBeDelivered)
{
- if (!unacked.isQueueDeleted())
- {
- // Mark message redelivered
- unacked.setRedelivered();
-
- // Ensure message is released for redelivery
- unacked.release();
+ // Mark message redelivered
+ unacked.setRedelivered();
- }
- else
- {
- unacked.delete();
- }
+ // Ensure message is released for redelivery
+ unacked.release();
}
}
@@ -752,7 +754,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
*/
public void requeue(long deliveryTag) throws AMQException
{
- QueueEntry unacked = _unacknowledgedMessageMap.remove(deliveryTag);
+ MessageInstance unacked = _unacknowledgedMessageMap.remove(deliveryTag);
if (unacked != null)
{
@@ -760,20 +762,8 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
unacked.setRedelivered();
// Ensure message is released for redelivery
- if (!unacked.isQueueDeleted())
- {
+ unacked.release();
- // Ensure message is released for redelivery
- unacked.release();
-
- }
- else
- {
- _logger.warn(System.identityHashCode(this) + " Requested requeue of message(" + unacked
- + "):" + deliveryTag + " but no queue defined and no DeadLetter queue so DROPPING message.");
-
- unacked.delete();
- }
}
else
{
@@ -786,10 +776,10 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
public boolean isMaxDeliveryCountEnabled(final long deliveryTag)
{
- final QueueEntry queueEntry = _unacknowledgedMessageMap.get(deliveryTag);
+ final MessageInstance queueEntry = _unacknowledgedMessageMap.get(deliveryTag);
if (queueEntry != null)
{
- final int maximumDeliveryCount = queueEntry.getQueue().getMaximumDeliveryCount();
+ final int maximumDeliveryCount = queueEntry.getMaximumDeliveryCount();
return maximumDeliveryCount > 0;
}
@@ -798,10 +788,10 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
public boolean isDeliveredTooManyTimes(final long deliveryTag)
{
- final QueueEntry queueEntry = _unacknowledgedMessageMap.get(deliveryTag);
+ final MessageInstance queueEntry = _unacknowledgedMessageMap.get(deliveryTag);
if (queueEntry != null)
{
- final int maximumDeliveryCount = queueEntry.getQueue().getMaximumDeliveryCount();
+ final int maximumDeliveryCount = queueEntry.getMaximumDeliveryCount();
final int numDeliveries = queueEntry.getDeliveryCount();
return maximumDeliveryCount != 0 && numDeliveries >= maximumDeliveryCount;
}
@@ -812,16 +802,14 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
/**
* Called to resend all outstanding unacknowledged messages to this same channel.
*
- * @param requeue Are the messages to be requeued or dropped.
- *
* @throws AMQException When something goes wrong.
*/
- public void resend(final boolean requeue) throws AMQException
+ public void resend() throws AMQException
{
- final Map<Long, QueueEntry> msgToRequeue = new LinkedHashMap<Long, QueueEntry>();
- final Map<Long, QueueEntry> msgToResend = new LinkedHashMap<Long, QueueEntry>();
+ final Map<Long, MessageInstance> msgToRequeue = new LinkedHashMap<Long, MessageInstance>();
+ final Map<Long, MessageInstance> msgToResend = new LinkedHashMap<Long, MessageInstance>();
if (_logger.isDebugEnabled())
{
@@ -833,9 +821,8 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
// and those that don't to be requeued.
_unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap,
msgToRequeue,
- msgToResend,
- requeue,
- _messageStore));
+ msgToResend
+ ));
// Process Messages to Resend
@@ -851,39 +838,20 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
}
}
- for (Map.Entry<Long, QueueEntry> entry : msgToResend.entrySet())
+ for (Map.Entry<Long, MessageInstance> entry : msgToResend.entrySet())
{
- QueueEntry message = entry.getValue();
+ MessageInstance message = entry.getValue();
long deliveryTag = entry.getKey();
//Amend the delivery counter as the client hasn't seen these messages yet.
message.decrementDeliveryCount();
- AMQQueue queue = message.getQueue();
-
// Without any details from the client about what has been processed we have to mark
// all messages in the unacked map as redelivered.
message.setRedelivered();
- Subscription sub = message.getDeliveredSubscription();
-
- if (sub != null)
- {
-
- if(!queue.resend(message,sub))
- {
- msgToRequeue.put(deliveryTag, message);
- }
- }
- else
+ if (!message.resend())
{
-
- if (_logger.isInfoEnabled())
- {
- _logger.info("DeliveredSubscription not recorded so just requeueing(" + message.toString()
- + ")to prevent loss");
- }
- // move this message to requeue
msgToRequeue.put(deliveryTag, message);
}
} // for all messages
@@ -898,9 +866,9 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
}
// Process Messages to Requeue at the front of the queue
- for (Map.Entry<Long, QueueEntry> entry : msgToRequeue.entrySet())
+ for (Map.Entry<Long, MessageInstance> entry : msgToRequeue.entrySet())
{
- QueueEntry message = entry.getValue();
+ MessageInstance message = entry.getValue();
long deliveryTag = entry.getKey();
//Amend the delivery counter as the client hasn't seen these messages yet.
@@ -926,11 +894,11 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
*/
public void acknowledgeMessage(long deliveryTag, boolean multiple) throws AMQException
{
- Collection<QueueEntry> ackedMessages = getAckedMessages(deliveryTag, multiple);
+ Collection<MessageInstance> ackedMessages = getAckedMessages(deliveryTag, multiple);
_transaction.dequeue(ackedMessages, new MessageAcknowledgeAction(ackedMessages));
}
- private Collection<QueueEntry> getAckedMessages(long deliveryTag, boolean multiple)
+ private Collection<MessageInstance> getAckedMessages(long deliveryTag, boolean multiple)
{
return _unacknowledgedMessageMap.acknowledge(deliveryTag, multiple);
@@ -976,9 +944,9 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
if (wasSuspended)
{
// may need to deliver queued messages
- for (Subscription s : _tag2SubscriptionMap.values())
+ for (ConsumerTarget_0_8 s : _tag2SubscriptionTargetMap.values())
{
- s.getQueue().deliverAsync(s);
+ s.getConsumer().externalStateChange();
}
}
@@ -992,15 +960,15 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
if (!wasSuspended)
{
// may need to deliver queued messages
- for (Subscription s : _tag2SubscriptionMap.values())
+ for (ConsumerTarget_0_8 s : _tag2SubscriptionTargetMap.values())
{
try
{
- s.getSendLock();
+ s.getConsumer().getSendLock();
}
finally
{
- s.releaseSendLock();
+ s.getConsumer().releaseSendLock();
}
}
}
@@ -1077,10 +1045,10 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
boolean requiresSuspend = _suspended.compareAndSet(false,true);
// ensure all subscriptions have seen the change to the channel state
- for(Subscription sub : _tag2SubscriptionMap.values())
+ for(ConsumerTarget_0_8 sub : _tag2SubscriptionTargetMap.values())
{
- sub.getSendLock();
- sub.releaseSendLock();
+ sub.getConsumer().getSendLock();
+ sub.getConsumer().releaseSendLock();
}
try
@@ -1098,16 +1066,16 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
postRollbackTask.run();
- for(QueueEntry entry : _resendList)
+ for(MessageInstance entry : _resendList)
{
- Subscription sub = entry.getDeliveredSubscription();
+ Consumer sub = entry.getDeliveredConsumer();
if(sub == null || sub.isClosed())
{
entry.release();
}
else
{
- sub.getQueue().resend(entry, sub);
+ entry.resend();
}
}
_resendList.clear();
@@ -1115,9 +1083,9 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
if(requiresSuspend)
{
_suspended.set(false);
- for(Subscription sub : _tag2SubscriptionMap.values())
+ for(ConsumerTarget_0_8 sub : _tag2SubscriptionTargetMap.values())
{
- sub.getQueue().deliverAsync(sub);
+ sub.getConsumer().externalStateChange();
}
}
@@ -1173,7 +1141,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
private final RecordDeliveryMethod _recordDeliveryMethod = new RecordDeliveryMethod()
{
- public void recordMessageDelivery(final Subscription sub, final QueueEntry entry, final long deliveryTag)
+ public void recordMessageDelivery(final Consumer sub, final MessageInstance entry, final long deliveryTag)
{
addUnacknowledgedMessage(entry, deliveryTag, sub);
}
@@ -1233,140 +1201,97 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
return getId().compareTo(o.getId());
}
- private class MessageDeliveryAction implements ServerTransaction.Action
- {
- private final MessageReference<AMQMessage> _reference;
- private List<? extends BaseQueue> _destinationQueues;
-
- public MessageDeliveryAction(AMQMessage currentMessage,
- List<? extends BaseQueue> destinationQueues)
- {
- _reference = currentMessage.newReference();
- _destinationQueues = destinationQueues;
- }
- public void postCommit()
- {
- try
- {
- AMQMessage message = _reference.getMessage();
- final boolean immediate = message.isImmediate();
-
- for(int i = 0; i < _destinationQueues.size(); i++)
- {
- BaseQueue queue = _destinationQueues.get(i);
-
- BaseQueue.PostEnqueueAction action;
-
- if(immediate)
- {
- action = new ImmediateAction();
- }
- else
- {
- action = null;
- }
-
- queue.enqueue(message, isTransactional(), action);
-
- if(queue instanceof AMQQueue)
- {
- ((AMQQueue)queue).checkCapacity(AMQChannel.this);
- }
-
- }
-
- message.getStoredMessage().flushToStore();
- _reference.release();
- }
- catch (AMQException e)
- {
- // TODO
- throw new RuntimeException(e);
- }
- }
-
- public void onRollback()
- {
- // Maybe keep track of entries that were created and then delete them here in case of failure
- // to in memory enqueue
- _reference.release();
- }
-
-
- }
- private class ImmediateAction implements BaseQueue.PostEnqueueAction
+ private class ImmediateAction<C extends Consumer> implements Action<MessageInstance<?,C>>
{
public ImmediateAction()
{
}
- public void onEnqueue(QueueEntry entry)
+ public void performAction(MessageInstance<?,C> entry)
{
- AMQQueue queue = entry.getQueue();
+ TransactionLogResource queue = entry.getOwningResource();
if (!entry.getDeliveredToConsumer() && entry.acquire())
{
ServerTransaction txn = new LocalTransaction(_messageStore);
- Collection<QueueEntry> entries = new ArrayList<QueueEntry>(1);
- entries.add(entry);
final AMQMessage message = (AMQMessage) entry.getMessage();
- txn.dequeue(queue, entry.getMessage(),
- new MessageAcknowledgeAction(entries)
- {
- @Override
- public void postCommit()
+ MessageReference ref = message.newReference();
+ try
+ {
+ entry.delete();
+ txn.dequeue(queue, message,
+ new ServerTransaction.Action()
{
- try
+ @Override
+ public void postCommit()
{
- final
- ProtocolOutputConverter outputConverter =
- _session.getProtocolOutputConverter();
-
- outputConverter.writeReturn(message.getMessagePublishInfo(),
- message.getContentHeaderBody(),
- message,
- _channelId,
- AMQConstant.NO_CONSUMERS.getCode(),
- IMMEDIATE_DELIVERY_REPLY_TEXT);
+ try
+ {
+ final
+ ProtocolOutputConverter outputConverter =
+ _session.getProtocolOutputConverter();
+
+ outputConverter.writeReturn(message.getMessagePublishInfo(),
+ message.getContentHeaderBody(),
+ message,
+ _channelId,
+ AMQConstant.NO_CONSUMERS.getCode(),
+ IMMEDIATE_DELIVERY_REPLY_TEXT);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
}
- catch (AMQException e)
+
+ @Override
+ public void onRollback()
{
- throw new RuntimeException(e);
+
}
- super.postCommit();
}
- }
- );
- txn.commit();
+ );
+ txn.commit();
+ }
+ finally
+ {
+ ref.release();
+ }
}
else
{
- queue.checkCapacity(AMQChannel.this);
+ if(queue instanceof CapacityChecker)
+ {
+ ((CapacityChecker)queue).checkCapacity(AMQChannel.this);
+ }
}
}
}
- private final class CapacityCheckAction implements BaseQueue.PostEnqueueAction
+ private final class CapacityCheckAction<C extends Consumer> implements Action<MessageInstance<?,C>>
{
@Override
- public void onEnqueue(final QueueEntry entry)
+ public void performAction(final MessageInstance<?,C> entry)
{
- AMQQueue queue = entry.getQueue();
- queue.checkCapacity(AMQChannel.this);
+ TransactionLogResource queue = entry.getOwningResource();
+ if(queue instanceof CapacityChecker)
+ {
+ ((CapacityChecker)queue).checkCapacity(AMQChannel.this);
+ }
}
}
private class MessageAcknowledgeAction implements ServerTransaction.Action
{
- private final Collection<QueueEntry> _ackedMessages;
+ private final Collection<MessageInstance> _ackedMessages;
- public MessageAcknowledgeAction(Collection<QueueEntry> ackedMessages)
+ public MessageAcknowledgeAction(Collection<MessageInstance> ackedMessages)
{
_ackedMessages = ackedMessages;
}
@@ -1375,7 +1300,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
{
try
{
- for(QueueEntry entry : _ackedMessages)
+ for(MessageInstance entry : _ackedMessages)
{
entry.delete();
}
@@ -1398,10 +1323,10 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
{
try
{
- for(QueueEntry entry : _ackedMessages)
- {
- entry.release();
- }
+ for(MessageInstance entry : _ackedMessages)
+ {
+ entry.release();
+ }
}
finally
{
@@ -1566,7 +1491,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
public void deadLetter(long deliveryTag) throws AMQException
{
final UnacknowledgedMessageMap unackedMap = getUnacknowledgedMessageMap();
- final QueueEntry rejectedQueueEntry = unackedMap.remove(deliveryTag);
+ final MessageInstance rejectedQueueEntry = unackedMap.remove(deliveryTag);
if (rejectedQueueEntry == null)
{
@@ -1575,36 +1500,42 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
else
{
final ServerMessage msg = rejectedQueueEntry.getMessage();
+ final Consumer sub = rejectedQueueEntry.getDeliveredConsumer();
- int requeues = rejectedQueueEntry.routeToAlternate(new BaseQueue.PostEnqueueAction()
+ int requeues = rejectedQueueEntry.routeToAlternate(new Action<MessageInstance>()
{
@Override
- public void onEnqueue(final QueueEntry requeueEntry)
+ public void performAction(final MessageInstance requeueEntry)
{
_actor.message( _logSubject, ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(),
- requeueEntry.getQueue().getName()));
+ requeueEntry.getOwningResource().getName()));
}
}, null);
if(requeues == 0)
{
- final AMQQueue queue = rejectedQueueEntry.getQueue();
- final Exchange altExchange = queue.getAlternateExchange();
-
- if (altExchange == null)
+ final TransactionLogResource owningResource = rejectedQueueEntry.getOwningResource();
+ if(owningResource instanceof AMQQueue)
{
- _logger.debug("No alternate exchange configured for queue, must discard the message as unable to DLQ: delivery tag: " + deliveryTag);
- _actor.message(_logSubject, ChannelMessages.DISCARDMSG_NOALTEXCH(msg.getMessageNumber(), queue.getName(), msg.getRoutingKey()));
+ final AMQQueue queue = (AMQQueue) owningResource;
- }
- else
- {
- _logger.debug(
- "Routing process provided no queues to enqueue the message on, must discard message as unable to DLQ: delivery tag: "
- + deliveryTag);
- _actor.message(_logSubject,
- ChannelMessages.DISCARDMSG_NOROUTE(msg.getMessageNumber(), altExchange.getName()));
+ final Exchange altExchange = queue.getAlternateExchange();
+
+ if (altExchange == null)
+ {
+ _logger.debug("No alternate exchange configured for queue, must discard the message as unable to DLQ: delivery tag: " + deliveryTag);
+ _actor.message(_logSubject, ChannelMessages.DISCARDMSG_NOALTEXCH(msg.getMessageNumber(), queue.getName(), msg.getRoutingKey()));
+
+ }
+ else
+ {
+ _logger.debug(
+ "Routing process provided no queues to enqueue the message on, must discard message as unable to DLQ: delivery tag: "
+ + deliveryTag);
+ _actor.message(_logSubject,
+ ChannelMessages.DISCARDMSG_NOROUTE(msg.getMessageNumber(), altExchange.getName()));
+ }
}
}
@@ -1665,6 +1596,6 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
@Override
public int getConsumerCount()
{
- return _tag2SubscriptionMap.size();
+ return _tag2SubscriptionTargetMap.size();
}
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java
index c7a84fa3b6..e83e86981b 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java
@@ -94,8 +94,7 @@ import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import org.apache.qpid.server.protocol.v0_8.state.AMQState;
import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager;
import org.apache.qpid.server.stats.StatisticsCounter;
-import org.apache.qpid.server.subscription.ClientDeliveryMethod;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Sender;
import org.apache.qpid.transport.TransportException;
@@ -1669,7 +1668,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi
}
@Override
- public void deliverToClient(final Subscription sub, final ServerMessage message,
+ public void deliverToClient(final Consumer sub, final ServerMessage message,
final InstanceProperties props, final long deliveryTag)
throws AMQException
{
@@ -1678,7 +1677,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi
props,
_channelId,
deliveryTag,
- ((SubscriptionImpl)sub).getConsumerTag());
+ new AMQShortString(sub.getName()));
}
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolSession.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolSession.java
index 85d995518a..6bcd4b9d49 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolSession.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolSession.java
@@ -39,7 +39,6 @@ import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter;
import org.apache.qpid.server.security.AuthorizationHolder;
-import org.apache.qpid.server.subscription.ClientDeliveryMethod;
import org.apache.qpid.server.virtualhost.VirtualHost;
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/ClientDeliveryMethod.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ClientDeliveryMethod.java
index 45a1978af1..2e362c11f8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/ClientDeliveryMethod.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ClientDeliveryMethod.java
@@ -18,14 +18,15 @@
* under the License.
*
*/
-package org.apache.qpid.server.subscription;
+package org.apache.qpid.server.protocol.v0_8;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.consumer.Consumer;
public interface ClientDeliveryMethod
{
- void deliverToClient(final Subscription sub, final ServerMessage message, final InstanceProperties props,
+ void deliverToClient(final Consumer sub, final ServerMessage message, final InstanceProperties props,
final long deliveryTag) throws AMQException;
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java
new file mode 100644
index 0000000000..0f0e49bf7f
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java
@@ -0,0 +1,571 @@
+/*
+ *
+ * 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.protocol.v0_8;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.common.AMQPFilterTypes;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.v0_8.handler.BasicGetMethodHandler;
+import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.consumer.AbstractConsumerTarget;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.StateChangeListener;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Encapsulation of a subscription to a queue. <p/> Ties together the protocol session of a subscriber, the consumer tag
+ * that was given out by the broker and the channel id. <p/>
+ */
+public abstract class ConsumerTarget_0_8 extends AbstractConsumerTarget implements FlowCreditManager.FlowCreditManagerListener
+{
+
+ private final StateChangeListener<MessageInstance, MessageInstance.State> _entryReleaseListener =
+ new StateChangeListener<MessageInstance, MessageInstance.State>()
+ {
+ @Override
+ public void stateChanged(final MessageInstance entry,
+ final MessageInstance.State oldSate,
+ final MessageInstance.State newState)
+ {
+ if (oldSate == QueueEntry.State.ACQUIRED && (newState == QueueEntry.State.AVAILABLE || newState == QueueEntry.State.DEQUEUED))
+ {
+ restoreCredit(entry.getMessage());
+ }
+ entry.removeStateChangeListener(this);
+ }
+ };
+
+ private final ClientDeliveryMethod _deliveryMethod;
+ private final RecordDeliveryMethod _recordMethod;
+
+ private final AtomicLong _unacknowledgedCount = new AtomicLong(0);
+ private final AtomicLong _unacknowledgedBytes = new AtomicLong(0);
+ private Consumer _consumer;
+
+
+ public static ConsumerTarget_0_8 createBrowserTarget(AMQChannel channel,
+ AMQShortString consumerTag, FieldTable filters,
+ FlowCreditManager creditManager) throws AMQException
+ {
+ return new BrowserConsumer(channel, consumerTag, filters, creditManager, channel.getClientDeliveryMethod(), channel.getRecordDeliveryMethod());
+ }
+
+ public static ConsumerTarget_0_8 createGetNoAckTarget(final AMQChannel channel,
+ final AMQShortString consumerTag,
+ final FieldTable filters,
+ final FlowCreditManager creditManager,
+ final ClientDeliveryMethod deliveryMethod,
+ final RecordDeliveryMethod recordMethod) throws AMQException
+ {
+ return new GetNoAckConsumer(channel, consumerTag, filters, creditManager, deliveryMethod, recordMethod);
+ }
+
+ static final class BrowserConsumer extends ConsumerTarget_0_8
+ {
+ public BrowserConsumer(AMQChannel channel,
+ AMQShortString consumerTag, FieldTable filters,
+ FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(channel, consumerTag,
+ filters, creditManager, deliveryMethod, recordMethod);
+ }
+
+ /**
+ * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
+ * thread safe.
+ *
+ *
+ * @param entry
+ * @param batch
+ * @throws org.apache.qpid.AMQException
+ */
+ @Override
+ public void send(MessageInstance entry, boolean batch) throws AMQException
+ {
+ // We don't decrement the reference here as we don't want to consume the message
+ // but we do want to send it to the client.
+
+ synchronized (getChannel())
+ {
+ long deliveryTag = getChannel().getNextDeliveryTag();
+ sendToClient(entry.getMessage(), entry.getInstanceProperties(), deliveryTag);
+ }
+
+ }
+
+ @Override
+ public boolean allocateCredit(ServerMessage msg)
+ {
+ return true;
+ }
+
+ }
+
+ public static ConsumerTarget_0_8 createNoAckTarget(AMQChannel channel,
+ AMQShortString consumerTag, FieldTable filters,
+ FlowCreditManager creditManager) throws AMQException
+ {
+ return new NoAckConsumer(channel, consumerTag, filters, creditManager, channel.getClientDeliveryMethod(), channel.getRecordDeliveryMethod());
+ }
+
+ public static ConsumerTarget_0_8 createNoAckTarget(AMQChannel channel,
+ AMQShortString consumerTag, FieldTable filters,
+ FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod) throws AMQException
+ {
+ return new NoAckConsumer(channel, consumerTag, filters, creditManager, deliveryMethod, recordMethod);
+ }
+
+ public static class NoAckConsumer extends ConsumerTarget_0_8
+ {
+ private final AutoCommitTransaction _txn;
+
+ public NoAckConsumer(AMQChannel channel,
+ AMQShortString consumerTag, FieldTable filters,
+ FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(channel, consumerTag, filters, creditManager, deliveryMethod, recordMethod);
+
+ _txn = new AutoCommitTransaction(channel.getVirtualHost().getMessageStore());
+ }
+
+ /**
+ * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
+ * thread safe.
+ *
+ *
+ * @param entry The message to send
+ * @param batch
+ * @throws org.apache.qpid.AMQException
+ */
+ @Override
+ public void send(MessageInstance entry, boolean batch) throws AMQException
+ {
+ // if we do not need to wait for client acknowledgements
+ // we can decrement the reference count immediately.
+
+ // By doing this _before_ the send we ensure that it
+ // doesn't get sent if it can't be dequeued, preventing
+ // duplicate delivery on recovery.
+
+ // The send may of course still fail, in which case, as
+ // the message is unacked, it will be lost.
+ _txn.dequeue(entry.getOwningResource(), entry.getMessage(), NOOP);
+
+ ServerMessage message = entry.getMessage();
+ MessageReference ref = message.newReference();
+ InstanceProperties props = entry.getInstanceProperties();
+ entry.delete();
+
+ synchronized (getChannel())
+ {
+ getChannel().getProtocolSession().setDeferFlush(batch);
+ long deliveryTag = getChannel().getNextDeliveryTag();
+
+ sendToClient(message, props, deliveryTag);
+
+ }
+ ref.release();
+
+
+ }
+
+ @Override
+ public boolean allocateCredit(ServerMessage msg)
+ {
+ return true;
+ }
+
+ private static final ServerTransaction.Action NOOP =
+ new ServerTransaction.Action()
+ {
+ @Override
+ public void postCommit()
+ {
+ }
+
+ @Override
+ public void onRollback()
+ {
+ }
+ };
+ }
+
+ /**
+ * NoAck Subscription for use with BasicGet method.
+ */
+ public static final class GetNoAckConsumer extends NoAckConsumer
+ {
+ public GetNoAckConsumer(AMQChannel channel,
+ AMQShortString consumerTag, FieldTable filters,
+ FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(channel, consumerTag, filters, creditManager, deliveryMethod, recordMethod);
+ }
+
+ public boolean allocateCredit(ServerMessage msg)
+ {
+ return getCreditManager().useCreditForMessage(msg.getSize());
+ }
+
+ }
+
+
+ public static ConsumerTarget_0_8 createAckTarget(AMQChannel channel,
+ AMQShortString consumerTag, FieldTable filters,
+ FlowCreditManager creditManager)
+ throws AMQException
+ {
+ return new AckConsumer(channel,consumerTag,filters,creditManager, channel.getClientDeliveryMethod(), channel.getRecordDeliveryMethod());
+ }
+
+
+ public static ConsumerTarget_0_8 createAckTarget(AMQChannel channel,
+ AMQShortString consumerTag, FieldTable filters,
+ FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ return new AckConsumer(channel,consumerTag,filters,creditManager, deliveryMethod, recordMethod);
+ }
+
+ static final class AckConsumer extends ConsumerTarget_0_8
+ {
+ public AckConsumer(AMQChannel channel,
+ AMQShortString consumerTag, FieldTable filters,
+ FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(channel, consumerTag, filters, creditManager, deliveryMethod, recordMethod);
+ }
+
+ /**
+ * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
+ * thread safe.
+ *
+ *
+ * @param entry The message to send
+ * @param batch
+ * @throws org.apache.qpid.AMQException
+ */
+ @Override
+ public void send(MessageInstance entry, boolean batch) throws AMQException
+ {
+
+
+ synchronized (getChannel())
+ {
+ getChannel().getProtocolSession().setDeferFlush(batch);
+ long deliveryTag = getChannel().getNextDeliveryTag();
+
+ addUnacknowledgedMessage(entry);
+ recordMessageDelivery(entry, deliveryTag);
+ entry.addStateChangeListener(getReleasedStateChangeListener());
+ sendToClient(entry.getMessage(), entry.getInstanceProperties(), deliveryTag);
+ entry.incrementDeliveryCount();
+
+ }
+ }
+
+
+
+ }
+
+
+ private static final Logger _logger = Logger.getLogger(ConsumerTarget_0_8.class);
+
+ private final AMQChannel _channel;
+
+ private final AMQShortString _consumerTag;
+
+ private final FlowCreditManager _creditManager;
+
+ private final Boolean _autoClose;
+
+ private final AtomicBoolean _deleted = new AtomicBoolean(false);
+
+
+
+
+ public ConsumerTarget_0_8(AMQChannel channel,
+ AMQShortString consumerTag,
+ FieldTable arguments,
+ FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(State.ACTIVE);
+
+ _channel = channel;
+ _consumerTag = consumerTag;
+
+ _creditManager = creditManager;
+ creditManager.addStateListener(this);
+
+ _deliveryMethod = deliveryMethod;
+ _recordMethod = recordMethod;
+
+ if (arguments != null)
+ {
+ Object autoClose = arguments.get(AMQPFilterTypes.AUTO_CLOSE.getValue());
+ if (autoClose != null)
+ {
+ _autoClose = (Boolean) autoClose;
+ }
+ else
+ {
+ _autoClose = false;
+ }
+ }
+ else
+ {
+ _autoClose = false;
+ }
+ }
+
+ public Consumer getConsumer()
+ {
+ return _consumer;
+ }
+
+ @Override
+ public void consumerRemoved(final Consumer sub)
+ {
+ }
+
+ @Override
+ public void consumerAdded(final Consumer sub)
+ {
+ _consumer = sub;
+ }
+
+ public AMQSessionModel getSessionModel()
+ {
+ return _channel;
+ }
+
+ public String toString()
+ {
+ String subscriber = "[channel=" + _channel +
+ ", consumerTag=" + _consumerTag +
+ ", session=" + getProtocolSession().getKey() ;
+
+ return subscriber + "]";
+ }
+
+ public boolean isSuspended()
+ {
+ return getState()!=State.ACTIVE || _channel.isSuspended() || _deleted.get() || _channel.getConnectionModel().isStopped();
+ }
+
+ /**
+ * Callback indicating that a queue has been deleted.
+ *
+ */
+ public void queueDeleted()
+ {
+ _deleted.set(true);
+ }
+
+ public boolean isAutoClose()
+ {
+ return _autoClose;
+ }
+
+ public FlowCreditManager getCreditManager()
+ {
+ return _creditManager;
+ }
+
+
+ public boolean close()
+ {
+ boolean closed = false;
+ State state = getState();
+
+ final Consumer consumer = getConsumer();
+
+ if(consumer != null)
+ {
+ consumer.getSendLock();
+ }
+ try
+ {
+ while(!closed && state != State.CLOSED)
+ {
+ closed = updateState(state, State.CLOSED);
+ if(!closed)
+ {
+ state = getState();
+ }
+ }
+ _creditManager.removeListener(this);
+ return closed;
+ }
+ finally
+ {
+ if(consumer != null)
+ {
+ consumer.releaseSendLock();
+ }
+ }
+ }
+
+
+ public boolean allocateCredit(ServerMessage msg)
+ {
+ return _creditManager.useCreditForMessage(msg.getSize());
+ }
+
+ public AMQChannel getChannel()
+ {
+ return _channel;
+ }
+
+ public AMQShortString getConsumerTag()
+ {
+ return _consumerTag;
+ }
+
+ public AMQProtocolSession getProtocolSession()
+ {
+ return _channel.getProtocolSession();
+ }
+
+ public void restoreCredit(final ServerMessage message)
+ {
+ _creditManager.restoreCredit(1, message.getSize());
+ }
+
+ protected final StateChangeListener<MessageInstance, MessageInstance.State> getReleasedStateChangeListener()
+ {
+ return _entryReleaseListener;
+ }
+
+ public void creditStateChanged(boolean hasCredit)
+ {
+
+ if(hasCredit)
+ {
+ if(!updateState(State.SUSPENDED, State.ACTIVE))
+ {
+ // this is a hack to get round the issue of increasing bytes credit
+ getStateListener().stateChanged(this, State.ACTIVE, State.ACTIVE);
+ }
+ }
+ else
+ {
+ updateState(State.ACTIVE, State.SUSPENDED);
+ }
+ }
+
+ protected void sendToClient(final ServerMessage message, final InstanceProperties props, final long deliveryTag)
+ throws AMQException
+ {
+ _deliveryMethod.deliverToClient(getConsumer(), message, props, deliveryTag);
+
+ }
+
+
+ protected void recordMessageDelivery(final MessageInstance entry, final long deliveryTag)
+ {
+ _recordMethod.recordMessageDelivery(getConsumer(),entry,deliveryTag);
+ }
+
+
+ public void confirmAutoClose()
+ {
+ ProtocolOutputConverter converter = getChannel().getProtocolSession().getProtocolOutputConverter();
+ converter.confirmConsumerAutoClose(getChannel().getChannelId(), getConsumerTag());
+ }
+
+ public void queueEmpty() throws AMQException
+ {
+ if (isAutoClose())
+ {
+ close();
+ confirmAutoClose();
+ }
+ }
+
+ public void flushBatched()
+ {
+ _channel.getProtocolSession().setDeferFlush(false);
+
+ _channel.getProtocolSession().flushBatched();
+ }
+
+ protected void addUnacknowledgedMessage(MessageInstance entry)
+ {
+ final long size = entry.getMessage().getSize();
+ _unacknowledgedBytes.addAndGet(size);
+ _unacknowledgedCount.incrementAndGet();
+ entry.addStateChangeListener(new StateChangeListener<MessageInstance, MessageInstance.State>()
+ {
+ public void stateChanged(MessageInstance entry, MessageInstance.State oldState, MessageInstance.State newState)
+ {
+ if(oldState.equals(MessageInstance.State.ACQUIRED) && !newState.equals(MessageInstance.State.ACQUIRED))
+ {
+ _unacknowledgedBytes.addAndGet(-size);
+ _unacknowledgedCount.decrementAndGet();
+ entry.removeStateChangeListener(this);
+ }
+ }
+ });
+ }
+
+ public long getUnacknowledgedBytes()
+ {
+ return _unacknowledgedBytes.longValue();
+ }
+
+ public long getUnacknowledgedMessages()
+ {
+ return _unacknowledgedCount.longValue();
+ }
+}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java
index 060aebdd65..1de1638c2e 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java
@@ -23,11 +23,8 @@ package org.apache.qpid.server.protocol.v0_8;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.txn.AutoCommitTransaction;
-import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.consumer.Consumer;
import java.util.Map;
@@ -35,34 +32,28 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor
{
private static final Logger _log = Logger.getLogger(ExtractResendAndRequeue.class);
- private final Map<Long, QueueEntry> _msgToRequeue;
- private final Map<Long, QueueEntry> _msgToResend;
- private final boolean _requeueIfUnableToResend;
+ private final Map<Long, MessageInstance> _msgToRequeue;
+ private final Map<Long, MessageInstance> _msgToResend;
private final UnacknowledgedMessageMap _unacknowledgedMessageMap;
- private final MessageStore _transactionLog;
public ExtractResendAndRequeue(UnacknowledgedMessageMap unacknowledgedMessageMap,
- Map<Long, QueueEntry> msgToRequeue,
- Map<Long, QueueEntry> msgToResend,
- boolean requeueIfUnableToResend,
- MessageStore txnLog)
+ Map<Long, MessageInstance> msgToRequeue,
+ Map<Long, MessageInstance> msgToResend)
{
_unacknowledgedMessageMap = unacknowledgedMessageMap;
_msgToRequeue = msgToRequeue;
_msgToResend = msgToResend;
- _requeueIfUnableToResend = requeueIfUnableToResend;
- _transactionLog = txnLog;
}
- public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException
+ public boolean callback(final long deliveryTag, MessageInstance message) throws AMQException
{
message.setRedelivered();
- final Subscription subscription = message.getDeliveredSubscription();
- if (subscription != null)
+ final Consumer consumer = message.getDeliveredConsumer();
+ if (consumer != null)
{
// Consumer exists
- if (!subscription.isClosed())
+ if (!consumer.isClosed())
{
_msgToResend.put(deliveryTag, message);
}
@@ -73,58 +64,13 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor
}
else
{
- // Message has no consumer tag, so was "delivered" to a GET
- // or consumer no longer registered
- // cannot resend, so re-queue.
- if (!message.isQueueDeleted())
- {
- if (_requeueIfUnableToResend)
- {
- _msgToRequeue.put(deliveryTag, message);
- }
- else
- {
-
- dequeueEntry(message);
- _log.info("No DeadLetter Queue and requeue not requested so dropping message:" + message);
- }
- }
- else
- {
- dequeueEntry(message);
- _log.warn("Message.queue is null and no DeadLetter Queue so dropping message:" + message);
- }
+ _log.info("No DeadLetter Queue and requeue not requested so dropping message:" + message);
}
// false means continue processing
return false;
}
-
- private void dequeueEntry(final QueueEntry node)
- {
- ServerTransaction txn = new AutoCommitTransaction(_transactionLog);
- dequeueEntry(node, txn);
- }
-
- private void dequeueEntry(final QueueEntry node, ServerTransaction txn)
- {
- txn.dequeue(node.getQueue(), node.getMessage(),
- new ServerTransaction.Action()
- {
-
- public void postCommit()
- {
- node.delete();
- }
-
- public void onRollback()
- {
-
- }
- });
- }
-
public void visitComplete()
{
_unacknowledgedMessageMap.clear();
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/IncomingMessage.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/IncomingMessage.java
index 5a9a51ff59..80c4c77b65 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/IncomingMessage.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/IncomingMessage.java
@@ -20,15 +20,12 @@
*/
package org.apache.qpid.server.protocol.v0_8;
-import org.apache.log4j.Logger;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.message.MessageDestination;
import java.util.ArrayList;
import java.util.List;
@@ -38,7 +35,7 @@ public class IncomingMessage
private final MessagePublishInfo _messagePublishInfo;
private ContentHeaderBody _contentHeaderBody;
- private Exchange _exchange;
+ private MessageDestination _messageDestination;
/**
* Keeps a track of how many bytes we have received in body frames
@@ -77,9 +74,9 @@ public class IncomingMessage
return _messagePublishInfo.getExchange();
}
- public Exchange getExchange()
+ public MessageDestination getDestination()
{
- return _exchange;
+ return _messageDestination;
}
public ContentHeaderBody getContentHeader()
@@ -92,9 +89,9 @@ public class IncomingMessage
return getContentHeader().getBodySize();
}
- public void setExchange(final Exchange e)
+ public void setMessageDestination(final MessageDestination e)
{
- _exchange = e;
+ _messageDestination = e;
}
public int getBodyCount() throws AMQException
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java
new file mode 100644
index 0000000000..b80ad3e7b8
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java
@@ -0,0 +1,268 @@
+/*
+ *
+ * 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.protocol.v0_8;
+
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.plugin.MessageConverter;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.codec.BBEncoder;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MessageConverter_Internal_to_v0_8 implements MessageConverter<InternalMessage, AMQMessage>
+{
+ private static final int BASIC_CLASS_ID = 60;
+ private static final Charset UTF_8 = Charset.forName("UTF-8");
+
+
+ public Class<InternalMessage> getInputClass()
+ {
+ return InternalMessage.class;
+ }
+
+ @Override
+ public Class<AMQMessage> getOutputClass()
+ {
+ return AMQMessage.class;
+ }
+
+ @Override
+ public AMQMessage convert(InternalMessage serverMsg, VirtualHost vhost)
+ {
+ return new AMQMessage(convertToStoredMessage(serverMsg), null);
+ }
+
+ private StoredMessage<MessageMetaData> convertToStoredMessage(final InternalMessage serverMsg)
+ {
+ final byte[] messageContent = convertToBody(serverMsg.getMessageBody());
+ final MessageMetaData messageMetaData_0_8 = convertMetaData(serverMsg,
+ getBodyMimeType(serverMsg.getMessageBody()),
+ messageContent.length);
+
+ return new StoredMessage<MessageMetaData>()
+ {
+ @Override
+ public MessageMetaData getMetaData()
+ {
+ return messageMetaData_0_8;
+ }
+
+ @Override
+ public long getMessageNumber()
+ {
+ return serverMsg.getMessageNumber();
+ }
+
+ @Override
+ public void addContent(int offsetInMessage, ByteBuffer src)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getContent(int offsetInMessage, ByteBuffer dst)
+ {
+ int size = messageContent.length - offsetInMessage;
+ if(dst.remaining() < size)
+ {
+ size = dst.remaining();
+ }
+ ByteBuffer buf = ByteBuffer.wrap(messageContent, offsetInMessage, size);
+ dst.put(buf);
+ return size;
+ }
+
+ @Override
+ public ByteBuffer getContent(int offsetInMessage, int size)
+ {
+ return ByteBuffer.wrap(messageContent, offsetInMessage, size);
+ }
+
+ @Override
+ public StoreFuture flushToStore()
+ {
+ return StoreFuture.IMMEDIATE_FUTURE;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ private MessageMetaData convertMetaData(InternalMessage serverMsg, final String bodyMimeType, final int size)
+ {
+
+ MessagePublishInfo publishInfo = new MessagePublishInfo()
+ {
+ @Override
+ public AMQShortString getExchange()
+ {
+ return null;
+ }
+
+ @Override
+ public void setExchange(final AMQShortString amqShortString)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isImmediate()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isMandatory()
+ {
+ return false;
+ }
+
+ @Override
+ public AMQShortString getRoutingKey()
+ {
+ return null;
+ }
+ };
+
+
+ final BasicContentHeaderProperties props = new BasicContentHeaderProperties();
+ props.setAppId(serverMsg.getMessageHeader().getAppId());
+ props.setContentType(bodyMimeType);
+ props.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId());
+ props.setDeliveryMode(serverMsg.isPersistent() ? BasicContentHeaderProperties.PERSISTENT : BasicContentHeaderProperties.NON_PERSISTENT);
+ props.setExpiration(serverMsg.getExpiration());
+ props.setMessageId(serverMsg.getMessageHeader().getMessageId());
+ props.setPriority(serverMsg.getMessageHeader().getPriority());
+ props.setReplyTo(serverMsg.getMessageHeader().getReplyTo());
+ props.setTimestamp(serverMsg.getMessageHeader().getTimestamp());
+ props.setUserId(serverMsg.getMessageHeader().getUserId());
+
+ Map<String,Object> headerProps = new LinkedHashMap<String, Object>();
+
+ for(String headerName : serverMsg.getMessageHeader().getHeaderNames())
+ {
+ headerProps.put(headerName, serverMsg.getMessageHeader().getHeader(headerName));
+ }
+
+ props.setHeaders(FieldTable.convertToFieldTable(headerProps));
+
+ final ContentHeaderBody chb = new ContentHeaderBody(props, BASIC_CLASS_ID);
+ return new MessageMetaData(publishInfo, chb, serverMsg.getArrivalTime());
+ }
+
+
+ @Override
+ public String getType()
+ {
+ return "Internal to v0-8";
+ }
+
+
+ public static byte[] convertToBody(Object object)
+ {
+ if(object instanceof String)
+ {
+ return ((String)object).getBytes(UTF_8);
+ }
+ else if(object instanceof byte[])
+ {
+ return (byte[]) object;
+ }
+ else if(object instanceof Map)
+ {
+ BBEncoder encoder = new BBEncoder(1024);
+ encoder.writeMap((Map)object);
+ ByteBuffer buf = encoder.segment();
+ int remaining = buf.remaining();
+ byte[] data = new byte[remaining];
+ buf.get(data);
+ return data;
+
+ }
+ else if(object instanceof List)
+ {
+ BBEncoder encoder = new BBEncoder(1024);
+ encoder.writeList((List) object);
+ ByteBuffer buf = encoder.segment();
+ int remaining = buf.remaining();
+ byte[] data = new byte[remaining];
+ buf.get(data);
+ return data;
+ }
+ else
+ {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ try
+ {
+ ObjectOutputStream os = new ObjectOutputStream(bytesOut);
+ os.writeObject(object);
+ return bytesOut.toByteArray();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public static String getBodyMimeType(Object object)
+ {
+ if(object instanceof String)
+ {
+ return "text/plain";
+ }
+ else if(object instanceof byte[])
+ {
+ return "application/octet-stream";
+ }
+ else if(object instanceof Map)
+ {
+ return "amqp/map";
+ }
+ else if(object instanceof List)
+ {
+ return "amqp/list";
+ }
+ else
+ {
+ return "application/java-object-stream";
+ }
+ }
+
+}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_v0_8_to_Internal.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_v0_8_to_Internal.java
new file mode 100644
index 0000000000..6076ff66c7
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_v0_8_to_Internal.java
@@ -0,0 +1,148 @@
+/*
+ *
+ * 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.protocol.v0_8;
+
+import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.plugin.MessageConverter;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.typedmessage.TypedBytesContentReader;
+import org.apache.qpid.typedmessage.TypedBytesFormatException;
+
+import java.io.EOFException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MessageConverter_v0_8_to_Internal implements MessageConverter<AMQMessage, InternalMessage>
+{
+ @Override
+ public Class<AMQMessage> getInputClass()
+ {
+ return AMQMessage.class;
+ }
+
+ @Override
+ public Class<InternalMessage> getOutputClass()
+ {
+ return InternalMessage.class;
+ }
+
+ @Override
+ public InternalMessage convert(AMQMessage serverMessage, VirtualHost vhost)
+ {
+ final String mimeType = serverMessage.getMessageHeader().getMimeType();
+ byte[] data = new byte[(int) serverMessage.getSize()];
+ serverMessage.getContent(ByteBuffer.wrap(data), 0);
+
+ Object body = convertMessageBody(mimeType, data);
+
+ return InternalMessage.convert(serverMessage.getMessageNumber(), serverMessage.isPersistent(), serverMessage.getMessageHeader(), body);
+ }
+
+ private static Object convertMessageBody(String mimeType, byte[] data)
+ {
+ if("text/plain".equals(mimeType) || "text/xml".equals(mimeType))
+ {
+ String text = new String(data);
+ return text;
+ }
+ else if("jms/map-message".equals(mimeType))
+ {
+ TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data));
+
+ LinkedHashMap map = new LinkedHashMap();
+ final int entries = reader.readIntImpl();
+ for (int i = 0; i < entries; i++)
+ {
+ try
+ {
+ String propName = reader.readStringImpl();
+ Object value = reader.readObject();
+
+ map.put(propName, value);
+ }
+ catch (EOFException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ catch (TypedBytesFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+
+ }
+
+ return map;
+
+ }
+ else if("amqp/map".equals(mimeType))
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(data));
+ final Map<String,Object> map = decoder.readMap();
+
+ return map;
+
+ }
+ else if("amqp/list".equals(mimeType))
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(data));
+ return decoder.readList();
+ }
+ else if("jms/stream-message".equals(mimeType))
+ {
+ TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data));
+
+ List list = new ArrayList();
+ while (reader.remaining() != 0)
+ {
+ try
+ {
+ list.add(reader.readObject());
+ }
+ catch (TypedBytesFormatException e)
+ {
+ throw new RuntimeException(e); // TODO - Implement
+ }
+ catch (EOFException e)
+ {
+ throw new RuntimeException(e); // TODO - Implement
+ }
+ }
+ return list;
+ }
+ else
+ {
+ return data;
+
+ }
+ }
+
+ @Override
+ public String getType()
+ {
+ return "v0-8 to Internal";
+ }
+}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java
index ead28c6e26..3665e7f135 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java
@@ -105,7 +105,7 @@ public class MessageMetaData implements StorableMessageMetaData
}
- public int writeToBuffer(int offset, ByteBuffer dest)
+ public int writeToBuffer(ByteBuffer dest)
{
int oldPosition = dest.position();
try
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/RecordDeliveryMethod.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/RecordDeliveryMethod.java
index e2ed4104de..70d7da3432 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/RecordDeliveryMethod.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/RecordDeliveryMethod.java
@@ -18,11 +18,12 @@
* under the License.
*
*/
-package org.apache.qpid.server.subscription;
+package org.apache.qpid.server.protocol.v0_8;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.consumer.Consumer;
public interface RecordDeliveryMethod
{
- void recordMessageDelivery(final Subscription sub, final QueueEntry entry, final long deliveryTag);
+ void recordMessageDelivery(final Consumer sub, final MessageInstance entry, final long deliveryTag);
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java
deleted file mode 100644
index 6646dc0cc2..0000000000
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java
+++ /dev/null
@@ -1,68 +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.server.protocol.v0_8;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.flow.FlowCreditManager;
-import org.apache.qpid.server.subscription.ClientDeliveryMethod;
-import org.apache.qpid.server.subscription.RecordDeliveryMethod;
-import org.apache.qpid.server.subscription.Subscription;
-
-/**
- * Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This factory
- * primarily assists testing although in future more sophisticated subscribers may need a different subscription
- * implementation.
- *
- * @see org.apache.qpid.server.queue.AMQQueue
- */
-public interface SubscriptionFactory
-{
- Subscription createSubscription(int channel,
- AMQProtocolSession protocolSession,
- AMQShortString consumerTag,
- boolean acks,
- FieldTable filters,
- boolean noLocal, FlowCreditManager creditManager) throws AMQException;
-
-
- Subscription createSubscription(AMQChannel channel,
- AMQProtocolSession protocolSession,
- AMQShortString consumerTag,
- boolean acks,
- FieldTable filters,
- boolean noLocal,
- FlowCreditManager creditManager,
- ClientDeliveryMethod clientMethod,
- RecordDeliveryMethod recordMethod) throws AMQException;
-
-
- Subscription createBasicGetNoAckSubscription(AMQChannel channel,
- AMQProtocolSession session,
- AMQShortString consumerTag,
- FieldTable filters,
- boolean noLocal,
- FlowCreditManager creditManager,
- ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod) throws AMQException;
-
-}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.java
deleted file mode 100644
index 93b51a0567..0000000000
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.java
+++ /dev/null
@@ -1,109 +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.server.protocol.v0_8;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.common.AMQPFilterTypes;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.flow.FlowCreditManager;
-import org.apache.qpid.server.subscription.ClientDeliveryMethod;
-import org.apache.qpid.server.subscription.RecordDeliveryMethod;
-import org.apache.qpid.server.subscription.Subscription;
-
-public class SubscriptionFactoryImpl implements SubscriptionFactory
-{
-
- public Subscription createSubscription(int channelId, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, boolean acks, FieldTable filters,
- boolean noLocal, FlowCreditManager creditManager) throws AMQException
- {
- AMQChannel channel = protocolSession.getChannel(channelId);
- if (channel == null)
- {
- throw new AMQException(AMQConstant.NOT_FOUND, "channel :" + channelId + " not found in protocol session");
- }
- ClientDeliveryMethod clientMethod = channel.getClientDeliveryMethod();
- RecordDeliveryMethod recordMethod = channel.getRecordDeliveryMethod();
-
-
- return createSubscription(channel, protocolSession, consumerTag, acks, filters,
- noLocal,
- creditManager,
- clientMethod,
- recordMethod
- );
- }
-
- public Subscription createSubscription(final AMQChannel channel,
- final AMQProtocolSession protocolSession,
- final AMQShortString consumerTag,
- final boolean acks,
- final FieldTable filters,
- final boolean noLocal,
- final FlowCreditManager creditManager,
- final ClientDeliveryMethod clientMethod,
- final RecordDeliveryMethod recordMethod
- )
- throws AMQException
- {
- boolean isBrowser;
-
- if (filters != null)
- {
- Boolean isBrowserObj = (Boolean) filters.get(AMQPFilterTypes.NO_CONSUME.getValue());
- isBrowser = (isBrowserObj != null) && isBrowserObj.booleanValue();
- }
- else
- {
- isBrowser = false;
- }
-
- if(isBrowser)
- {
- return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
- }
- else if(acks)
- {
- return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
- }
- else
- {
- return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
- }
- }
-
- public SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(final AMQChannel channel,
- final AMQProtocolSession session,
- final AMQShortString consumerTag,
- final FieldTable filters,
- final boolean noLocal,
- final FlowCreditManager creditManager,
- final ClientDeliveryMethod deliveryMethod,
- final RecordDeliveryMethod recordMethod) throws AMQException
- {
- return new SubscriptionImpl.GetNoAckSubscription(channel, session, null, null, false, creditManager, deliveryMethod, recordMethod);
- }
-
- public static final SubscriptionFactoryImpl INSTANCE = new SubscriptionFactoryImpl();
-
-}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java
deleted file mode 100644
index 7c52fbe3b0..0000000000
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java
+++ /dev/null
@@ -1,858 +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.server.protocol.v0_8;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.common.AMQPFilterTypes;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.filter.FilterManager;
-import org.apache.qpid.server.filter.FilterManagerFactory;
-import org.apache.qpid.server.flow.FlowCreditManager;
-import org.apache.qpid.server.logging.LogActor;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.SubscriptionActor;
-import org.apache.qpid.server.logging.messages.SubscriptionMessages;
-import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject;
-import org.apache.qpid.server.message.InstanceProperties;
-import org.apache.qpid.server.message.MessageReference;
-import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.protocol.MessageConverterRegistry;
-import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter;
-import org.apache.qpid.server.protocol.AMQSessionModel;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.subscription.ClientDeliveryMethod;
-import org.apache.qpid.server.subscription.RecordDeliveryMethod;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.txn.AutoCommitTransaction;
-import org.apache.qpid.server.txn.ServerTransaction;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Encapsulation of a subscription to a queue. <p/> Ties together the protocol session of a subscriber, the consumer tag
- * that was given out by the broker and the channel id. <p/>
- */
-public abstract class SubscriptionImpl implements Subscription, FlowCreditManager.FlowCreditManagerListener
-{
-
- private StateListener _stateListener = new StateListener()
- {
-
- public void stateChange(Subscription sub, State oldState, State newState)
- {
-
- }
- };
-
-
- private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE);
- private volatile AMQQueue.Context _queueContext;
-
- private final ClientDeliveryMethod _deliveryMethod;
- private final RecordDeliveryMethod _recordMethod;
-
- private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
-
- private final Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
-
- private final Lock _stateChangeLock;
-
- private final long _subscriptionID;
- private LogSubject _logSubject;
- private LogActor _logActor;
- private final AtomicLong _deliveredCount = new AtomicLong(0);
- private final AtomicLong _deliveredBytes = new AtomicLong(0);
-
- private final AtomicLong _unacknowledgedCount = new AtomicLong(0);
- private final AtomicLong _unacknowledgedBytes = new AtomicLong(0);
-
- private long _createTime = System.currentTimeMillis();
-
-
- static final class BrowserSubscription extends SubscriptionImpl
- {
- public BrowserSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, FieldTable filters,
- boolean noLocal, FlowCreditManager creditManager,
- ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
- throws AMQException
- {
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
- }
-
-
- public boolean isBrowser()
- {
- return true;
- }
-
- /**
- * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
- * thread safe.
- *
- *
- * @param entry
- * @param batch
- * @throws AMQException
- */
- @Override
- public void send(QueueEntry entry, boolean batch) throws AMQException
- {
- // We don't decrement the reference here as we don't want to consume the message
- // but we do want to send it to the client.
-
- synchronized (getChannel())
- {
- long deliveryTag = getChannel().getNextDeliveryTag();
- sendToClient(entry.getMessage(), entry.getInstanceProperties(), deliveryTag);
- }
-
- }
-
- @Override
- public boolean wouldSuspend(QueueEntry msg)
- {
- return false;
- }
-
- }
-
- public static class NoAckSubscription extends SubscriptionImpl
- {
- private final AutoCommitTransaction _txn;
-
- public NoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, FieldTable filters,
- boolean noLocal, FlowCreditManager creditManager,
- ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
- throws AMQException
- {
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
- _txn = new AutoCommitTransaction(protocolSession.getVirtualHost().getMessageStore());
- }
-
-
- public boolean isBrowser()
- {
- return false;
- }
-
- @Override
- public boolean isExplicitAcknowledge()
- {
- return false;
- }
-
- /**
- * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
- * thread safe.
- *
- *
- * @param entry The message to send
- * @param batch
- * @throws AMQException
- */
- @Override
- public void send(QueueEntry entry, boolean batch) throws AMQException
- {
- // if we do not need to wait for client acknowledgements
- // we can decrement the reference count immediately.
-
- // By doing this _before_ the send we ensure that it
- // doesn't get sent if it can't be dequeued, preventing
- // duplicate delivery on recovery.
-
- // The send may of course still fail, in which case, as
- // the message is unacked, it will be lost.
- _txn.dequeue(getQueue(), entry.getMessage(), NOOP);
-
- ServerMessage message = entry.getMessage();
- MessageReference ref = message.newReference();
- InstanceProperties props = entry.getInstanceProperties();
- entry.delete();
-
- synchronized (getChannel())
- {
- getChannel().getProtocolSession().setDeferFlush(batch);
- long deliveryTag = getChannel().getNextDeliveryTag();
-
- sendToClient(message, props, deliveryTag);
-
- }
- ref.release();
-
-
- }
-
- @Override
- public boolean wouldSuspend(QueueEntry msg)
- {
- return false;
- }
-
- private static final ServerTransaction.Action NOOP =
- new ServerTransaction.Action()
- {
- @Override
- public void postCommit()
- {
- }
-
- @Override
- public void onRollback()
- {
- }
- };
- }
-
- /**
- * NoAck Subscription for use with BasicGet method.
- */
- public static final class GetNoAckSubscription extends SubscriptionImpl.NoAckSubscription
- {
- public GetNoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, FieldTable filters,
- boolean noLocal, FlowCreditManager creditManager,
- ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
- throws AMQException
- {
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
- }
-
- public boolean isTransient()
- {
- return true;
- }
-
- public boolean wouldSuspend(QueueEntry msg)
- {
- return !getCreditManager().useCreditForMessage(msg.getMessage().getSize());
- }
-
- }
-
- static final class AckSubscription extends SubscriptionImpl
- {
- public AckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, FieldTable filters,
- boolean noLocal, FlowCreditManager creditManager,
- ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
- throws AMQException
- {
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
- }
-
-
- public boolean isBrowser()
- {
- return false;
- }
-
-
- /**
- * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
- * thread safe.
- *
- *
- * @param entry The message to send
- * @param batch
- * @throws AMQException
- */
- @Override
- public void send(QueueEntry entry, boolean batch) throws AMQException
- {
-
-
- synchronized (getChannel())
- {
- getChannel().getProtocolSession().setDeferFlush(batch);
- long deliveryTag = getChannel().getNextDeliveryTag();
-
- addUnacknowledgedMessage(entry);
- recordMessageDelivery(entry, deliveryTag);
- sendToClient(entry.getMessage(), entry.getInstanceProperties(), deliveryTag);
- entry.incrementDeliveryCount();
-
- }
- }
-
-
-
- }
-
-
- private static final Logger _logger = Logger.getLogger(SubscriptionImpl.class);
-
- private final AMQChannel _channel;
-
- private final AMQShortString _consumerTag;
-
-
- private boolean _noLocal;
-
- private final FlowCreditManager _creditManager;
-
- private FilterManager _filters;
-
- private final Boolean _autoClose;
-
- private AMQQueue _queue;
- private final AtomicBoolean _deleted = new AtomicBoolean(false);
-
-
-
-
- public SubscriptionImpl(AMQChannel channel, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, FieldTable arguments,
- boolean noLocal, FlowCreditManager creditManager,
- ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
- throws AMQException
- {
- _subscriptionID = SUB_ID_GENERATOR.getAndIncrement();
- _channel = channel;
- _consumerTag = consumerTag;
-
- _creditManager = creditManager;
- creditManager.addStateListener(this);
-
- _noLocal = noLocal;
-
-
- _filters = FilterManagerFactory.createManager(FieldTable.convertToMap(arguments));
-
- _deliveryMethod = deliveryMethod;
- _recordMethod = recordMethod;
-
-
- _stateChangeLock = new ReentrantLock();
-
-
- if (arguments != null)
- {
- Object autoClose = arguments.get(AMQPFilterTypes.AUTO_CLOSE.getValue());
- if (autoClose != null)
- {
- _autoClose = (Boolean) autoClose;
- }
- else
- {
- _autoClose = false;
- }
- }
- else
- {
- _autoClose = false;
- }
-
- }
-
- public AMQSessionModel getSessionModel()
- {
- return _channel;
- }
-
- public Long getDelivered()
- {
- return _deliveredCount.get();
- }
-
- public synchronized void setQueue(AMQQueue queue, boolean exclusive)
- {
- if(getQueue() != null)
- {
- throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue());
- }
- _queue = queue;
-
- _logSubject = new SubscriptionLogSubject(this);
- _logActor = new SubscriptionActor(CurrentActor.get().getRootMessageLogger(), this);
-
- if (CurrentActor.get().getRootMessageLogger().
- isMessageEnabled(CurrentActor.get(), _logSubject, SubscriptionMessages.CREATE_LOG_HIERARCHY))
- {
- // Get the string value of the filters
- String filterLogString = null;
- if (_filters != null && _filters.hasFilters())
- {
- filterLogString = _filters.toString();
- }
-
- if (isAutoClose())
- {
- if (filterLogString == null)
- {
- filterLogString = "";
- }
- else
- {
- filterLogString += ",";
- }
- filterLogString += "AutoClose";
- }
-
- if (isBrowser())
- {
- // We do not need to check for null here as all Browsers are AutoClose
- filterLogString +=",Browser";
- }
-
- CurrentActor.get().
- message(_logSubject,
- SubscriptionMessages.CREATE(filterLogString,
- queue.isDurable() && exclusive,
- filterLogString != null));
- }
- }
-
- public String toString()
- {
- String subscriber = "[channel=" + _channel +
- ", consumerTag=" + _consumerTag +
- ", session=" + getProtocolSession().getKey() ;
-
- return subscriber + "]";
- }
-
- /**
- * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
- * thread safe.
- *
- *
- * @param entry
- * @param batch
- * @throws AMQException
- */
- abstract public void send(QueueEntry entry, boolean batch) throws AMQException;
-
-
- public boolean isSuspended()
- {
- return !isActive() || _channel.isSuspended() || _deleted.get() || _channel.getConnectionModel().isStopped();
- }
-
- /**
- * Callback indicating that a queue has been deleted.
- *
- * @param queue The queue to delete
- */
- public void queueDeleted(AMQQueue queue)
- {
- _deleted.set(true);
- }
-
- public boolean hasInterest(QueueEntry entry)
- {
- //check that the message hasn't been rejected
- if (entry.isRejectedBy(getSubscriptionID()))
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Subscription:" + this + " rejected message:" + entry);
- }
- }
-
- if(entry.getMessage() instanceof AMQMessage)
- {
- if (_noLocal)
- {
- AMQMessage message = (AMQMessage) entry.getMessage();
-
- final Object publisherReference = message.getConnectionReference();
-
- // We don't want local messages so check to see if message is one we sent
- Object localReference = getProtocolSession().getReference();
-
- if(publisherReference != null && publisherReference.equals(localReference))
- {
- return false;
- }
- }
- }
- else
- {
- // No interest in messages we can't convert to AMQMessage
- if(MessageConverterRegistry.getConverter(entry.getMessage().getClass(), AMQMessage.class)==null)
- {
- return false;
- }
- }
-
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("(" + this + ") checking filters for message (" + entry);
- }
- return checkFilters(entry);
-
- }
-
- private boolean checkFilters(QueueEntry msg)
- {
- return (_filters == null) || _filters.allAllow(msg.asFilterable());
- }
-
- public boolean isAutoClose()
- {
- return _autoClose;
- }
-
- public FlowCreditManager getCreditManager()
- {
- return _creditManager;
- }
-
-
- public void close()
- {
- boolean closed = false;
- State state = getState();
-
- _stateChangeLock.lock();
- try
- {
- while(!closed && state != State.CLOSED)
- {
- closed = _state.compareAndSet(state, State.CLOSED);
- if(!closed)
- {
- state = getState();
- }
- else
- {
- _stateListener.stateChange(this,state, State.CLOSED);
- }
- }
- _creditManager.removeListener(this);
- }
- finally
- {
- _stateChangeLock.unlock();
- }
- //Log Subscription closed
- CurrentActor.get().message(_logSubject, SubscriptionMessages.CLOSE());
- }
-
- public boolean isClosed()
- {
- return getState() == State.CLOSED;
- }
-
-
- public boolean wouldSuspend(QueueEntry msg)
- {
- return !_creditManager.useCreditForMessage(msg.getMessage().getSize());
- }
-
- public boolean trySendLock()
- {
- return _stateChangeLock.tryLock();
- }
-
- public void getSendLock()
- {
- _stateChangeLock.lock();
- }
-
- public void releaseSendLock()
- {
- _stateChangeLock.unlock();
- }
-
- public AMQChannel getChannel()
- {
- return _channel;
- }
-
- public AMQShortString getConsumerTag()
- {
- return _consumerTag;
- }
-
- public String getConsumerName()
- {
- return _consumerTag == null ? null : _consumerTag.asString();
- }
-
- public long getSubscriptionID()
- {
- return _subscriptionID;
- }
-
- public AMQProtocolSession getProtocolSession()
- {
- return _channel.getProtocolSession();
- }
-
- public LogActor getLogActor()
- {
- return _logActor;
- }
-
- public AMQQueue getQueue()
- {
- return _queue;
- }
-
- public void onDequeue(final QueueEntry queueEntry)
- {
- restoreCredit(queueEntry);
- }
-
- public void releaseQueueEntry(final QueueEntry queueEntry)
- {
- restoreCredit(queueEntry);
- }
-
- public void restoreCredit(final QueueEntry queueEntry)
- {
- _creditManager.restoreCredit(1, queueEntry.getSize());
- }
-
- public void creditStateChanged(boolean hasCredit)
- {
-
- if(hasCredit)
- {
- if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE))
- {
- _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE);
- }
- else
- {
- // this is a hack to get round the issue of increasing bytes credit
- _stateListener.stateChange(this, State.ACTIVE, State.ACTIVE);
- }
- }
- else
- {
- if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
- {
- _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
- }
- }
- CurrentActor.get().message(_logSubject,SubscriptionMessages.STATE(_state.get().toString()));
- }
-
- public State getState()
- {
- return _state.get();
- }
-
-
- public void setStateListener(final StateListener listener)
- {
- _stateListener = listener;
- }
-
-
- public AMQQueue.Context getQueueContext()
- {
- return _queueContext;
- }
-
- public void setQueueContext(AMQQueue.Context context)
- {
- _queueContext = context;
- }
-
-
- protected void sendToClient(final ServerMessage message, final InstanceProperties props, final long deliveryTag)
- throws AMQException
- {
- _deliveryMethod.deliverToClient(this, message, props, deliveryTag);
- _deliveredCount.incrementAndGet();
- _deliveredBytes.addAndGet(message.getSize());
- }
-
-
- protected void recordMessageDelivery(final QueueEntry entry, final long deliveryTag)
- {
- _recordMethod.recordMessageDelivery(this,entry,deliveryTag);
- }
-
-
- public boolean isActive()
- {
- return getState() == State.ACTIVE;
- }
-
- public QueueEntry.SubscriptionAcquiredState getOwningState()
- {
- return _owningState;
- }
-
- public void confirmAutoClose()
- {
- ProtocolOutputConverter converter = getChannel().getProtocolSession().getProtocolOutputConverter();
- converter.confirmConsumerAutoClose(getChannel().getChannelId(), getConsumerTag());
- }
-
- public boolean acquires()
- {
- return !isBrowser();
- }
-
- public boolean seesRequeues()
- {
- return !isBrowser();
- }
-
- public boolean isTransient()
- {
- return false;
- }
-
- public void set(String key, Object value)
- {
- _properties.put(key, value);
- }
-
- public Object get(String key)
- {
- return _properties.get(key);
- }
-
-
- public void setNoLocal(boolean noLocal)
- {
- _noLocal = noLocal;
- }
-
- abstract boolean isBrowser();
-
- public String getCreditMode()
- {
- return "WINDOW";
- }
-
- public boolean isBrowsing()
- {
- return isBrowser();
- }
-
- public boolean isExplicitAcknowledge()
- {
- return true;
- }
-
- public boolean isDurable()
- {
- return false;
- }
-
- public boolean isExclusive()
- {
- return getQueue().hasExclusiveSubscriber();
- }
-
- public String getName()
- {
- return String.valueOf(_consumerTag);
- }
-
- public Map<String, Object> getArguments()
- {
- return null;
- }
-
- public boolean isSessionTransactional()
- {
- return _channel.isTransactional();
- }
-
- public long getCreateTime()
- {
- return _createTime;
- }
-
- public void queueEmpty() throws AMQException
- {
- if (isAutoClose())
- {
- _queue.unregisterSubscription(this);
-
- confirmAutoClose();
- }
- }
-
- public void flushBatched()
- {
- _channel.getProtocolSession().setDeferFlush(false);
-
- _channel.getProtocolSession().flushBatched();
- }
-
- public long getBytesOut()
- {
- return _deliveredBytes.longValue();
- }
-
- public long getMessagesOut()
- {
- return _deliveredCount.longValue();
- }
-
-
- protected void addUnacknowledgedMessage(QueueEntry entry)
- {
- final long size = entry.getSize();
- _unacknowledgedBytes.addAndGet(size);
- _unacknowledgedCount.incrementAndGet();
- entry.addStateChangeListener(new QueueEntry.StateChangeListener()
- {
- public void stateChanged(QueueEntry entry, QueueEntry.State oldState, QueueEntry.State newState)
- {
- if(oldState.equals(QueueEntry.State.ACQUIRED) && !newState.equals(QueueEntry.State.ACQUIRED))
- {
- _unacknowledgedBytes.addAndGet(-size);
- _unacknowledgedCount.decrementAndGet();
- entry.removeStateChangeListener(this);
- }
- }
- });
- }
-
- public long getUnacknowledgedBytes()
- {
- return _unacknowledgedBytes.longValue();
- }
-
- public long getUnacknowledgedMessages()
- {
- return _unacknowledgedCount.longValue();
- }
-}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java
index 1d41bcdcf4..fcbbadd507 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.protocol.v0_8;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.queue.QueueEntry;
import java.util.Collection;
@@ -36,24 +37,24 @@ public interface UnacknowledgedMessageMap
*@param message the message being iterated over @return true to stop iteration, false to continue
* @throws AMQException
*/
- boolean callback(final long deliveryTag, QueueEntry message) throws AMQException;
+ boolean callback(final long deliveryTag, MessageInstance message) throws AMQException;
void visitComplete();
}
void visit(Visitor visitor) throws AMQException;
- void add(long deliveryTag, QueueEntry message);
+ void add(long deliveryTag, MessageInstance message);
- QueueEntry remove(long deliveryTag);
+ MessageInstance remove(long deliveryTag);
- Collection<QueueEntry> cancelAllMessages();
+ Collection<MessageInstance> cancelAllMessages();
int size();
void clear();
- QueueEntry get(long deliveryTag);
+ MessageInstance get(long deliveryTag);
/**
* Get the set of delivery tags that are outstanding.
@@ -62,7 +63,7 @@ public interface UnacknowledgedMessageMap
*/
Set<Long> getDeliveryTags();
- Collection<QueueEntry> acknowledge(long deliveryTag, boolean multiple);
+ Collection<MessageInstance> acknowledge(long deliveryTag, boolean multiple);
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java
index 17b2c7b985..8d70e769d3 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.protocol.v0_8;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.queue.QueueEntry;
import java.util.Collection;
@@ -34,7 +35,7 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
private long _unackedSize;
- private Map<Long, QueueEntry> _map;
+ private Map<Long, MessageInstance> _map;
private long _lastDeliveryTag;
@@ -43,10 +44,10 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
public UnacknowledgedMessageMapImpl(int prefetchLimit)
{
_prefetchLimit = prefetchLimit;
- _map = new LinkedHashMap<Long, QueueEntry>(prefetchLimit);
+ _map = new LinkedHashMap<Long, MessageInstance>(prefetchLimit);
}
- public void collect(long deliveryTag, boolean multiple, Map<Long, QueueEntry> msgs)
+ public void collect(long deliveryTag, boolean multiple, Map<Long, MessageInstance> msgs)
{
if (multiple)
{
@@ -54,7 +55,7 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
else
{
- final QueueEntry entry = get(deliveryTag);
+ final MessageInstance entry = get(deliveryTag);
if(entry != null)
{
msgs.put(deliveryTag, entry);
@@ -63,7 +64,7 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
- public void remove(Map<Long,QueueEntry> msgs)
+ public void remove(Map<Long,MessageInstance> msgs)
{
synchronized (_lock)
{
@@ -74,12 +75,12 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public QueueEntry remove(long deliveryTag)
+ public MessageInstance remove(long deliveryTag)
{
synchronized (_lock)
{
- QueueEntry message = _map.remove(deliveryTag);
+ MessageInstance message = _map.remove(deliveryTag);
if(message != null)
{
_unackedSize -= message.getMessage().getSize();
@@ -94,8 +95,8 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
{
synchronized (_lock)
{
- Set<Map.Entry<Long, QueueEntry>> currentEntries = _map.entrySet();
- for (Map.Entry<Long, QueueEntry> entry : currentEntries)
+ Set<Map.Entry<Long, MessageInstance>> currentEntries = _map.entrySet();
+ for (Map.Entry<Long, MessageInstance> entry : currentEntries)
{
visitor.callback(entry.getKey().longValue(), entry.getValue());
}
@@ -103,7 +104,7 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public void add(long deliveryTag, QueueEntry message)
+ public void add(long deliveryTag, MessageInstance message)
{
synchronized (_lock)
{
@@ -113,12 +114,12 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public Collection<QueueEntry> cancelAllMessages()
+ public Collection<MessageInstance> cancelAllMessages()
{
synchronized (_lock)
{
- Collection<QueueEntry> currentEntries = _map.values();
- _map = new LinkedHashMap<Long, QueueEntry>(_prefetchLimit);
+ Collection<MessageInstance> currentEntries = _map.values();
+ _map = new LinkedHashMap<Long, MessageInstance>(_prefetchLimit);
_unackedSize = 0l;
return currentEntries;
}
@@ -141,7 +142,7 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public QueueEntry get(long key)
+ public MessageInstance get(long key)
{
synchronized (_lock)
{
@@ -157,19 +158,19 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public Collection<QueueEntry> acknowledge(long deliveryTag, boolean multiple)
+ public Collection<MessageInstance> acknowledge(long deliveryTag, boolean multiple)
{
- Map<Long, QueueEntry> ackedMessageMap = new LinkedHashMap<Long,QueueEntry>();
+ Map<Long, MessageInstance> ackedMessageMap = new LinkedHashMap<Long,MessageInstance>();
collect(deliveryTag, multiple, ackedMessageMap);
remove(ackedMessageMap);
return ackedMessageMap.values();
}
- private void collect(long key, Map<Long, QueueEntry> msgs)
+ private void collect(long key, Map<Long, MessageInstance> msgs)
{
synchronized (_lock)
{
- for (Map.Entry<Long, QueueEntry> entry : _map.entrySet())
+ for (Map.Entry<Long, MessageInstance> entry : _map.entrySet())
{
msgs.put(entry.getKey(),entry.getValue());
if (entry.getKey() == key)
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java
index 836de44f4e..b28bb5a0ad 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java
@@ -28,6 +28,7 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicConsumeBody;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.protocol.v0_8.AMQChannel;
import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession;
import org.apache.qpid.server.protocol.AMQSessionModel;
@@ -73,7 +74,7 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
" args:" + body.getArguments());
}
- AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueue(body.getQueue().intern().toString());
+ MessageSource queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueue(body.getQueue().intern().toString());
if (queue == null)
{
@@ -120,8 +121,12 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
if(consumerTagName == null || channel.getSubscription(consumerTagName) == null)
{
- AMQShortString consumerTag = channel.subscribeToQueue(consumerTagName, queue, !body.getNoAck(),
- body.getArguments(), body.getNoLocal(), body.getExclusive());
+ AMQShortString consumerTag = channel.consumeFromSource(consumerTagName,
+ queue,
+ !body.getNoAck(),
+ body.getArguments(),
+ body.getExclusive(),
+ body.getNoLocal());
if (!body.getNowait())
{
MethodRegistry methodRegistry = protocolConnection.getMethodRegistry();
@@ -156,14 +161,14 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
}
- catch (AMQQueue.ExistingExclusiveSubscription e)
+ catch (AMQQueue.ExistingExclusiveConsumer e)
{
throw body.getChannelException(AMQConstant.ACCESS_REFUSED,
"Cannot subscribe to queue "
+ queue.getName()
+ " as it already has an existing exclusive consumer");
}
- catch (AMQQueue.ExistingSubscriptionPreventsExclusive e)
+ catch (AMQQueue.ExistingConsumerPreventsExclusive e)
{
throw body.getChannelException(AMQConstant.ACCESS_REFUSED,
"Cannot subscribe to queue "
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java
index 4b569ccc71..b1d2fa5088 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java
@@ -24,27 +24,31 @@ package org.apache.qpid.server.protocol.v0_8.handler;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicGetBody;
import org.apache.qpid.framing.BasicGetEmptyBody;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.v0_8.AMQChannel;
import org.apache.qpid.server.flow.FlowCreditManager;
import org.apache.qpid.server.flow.MessageOnlyCreditManager;
+import org.apache.qpid.server.protocol.v0_8.AMQMessage;
import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession;
import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.v0_8.ConsumerTarget_0_8;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager;
import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener;
-import org.apache.qpid.server.subscription.ClientDeliveryMethod;
-import org.apache.qpid.server.subscription.RecordDeliveryMethod;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.protocol.v0_8.SubscriptionFactoryImpl;
+import org.apache.qpid.server.protocol.v0_8.ClientDeliveryMethod;
+import org.apache.qpid.server.protocol.v0_8.RecordDeliveryMethod;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.EnumSet;
+
public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetBody>
{
private static final Logger _log = Logger.getLogger(BasicGetMethodHandler.class);
@@ -124,50 +128,79 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB
final FlowCreditManager singleMessageCredit = new MessageOnlyCreditManager(1L);
- final ClientDeliveryMethod getDeliveryMethod = new ClientDeliveryMethod()
- {
-
- @Override
- public void deliverToClient(final Subscription sub, final ServerMessage message, final
- InstanceProperties props, final long deliveryTag)
- throws AMQException
- {
- singleMessageCredit.useCreditForMessage(message.getSize());
- session.getProtocolOutputConverter().writeGetOk(message,
- props,
- channel.getChannelId(),
- deliveryTag,
- queue.getMessageCount());
-
-
- }
- };
+ final GetDeliveryMethod getDeliveryMethod =
+ new GetDeliveryMethod(singleMessageCredit, session, channel, queue);
final RecordDeliveryMethod getRecordMethod = new RecordDeliveryMethod()
{
- public void recordMessageDelivery(final Subscription sub, final QueueEntry entry, final long deliveryTag)
+ public void recordMessageDelivery(final Consumer sub, final MessageInstance entry, final long deliveryTag)
{
channel.addUnacknowledgedMessage(entry, deliveryTag, null);
}
};
- Subscription sub;
+ ConsumerTarget_0_8 target;
+ EnumSet<Consumer.Option> options = EnumSet.of(Consumer.Option.TRANSIENT, Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES);
if(acks)
{
- sub = SubscriptionFactoryImpl.INSTANCE.createSubscription(channel, session, null, acks, null, false, singleMessageCredit, getDeliveryMethod, getRecordMethod);
+
+ target = ConsumerTarget_0_8.createAckTarget(channel,
+ AMQShortString.EMPTY_STRING, null,
+ singleMessageCredit, getDeliveryMethod, getRecordMethod);
}
else
{
- sub = SubscriptionFactoryImpl.INSTANCE.createBasicGetNoAckSubscription(channel, session, null, null, false, singleMessageCredit, getDeliveryMethod, getRecordMethod);
+ target = ConsumerTarget_0_8.createGetNoAckTarget(channel,
+ AMQShortString.EMPTY_STRING, null,
+ singleMessageCredit, getDeliveryMethod, getRecordMethod);
}
- queue.registerSubscription(sub,false);
- queue.flushSubscription(sub);
- queue.unregisterSubscription(sub);
- return(!singleMessageCredit.hasCredit());
+ Consumer sub = queue.addConsumer(target, null, AMQMessage.class, "", options);
+ sub.flush();
+ sub.close();
+ return(getDeliveryMethod.hasDeliveredMessage());
}
+ private static class GetDeliveryMethod implements ClientDeliveryMethod
+ {
+
+ private final FlowCreditManager _singleMessageCredit;
+ private final AMQProtocolSession _session;
+ private final AMQChannel _channel;
+ private final AMQQueue _queue;
+ private boolean _deliveredMessage;
+
+ public GetDeliveryMethod(final FlowCreditManager singleMessageCredit,
+ final AMQProtocolSession session,
+ final AMQChannel channel, final AMQQueue queue)
+ {
+ _singleMessageCredit = singleMessageCredit;
+ _session = session;
+ _channel = channel;
+ _queue = queue;
+ }
+
+ @Override
+ public void deliverToClient(final Consumer sub, final ServerMessage message,
+ final InstanceProperties props, final long deliveryTag) throws AMQException
+ {
+ _singleMessageCredit.useCreditForMessage(message.getSize());
+ _session.getProtocolOutputConverter().writeGetOk(message,
+ props,
+ _channel.getChannelId(),
+ deliveryTag,
+ _queue.getMessageCount());
+
+ _deliveredMessage = true;
+ }
+
+ public boolean hasDeliveredMessage()
+ {
+ return _deliveredMessage;
+ }
+ }
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java
index 497e97db3e..f8a7722447 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java
@@ -28,6 +28,7 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicPublishBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.message.MessageDestination;
import org.apache.qpid.server.protocol.v0_8.AMQChannel;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession;
@@ -67,7 +68,7 @@ public class BasicPublishMethodHandler implements StateAwareMethodListener<Basic
}
VirtualHost vHost = session.getVirtualHost();
- Exchange exch = vHost.getExchange(exchangeName.toString());
+ MessageDestination exch = vHost.getMessageDestination(exchangeName.toString());
// if the exchange does not exist we raise a channel exception
if (exch == null)
{
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java
index 0a79466b35..606bcf1693 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java
@@ -56,7 +56,7 @@ public class BasicRecoverMethodHandler implements StateAwareMethodListener<Basic
throw body.getChannelNotFoundException(channelId);
}
- channel.resend(body.getRequeue());
+ channel.resend();
// Qpid 0-8 hacks a synchronous -ok onto recover.
// In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java
index b54e1c7dcf..ef26e60a62 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java
@@ -58,7 +58,7 @@ public class BasicRecoverSyncMethodHandler implements StateAwareMethodListener<B
throw body.getChannelNotFoundException(channelId);
}
channel.sync();
- channel.resend(body.getRequeue());
+ channel.resend();
// Qpid 0-8 hacks a synchronous -ok onto recover.
// In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java
index f2ab154b32..fdbd44b06d 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java
@@ -24,6 +24,7 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.BasicRejectBody;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.protocol.v0_8.AMQChannel;
import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession;
import org.apache.qpid.server.queue.QueueEntry;
@@ -65,7 +66,7 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
long deliveryTag = body.getDeliveryTag();
- QueueEntry message = channel.getUnacknowledgedMessageMap().get(deliveryTag);
+ MessageInstance message = channel.getUnacknowledgedMessageMap().get(deliveryTag);
if (message == null)
{
@@ -73,16 +74,6 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
}
else
{
- if (message.isQueueDeleted())
- {
- _logger.warn("Message's Queue has already been purged, dropping message");
- message = channel.getUnacknowledgedMessageMap().remove(deliveryTag);
- if(message != null)
- {
- message.delete();
- }
- return;
- }
if (message.getMessage() == null)
{
@@ -98,41 +89,43 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
" on channel:" + channel.debugIdentity());
}
- message.reject();
-
if (body.getRequeue())
{
- channel.requeue(deliveryTag);
-
//this requeue represents a message rejected from the pre-dispatch queue
//therefore we need to amend the delivery counter.
message.decrementDeliveryCount();
+
+ channel.requeue(deliveryTag);
}
else
{
- final boolean maxDeliveryCountEnabled = channel.isMaxDeliveryCountEnabled(deliveryTag);
- _logger.debug("maxDeliveryCountEnabled: " + maxDeliveryCountEnabled + " deliveryTag " + deliveryTag);
- if (maxDeliveryCountEnabled)
- {
- final boolean deliveredTooManyTimes = channel.isDeliveredTooManyTimes(deliveryTag);
- _logger.debug("deliveredTooManyTimes: " + deliveredTooManyTimes + " deliveryTag " + deliveryTag);
- if (deliveredTooManyTimes)
- {
- channel.deadLetter(body.getDeliveryTag());
- }
- else
- {
- //this requeue represents a message rejected because of a recover/rollback that we
- //are not ready to DLQ. We rely on the reject command to resend from the unacked map
- //and therefore need to increment the delivery counter so we cancel out the effect
- //of the AMQChannel#resend() decrement.
- message.incrementDeliveryCount();
- }
- }
- else
- {
- channel.deadLetter(body.getDeliveryTag());
- }
+ // Since the Java client abuses the reject flag for requeing after rollback, we won't set reject here
+ // as it would prevent redelivery
+ // message.reject();
+
+ final boolean maxDeliveryCountEnabled = channel.isMaxDeliveryCountEnabled(deliveryTag);
+ _logger.debug("maxDeliveryCountEnabled: " + maxDeliveryCountEnabled + " deliveryTag " + deliveryTag);
+ if (maxDeliveryCountEnabled)
+ {
+ final boolean deliveredTooManyTimes = channel.isDeliveredTooManyTimes(deliveryTag);
+ _logger.debug("deliveredTooManyTimes: " + deliveredTooManyTimes + " deliveryTag " + deliveryTag);
+ if (deliveredTooManyTimes)
+ {
+ channel.deadLetter(body.getDeliveryTag());
+ }
+ else
+ {
+ //this requeue represents a message rejected because of a recover/rollback that we
+ //are not ready to DLQ. We rely on the reject command to resend from the unacked map
+ //and therefore need to increment the delivery counter so we cancel out the effect
+ //of the AMQChannel#resend() decrement.
+ message.incrementDeliveryCount();
+ }
+ }
+ else
+ {
+ channel.requeue(deliveryTag);
+ }
}
}
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java
index 3fdce83c2a..263175d590 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java
@@ -41,6 +41,7 @@ import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager;
import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener;
import org.apache.qpid.server.store.DurableConfigurationStoreHelper;
import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Map;
@@ -134,8 +135,8 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
}
};
protocolConnection.addSessionCloseTask(sessionCloseTask);
- queue.addQueueDeleteTask(new AMQQueue.Task() {
- public void doTask(AMQQueue queue) throws AMQException
+ queue.addQueueDeleteTask(new Action<AMQQueue>() {
+ public void performAction(AMQQueue queue)
{
protocolConnection.removeSessionCloseTask(sessionCloseTask);
}
@@ -245,9 +246,9 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
session.addSessionCloseTask(deleteQueueTask);
- queue.addQueueDeleteTask(new AMQQueue.Task()
+ queue.addQueueDeleteTask(new Action<AMQQueue>()
{
- public void doTask(AMQQueue queue)
+ public void performAction(AMQQueue queue)
{
session.removeSessionCloseTask(deleteQueueTask);
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java
index 19d0da007b..69ad1a0a21 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java
@@ -74,7 +74,7 @@ public class TxRollbackHandler implements StateAwareMethodListener<TxRollbackBod
//Now resend all the unacknowledged messages back to the original subscribers.
//(Must be done after the TxnRollback-ok response).
// Why, are we not allowed to send messages back to client before the ok method?
- channel.resend(false);
+ channel.resend();
}
catch (AMQException e)
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter
new file mode 100644
index 0000000000..d87bc2566f
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+org.apache.qpid.server.protocol.v0_8.MessageConverter_Internal_to_v0_8
+org.apache.qpid.server.protocol.v0_8.MessageConverter_v0_8_to_Internal \ No newline at end of file
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java
index 2243cbff11..c805956b83 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java
@@ -28,11 +28,11 @@ import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.flow.LimitlessCreditManager;
import org.apache.qpid.server.flow.Pre0_10CreditManager;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.util.BrokerTestHelper;
@@ -40,6 +40,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
import java.util.ArrayList;
+import java.util.EnumSet;
import java.util.Set;
/**
@@ -47,7 +48,8 @@ import java.util.Set;
*/
public class AckTest extends QpidTestCase
{
- private Subscription _subscription;
+ private ConsumerTarget_0_8 _subscriptionTarget;
+ private Consumer _consumer;
private AMQProtocolSession _protocolSession;
@@ -86,7 +88,6 @@ public class AckTest extends QpidTestCase
private void publishMessages(int count, boolean persistent) throws AMQException
{
- _queue.registerSubscription(_subscription,false);
for (int i = 1; i <= count; i++)
{
// AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
@@ -144,7 +145,7 @@ public class AckTest extends QpidTestCase
try
{
- _queue.enqueue(message);
+ _queue.enqueue(message,null);
}
catch (AMQException e)
{
@@ -178,7 +179,13 @@ public class AckTest extends QpidTestCase
*/
public void testAckChannelAssociationTest() throws AMQException
{
- _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true, null, false, new LimitlessCreditManager());
+ _subscriptionTarget = ConsumerTarget_0_8.createAckTarget(_channel,
+ DEFAULT_CONSUMER_TAG,
+ null,
+ new LimitlessCreditManager());
+ _consumer = _queue.addConsumer(_subscriptionTarget, null, AMQMessage.class, DEFAULT_CONSUMER_TAG.toString(),
+ EnumSet.of(Consumer.Option.SEES_REQUEUES,
+ Consumer.Option.ACQUIRES));
final int msgCount = 10;
publishMessages(msgCount, true);
UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap();
@@ -190,8 +197,8 @@ public class AckTest extends QpidTestCase
{
assertTrue(deliveryTag == i);
i++;
- QueueEntry unackedMsg = map.get(deliveryTag);
- assertTrue(unackedMsg.getQueue() == _queue);
+ MessageInstance unackedMsg = map.get(deliveryTag);
+ assertTrue(unackedMsg.getOwningResource() == _queue);
}
}
@@ -202,7 +209,16 @@ public class AckTest extends QpidTestCase
public void testNoAckMode() throws AMQException
{
// false arg means no acks expected
- _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, false, null, false, new LimitlessCreditManager());
+ _subscriptionTarget = ConsumerTarget_0_8.createNoAckTarget(_channel,
+ DEFAULT_CONSUMER_TAG,
+ null,
+ new LimitlessCreditManager());
+ _consumer = _queue.addConsumer(_subscriptionTarget,
+ null,
+ AMQMessage.class,
+ DEFAULT_CONSUMER_TAG.toString(),
+ EnumSet.of(Consumer.Option.SEES_REQUEUES,
+ Consumer.Option.ACQUIRES));
final int msgCount = 10;
publishMessages(msgCount);
UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap();
@@ -218,7 +234,13 @@ public class AckTest extends QpidTestCase
public void testPersistentNoAckMode() throws AMQException
{
// false arg means no acks expected
- _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, false,null,false, new LimitlessCreditManager());
+
+ _subscriptionTarget = ConsumerTarget_0_8.createNoAckTarget(_channel,
+ DEFAULT_CONSUMER_TAG,
+ null,
+ new LimitlessCreditManager());
+ _consumer = _queue.addConsumer(_subscriptionTarget, null, AMQMessage.class, DEFAULT_CONSUMER_TAG.toString(),
+ EnumSet.of(Consumer.Option.SEES_REQUEUES, Consumer.Option.ACQUIRES));
final int msgCount = 10;
publishMessages(msgCount, true);
@@ -235,7 +257,15 @@ public class AckTest extends QpidTestCase
*/
public void testSingleAckReceivedTest() throws AMQException
{
- _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager());
+
+ _subscriptionTarget = ConsumerTarget_0_8.createAckTarget(_channel,
+ DEFAULT_CONSUMER_TAG,
+ null,
+ new LimitlessCreditManager());
+ _consumer = _queue.addConsumer(_subscriptionTarget, null, AMQMessage.class, DEFAULT_CONSUMER_TAG.toString(),
+ EnumSet.of(Consumer.Option.SEES_REQUEUES,
+ Consumer.Option.ACQUIRES));
+
final int msgCount = 10;
publishMessages(msgCount);
@@ -248,8 +278,8 @@ public class AckTest extends QpidTestCase
for (long deliveryTag : deliveryTagSet)
{
assertTrue(deliveryTag == i);
- QueueEntry unackedMsg = map.get(deliveryTag);
- assertTrue(unackedMsg.getQueue() == _queue);
+ MessageInstance unackedMsg = map.get(deliveryTag);
+ assertTrue(unackedMsg.getOwningResource() == _queue);
// 5 is the delivery tag of the message that *should* be removed
if (++i == 5)
{
@@ -264,7 +294,15 @@ public class AckTest extends QpidTestCase
*/
public void testMultiAckReceivedTest() throws AMQException
{
- _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager());
+
+ _subscriptionTarget = ConsumerTarget_0_8.createAckTarget(_channel,
+ DEFAULT_CONSUMER_TAG,
+ null,
+ new LimitlessCreditManager());
+ _consumer = _queue.addConsumer(_subscriptionTarget, null, AMQMessage.class, DEFAULT_CONSUMER_TAG.toString(),
+ EnumSet.of(Consumer.Option.SEES_REQUEUES,
+ Consumer.Option.ACQUIRES));
+
final int msgCount = 10;
publishMessages(msgCount);
@@ -279,8 +317,8 @@ public class AckTest extends QpidTestCase
for (long deliveryTag : deliveryTagSet)
{
assertTrue(deliveryTag == i + 5);
- QueueEntry unackedMsg = map.get(deliveryTag);
- assertTrue(unackedMsg.getQueue() == _queue);
+ MessageInstance unackedMsg = map.get(deliveryTag);
+ assertTrue(unackedMsg.getOwningResource() == _queue);
++i;
}
}
@@ -290,7 +328,15 @@ public class AckTest extends QpidTestCase
*/
public void testMultiAckAllReceivedTest() throws AMQException
{
- _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager());
+
+ _subscriptionTarget = ConsumerTarget_0_8.createAckTarget(_channel,
+ DEFAULT_CONSUMER_TAG,
+ null,
+ new LimitlessCreditManager());
+ _consumer = _queue.addConsumer(_subscriptionTarget, null, AMQMessage.class, DEFAULT_CONSUMER_TAG.toString(),
+ EnumSet.of(Consumer.Option.SEES_REQUEUES,
+ Consumer.Option.ACQUIRES));
+
final int msgCount = 10;
publishMessages(msgCount);
@@ -303,8 +349,8 @@ public class AckTest extends QpidTestCase
for (long deliveryTag : deliveryTagSet)
{
assertTrue(deliveryTag == i + 5);
- QueueEntry unackedMsg = map.get(deliveryTag);
- assertTrue(unackedMsg.getQueue() == _queue);
+ MessageInstance unackedMsg = map.get(deliveryTag);
+ assertTrue(unackedMsg.getOwningResource() == _queue);
++i;
}
}
@@ -319,12 +365,16 @@ public class AckTest extends QpidTestCase
// Send 10 messages
Pre0_10CreditManager creditManager = new Pre0_10CreditManager(0l, 1);
- _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession,
- DEFAULT_CONSUMER_TAG, true, null, false, creditManager);
+
+ _subscriptionTarget = ConsumerTarget_0_8.createAckTarget(_channel, DEFAULT_CONSUMER_TAG, null, creditManager);
+ _consumer = _queue.addConsumer(_subscriptionTarget, null, AMQMessage.class, DEFAULT_CONSUMER_TAG.toString(),
+ EnumSet.of(Consumer.Option.SEES_REQUEUES,
+ Consumer.Option.ACQUIRES));
+
final int msgCount = 1;
publishMessages(msgCount);
- _queue.deliverAsync(_subscription);
+ _consumer.externalStateChange();
_channel.acknowledgeMessage(1, false);
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java
index bb5fecdfb4..f47525097e 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java
@@ -24,7 +24,7 @@ package org.apache.qpid.server.protocol.v0_8;
import org.apache.qpid.AMQException;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.util.BrokerTestHelper;
@@ -36,7 +36,7 @@ import java.util.List;
public class AcknowledgeTest extends QpidTestCase
{
private AMQChannel _channel;
- private SimpleAMQQueue _queue;
+ private AMQQueue _queue;
private MessageStore _messageStore;
private String _queueName;
@@ -79,7 +79,7 @@ public class AcknowledgeTest extends QpidTestCase
return (InternalTestProtocolSession)_channel.getProtocolSession();
}
- private SimpleAMQQueue getQueue()
+ private AMQQueue getQueue()
{
return _queue;
}
@@ -140,7 +140,7 @@ public class AcknowledgeTest extends QpidTestCase
assertEquals("Channel should have no unacked msgs ", 0, getChannel().getUnacknowledgedMessageMap().size());
//Subscribe to the queue
- AMQShortString subscriber = _channel.subscribeToQueue(null, _queue, true, null, false, true);
+ AMQShortString subscriber = _channel.consumeFromSource(null, _queue, true, null, true, false);
getQueue().deliverAsync();
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java
index 36a57fa05f..aa5a75396a 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java
@@ -23,20 +23,22 @@ package org.apache.qpid.server.protocol.v0_8;
import junit.framework.TestCase;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.MockAMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.queue.QueueEntryIterator;
-import org.apache.qpid.server.queue.SimpleQueueEntryList;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.TestMemoryMessageStore;
-import org.apache.qpid.server.subscription.MockSubscription;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.consumer.Consumer;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
/**
* QPID-1385 : Race condition between added to unacked map and resending due to a rollback.
*
@@ -59,40 +61,50 @@ public class ExtractResendAndRequeueTest extends TestCase
private UnacknowledgedMessageMapImpl _unacknowledgedMessageMap;
private static final int INITIAL_MSG_COUNT = 10;
- private AMQQueue _queue = new MockAMQQueue(getName());
- private MessageStore _messageStore = new TestMemoryMessageStore();
- private LinkedList<QueueEntry> _referenceList = new LinkedList<QueueEntry>();
+ private AMQQueue _queue;
+ private LinkedList<MessageInstance> _referenceList = new LinkedList<MessageInstance>();
+ private Consumer _consumer;
+ private boolean _queueDeleted;
@Override
public void setUp() throws AMQException
{
+ _queueDeleted = false;
_unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(100);
+ _queue = mock(AMQQueue.class);
+ when(_queue.getName()).thenReturn(getName());
+ when(_queue.isDeleted()).thenReturn(_queueDeleted);
+ _consumer = mock(Consumer.class);
+ when(_consumer.getId()).thenReturn(Consumer.SUB_ID_GENERATOR.getAndIncrement());
+
long id = 0;
- SimpleQueueEntryList list = new SimpleQueueEntryList(_queue);
// Add initial messages to QueueEntryList
for (int count = 0; count < INITIAL_MSG_COUNT; count++)
{
- AMQMessage msg = new MockAMQMessage(id);
-
- list.add(msg);
-
+ ServerMessage msg = mock(ServerMessage.class);
+ when(msg.getMessageNumber()).thenReturn(id);
+ final QueueEntry entry = mock(QueueEntry.class);
+ when(entry.getMessage()).thenReturn(msg);
+ when(entry.getQueue()).thenReturn(_queue);
+ when(entry.isQueueDeleted()).thenReturn(_queueDeleted);
+ doAnswer(new Answer()
+ {
+ @Override
+ public Object answer(final InvocationOnMock invocation) throws Throwable
+ {
+ when(entry.isDeleted()).thenReturn(true);
+ return null;
+ }
+ }).when(entry).delete();
+
+ _unacknowledgedMessageMap.add(id, entry);
+ _referenceList.add(entry);
//Increment ID;
id++;
}
- // Iterate through the QueueEntryList and add entries to unacknowledgedMessageMap and referenceList
- QueueEntryIterator queueEntries = list.iterator();
- while(queueEntries.advance())
- {
- QueueEntry entry = queueEntries.getNode();
- _unacknowledgedMessageMap.add(entry.getMessage().getMessageNumber(), entry);
-
- // Store the entry for future inspection
- _referenceList.add(entry);
- }
-
assertEquals("Map does not contain correct setup data", INITIAL_MSG_COUNT, _unacknowledgedMessageMap.size());
}
@@ -103,17 +115,14 @@ public class ExtractResendAndRequeueTest extends TestCase
*
* @return Subscription that performed the acquire
*/
- private Subscription createSubscriptionAndAcquireMessages(LinkedList<QueueEntry> messageList)
+ private void acquireMessages(LinkedList<MessageInstance> messageList)
{
- Subscription subscription = new MockSubscription();
- // Aquire messages in subscription
- for (QueueEntry entry : messageList)
+ // Acquire messages in subscription
+ for(MessageInstance entry : messageList)
{
- entry.acquire(subscription);
+ when(entry.getDeliveredConsumer()).thenReturn(_consumer);
}
-
- return subscription;
}
/**
@@ -128,14 +137,14 @@ public class ExtractResendAndRequeueTest extends TestCase
public void testResend() throws AMQException
{
//We don't need the subscription object here.
- createSubscriptionAndAcquireMessages(_referenceList);
+ acquireMessages(_referenceList);
- final Map<Long, QueueEntry> msgToRequeue = new LinkedHashMap<Long, QueueEntry>();
- final Map<Long, QueueEntry> msgToResend = new LinkedHashMap<Long, QueueEntry>();
+ final Map<Long, MessageInstance> msgToRequeue = new LinkedHashMap<Long, MessageInstance>();
+ final Map<Long, MessageInstance> msgToResend = new LinkedHashMap<Long, MessageInstance>();
// requeueIfUnableToResend doesn't matter here.
_unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, true, _messageStore));
+ msgToResend));
assertEquals("Message count for resend not correct.", INITIAL_MSG_COUNT, msgToResend.size());
assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size());
@@ -154,100 +163,22 @@ public class ExtractResendAndRequeueTest extends TestCase
*/
public void testRequeueDueToSubscriptionClosure() throws AMQException
{
- Subscription subscription = createSubscriptionAndAcquireMessages(_referenceList);
+ acquireMessages(_referenceList);
// Close subscription
- subscription.close();
+ when(_consumer.isClosed()).thenReturn(true);
- final Map<Long, QueueEntry> msgToRequeue = new LinkedHashMap<Long, QueueEntry>();
- final Map<Long, QueueEntry> msgToResend = new LinkedHashMap<Long, QueueEntry>();
+ final Map<Long, MessageInstance> msgToRequeue = new LinkedHashMap<Long, MessageInstance>();
+ final Map<Long, MessageInstance> msgToResend = new LinkedHashMap<Long, MessageInstance>();
// requeueIfUnableToResend doesn't matter here.
_unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, true, _messageStore));
+ msgToResend));
assertEquals("Message count for resend not correct.", 0, msgToResend.size());
assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size());
assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size());
}
- /**
- * If the subscription is null, due to message being retrieved via a GET, And we request that messages are requeued
- * requeueIfUnableToResend(set to true) then all messages should be sent to the msgToRequeue map.
- *
- * @throws AMQException the visit interface throws this
- */
-
- public void testRequeueDueToMessageHavingNoConsumerTag() throws AMQException
- {
- final Map<Long, QueueEntry> msgToRequeue = new LinkedHashMap<Long, QueueEntry>();
- final Map<Long, QueueEntry> msgToResend = new LinkedHashMap<Long, QueueEntry>();
-
- // requeueIfUnableToResend = true so all messages should go to msgToRequeue
- _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, true, _messageStore));
-
- assertEquals("Message count for resend not correct.", 0, msgToResend.size());
- assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size());
- assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size());
- }
-
- /**
- * If the subscription is null, due to message being retrieved via a GET, And we request that we don't
- * requeueIfUnableToResend(set to false) then all messages should be dropped as we do not have a dead letter queue.
- *
- * @throws AMQException the visit interface throws this
- */
-
- public void testDrop() throws AMQException
- {
- final Map<Long, QueueEntry> msgToRequeue = new LinkedHashMap<Long, QueueEntry>();
- final Map<Long, QueueEntry> msgToResend = new LinkedHashMap<Long, QueueEntry>();
-
- // requeueIfUnableToResend = false so all messages should be dropped all maps should be empty
- _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, false, _messageStore));
-
- assertEquals("Message count for resend not correct.", 0, msgToResend.size());
- assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size());
- assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size());
-
-
- for (QueueEntry entry : _referenceList)
- {
- assertTrue("Message was not discarded", entry.isDeleted());
- }
-
- }
-
- /**
- * If the subscription is null, due to message being retrieved via a GET, AND the queue upon which the message was
- * delivered has been deleted then it is not possible to requeue. Currently we simply discard the message but in the
- * future we may wish to dead letter the message.
- *
- * Validate that at the end of the visit all Maps are empty and all messages are marked as deleted
- *
- * @throws AMQException the visit interface throws this
- */
- public void testDiscard() throws AMQException
- {
- final Map<Long, QueueEntry> msgToRequeue = new LinkedHashMap<Long, QueueEntry>();
- final Map<Long, QueueEntry> msgToResend = new LinkedHashMap<Long, QueueEntry>();
-
- _queue.delete();
-
- // requeueIfUnableToResend : value doesn't matter here as queue has been deleted
- _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, false, _messageStore));
-
- assertEquals("Message count for resend not correct.", 0, msgToResend.size());
- assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size());
- assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size());
-
- for (QueueEntry entry : _referenceList)
- {
- assertTrue("Message was not discarded", entry.isDeleted());
- }
- }
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java
index ef0837b3c6..1fad8fb41f 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java
@@ -47,11 +47,9 @@ import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter;
-import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import org.apache.qpid.server.security.auth.UsernamePrincipal;
-import org.apache.qpid.server.subscription.ClientDeliveryMethod;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Sender;
import org.apache.qpid.transport.network.NetworkConnection;
@@ -60,7 +58,7 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
{
private static final Logger _logger = Logger.getLogger(InternalTestProtocolSession.class);
// ChannelID(LIST) -> LinkedList<Pair>
- private final Map<Integer, Map<AMQShortString, LinkedList<DeliveryPair>>> _channelDelivers;
+ private final Map<Integer, Map<String, LinkedList<DeliveryPair>>> _channelDelivers;
private AtomicInteger _deliveryCount = new AtomicInteger(0);
private static final AtomicLong ID_GENERATOR = new AtomicLong(0);
@@ -68,7 +66,7 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
{
super(broker, new TestNetworkConnection(), ID_GENERATOR.getAndIncrement(), null, null);
- _channelDelivers = new HashMap<Integer, Map<AMQShortString, LinkedList<DeliveryPair>>>();
+ _channelDelivers = new HashMap<Integer, Map<String, LinkedList<DeliveryPair>>>();
setTestAuthorizedSubject();
setVirtualHost(virtualHost);
@@ -117,7 +115,7 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
{
synchronized (_channelDelivers)
{
- List<DeliveryPair> all =_channelDelivers.get(channelId).get(consumerTag);
+ List<DeliveryPair> all =_channelDelivers.get(channelId).get(AMQShortString.toString(consumerTag));
if (all == null)
{
@@ -153,23 +151,23 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
synchronized (_channelDelivers)
{
- Map<AMQShortString, LinkedList<DeliveryPair>> consumers = _channelDelivers.get(channelId);
+ Map<String, LinkedList<DeliveryPair>> consumers = _channelDelivers.get(channelId);
if (consumers == null)
{
- consumers = new HashMap<AMQShortString, LinkedList<DeliveryPair>>();
+ consumers = new HashMap<String, LinkedList<DeliveryPair>>();
_channelDelivers.put(channelId, consumers);
}
- LinkedList<DeliveryPair> consumerDelivers = consumers.get(consumerTag);
+ LinkedList<DeliveryPair> consumerDelivers = consumers.get(AMQShortString.toString(consumerTag));
if (consumerDelivers == null)
{
consumerDelivers = new LinkedList<DeliveryPair>();
- consumers.put(consumerTag, consumerDelivers);
+ consumers.put(consumerTag.toString(), consumerDelivers);
}
- consumerDelivers.add(new DeliveryPair(deliveryTag, (AMQMessage)msg));
+ consumerDelivers.add(new DeliveryPair(deliveryTag, msg));
}
}
@@ -247,27 +245,27 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
@Override
- public void deliverToClient(Subscription sub, ServerMessage message,
+ public void deliverToClient(Consumer sub, ServerMessage message,
InstanceProperties props, long deliveryTag) throws AMQException
{
_deliveryCount.incrementAndGet();
synchronized (_channelDelivers)
{
- Map<AMQShortString, LinkedList<DeliveryPair>> consumers = _channelDelivers.get(_channelId);
+ Map<String, LinkedList<DeliveryPair>> consumers = _channelDelivers.get(_channelId);
if (consumers == null)
{
- consumers = new HashMap<AMQShortString, LinkedList<DeliveryPair>>();
+ consumers = new HashMap<String, LinkedList<DeliveryPair>>();
_channelDelivers.put(_channelId, consumers);
}
- LinkedList<DeliveryPair> consumerDelivers = consumers.get(((SubscriptionImpl)sub).getConsumerTag());
+ LinkedList<DeliveryPair> consumerDelivers = consumers.get(sub.getName());
if (consumerDelivers == null)
{
consumerDelivers = new LinkedList<DeliveryPair>();
- consumers.put(((SubscriptionImpl)sub).getConsumerTag(), consumerDelivers);
+ consumers.put(sub.getName(), consumerDelivers);
}
consumerDelivers.add(new DeliveryPair(deliveryTag, message));
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java
index 8c716a0b56..dc687e1075 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java
@@ -26,10 +26,8 @@ import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.util.BrokerTestHelper;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -39,7 +37,7 @@ import java.util.List;
public class QueueBrowserUsesNoAckTest extends QpidTestCase
{
private AMQChannel _channel;
- private SimpleAMQQueue _queue;
+ private AMQQueue _queue;
private MessageStore _messageStore;
private String _queueName;
@@ -82,7 +80,7 @@ public class QueueBrowserUsesNoAckTest extends QpidTestCase
return (InternalTestProtocolSession)_channel.getProtocolSession();
}
- private SimpleAMQQueue getQueue()
+ private AMQQueue getQueue()
{
return _queue;
}
@@ -130,8 +128,7 @@ public class QueueBrowserUsesNoAckTest extends QpidTestCase
//Check the process didn't suspend the subscription as this would
// indicate we are using the prefetch credit. i.e. using acks not No-Ack
assertTrue("The subscription has been suspended",
- !getChannel().getSubscription(browser).getState()
- .equals(Subscription.State.SUSPENDED));
+ !getChannel().getSubscription(browser).isSuspended());
}
private void checkStoreContents(int messageCount)
@@ -144,6 +141,6 @@ public class QueueBrowserUsesNoAckTest extends QpidTestCase
FieldTable filters = new FieldTable();
filters.put(AMQPFilterTypes.NO_CONSUME.getValue(), true);
- return channel.subscribeToQueue(null, queue, true, filters, false, true);
+ return channel.consumeFromSource(null, queue, true, filters, true, false);
}
}
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImplTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImplTest.java
deleted file mode 100644
index e0d1b28007..0000000000
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImplTest.java
+++ /dev/null
@@ -1,96 +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.server.protocol.v0_8;
-
-import org.apache.qpid.common.AMQPFilterTypes;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.logging.UnitTestMessageLogger;
-import org.apache.qpid.server.logging.actors.GenericActor;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.util.BrokerTestHelper;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class SubscriptionFactoryImplTest extends QpidTestCase
-{
- private AMQChannel _channel;
- private AMQProtocolSession _session;
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
- BrokerTestHelper.setUp();
- _channel = BrokerTestHelper_0_8.createChannel();
- _session = _channel.getProtocolSession();
- GenericActor.setDefaultMessageLogger(new UnitTestMessageLogger(false));
- }
-
- @Override
- public void tearDown() throws Exception
- {
- try
- {
- if (_channel != null)
- {
- _channel.getVirtualHost().close();
- }
- }
- finally
- {
- BrokerTestHelper.tearDown();
- super.tearDown();
- }
- }
-
- /**
- * Tests that while creating Subscriptions of various types, the
- * ID numbers assigned are allocated from a common sequence
- * (in increasing order).
- */
- public void testDifferingSubscriptionTypesShareCommonIdNumberingSequence() throws Exception
- {
- //create a No-Ack subscription, get the first Subscription ID
- long previousId = 0;
- Subscription noAckSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, _session, new AMQShortString("1"), false, null, false, _channel.getCreditManager());
- previousId = noAckSub.getSubscriptionID();
-
- //create an ack subscription, verify the next Subscription ID is used
- Subscription ackSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, _session, new AMQShortString("1"), true, null, false, _channel.getCreditManager());
- assertEquals("Unexpected Subscription ID allocated", previousId + 1, ackSub.getSubscriptionID());
- previousId = ackSub.getSubscriptionID();
-
- //create a browser subscription
- FieldTable filters = new FieldTable();
- filters.put(AMQPFilterTypes.NO_CONSUME.getValue(), true);
- Subscription browserSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, _session, new AMQShortString("1"), true, null, false, _channel.getCreditManager());
- assertEquals("Unexpected Subscription ID allocated", previousId + 1, browserSub.getSubscriptionID());
- previousId = browserSub.getSubscriptionID();
-
- //create an BasicGet NoAck subscription
- Subscription getNoAckSub = SubscriptionFactoryImpl.INSTANCE.createBasicGetNoAckSubscription(_channel, _session, new AMQShortString("1"), null, false,
- _channel.getCreditManager(),_channel.getClientDeliveryMethod(), _channel.getRecordDeliveryMethod());
- assertEquals("Unexpected Subscription ID allocated", previousId + 1, getNoAckSub.getSubscriptionID());
- previousId = getNoAckSub.getSubscriptionID();
-
- }
-
-}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/pom.xml b/qpid/java/broker-plugins/amqp-1-0-protocol/pom.xml
index 97db18011d..c3b28c5ee4 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/pom.xml
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/pom.xml
@@ -16,36 +16,37 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-amqp-1-0-protocol</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 1-0 Protocol Broker Plug-in</name>
+ <description>AMQP 1-0 protocol broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-amqp-1-0-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
index 4082f22e9c..41e2fef03f 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
@@ -34,6 +34,7 @@ import org.apache.qpid.server.model.Transport;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.stats.StatisticsCounter;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.ArrayList;
@@ -53,16 +54,8 @@ public class Connection_1_0 implements ConnectionEventListener
private final Collection<Session_1_0> _sessions = Collections.synchronizedCollection(new ArrayList<Session_1_0>());
private final Object _reference = new Object();
-
-
- public static interface Task
- {
- public void doTask(Connection_1_0 connection);
- }
-
-
- private List<Task> _closeTasks =
- Collections.synchronizedList(new ArrayList<Task>());
+ private List<Action<Connection_1_0>> _closeTasks =
+ Collections.synchronizedList(new ArrayList<Action<Connection_1_0>>());
@@ -98,26 +91,26 @@ public class Connection_1_0 implements ConnectionEventListener
_sessions.remove(session);
}
- void removeConnectionCloseTask(final Task task)
+ void removeConnectionCloseTask(final Action<Connection_1_0> task)
{
_closeTasks.remove( task );
}
- void addConnectionCloseTask(final Task task)
+ void addConnectionCloseTask(final Action<Connection_1_0> task)
{
_closeTasks.add( task );
}
public void closeReceived()
{
- List<Task> taskCopy;
+ List<Action<Connection_1_0>> taskCopy;
synchronized (_closeTasks)
{
- taskCopy = new ArrayList<Task>(_closeTasks);
+ taskCopy = new ArrayList<Action<Connection_1_0>>(_closeTasks);
}
- for(Task task : taskCopy)
+ for(Action<Connection_1_0> task : taskCopy)
{
- task.doTask(this);
+ task.performAction(this);
}
synchronized (_closeTasks)
{
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
index 6a3f5b46e1..027c40aabe 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
@@ -20,12 +20,6 @@
*/
package org.apache.qpid.server.protocol.v1_0;
-import java.nio.ByteBuffer;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.ReentrantLock;
import org.apache.qpid.AMQException;
import org.apache.qpid.amqp_1_0.codec.ValueHandler;
import org.apache.qpid.amqp_1_0.messaging.SectionEncoder;
@@ -41,153 +35,84 @@ import org.apache.qpid.amqp_1_0.type.messaging.Accepted;
import org.apache.qpid.amqp_1_0.type.messaging.Header;
import org.apache.qpid.amqp_1_0.type.messaging.Modified;
import org.apache.qpid.amqp_1_0.type.messaging.Released;
-import org.apache.qpid.amqp_1_0.type.messaging.Source;
-import org.apache.qpid.amqp_1_0.type.messaging.StdDistMode;
import org.apache.qpid.amqp_1_0.type.transaction.TransactionalState;
import org.apache.qpid.amqp_1_0.type.transport.SenderSettleMode;
import org.apache.qpid.amqp_1_0.type.transport.Transfer;
-import org.apache.qpid.server.plugin.MessageConverter;
-import org.apache.qpid.server.protocol.MessageConverterRegistry;
-import org.apache.qpid.server.filter.FilterManager;
-import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.plugin.MessageConverter;
import org.apache.qpid.server.protocol.AMQSessionModel;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.protocol.MessageConverterRegistry;
+import org.apache.qpid.server.consumer.AbstractConsumerTarget;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.txn.ServerTransaction;
-class
- Subscription_1_0 implements Subscription
-{
- private SendingLink_1_0 _link;
-
- private AMQQueue _queue;
-
- private final AtomicReference<State> _state = new AtomicReference<State>(State.SUSPENDED);
+import java.nio.ByteBuffer;
+import java.util.List;
- private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
- private final long _id;
+class ConsumerTarget_1_0 extends AbstractConsumerTarget
+{
private final boolean _acquires;
- private volatile AMQQueue.Context _queueContext;
- private Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
- private ReentrantLock _stateChangeLock = new ReentrantLock();
-
- private boolean _noLocal;
- private FilterManager _filters;
+ private SendingLink_1_0 _link;
private long _deliveryTag = 0L;
- private StateListener _stateListener;
private Binary _transactionId;
- private final AMQPDescribedTypeRegistry _typeRegistry = AMQPDescribedTypeRegistry.newInstance()
- .registerTransportLayer()
- .registerMessagingLayer()
- .registerTransactionLayer()
- .registerSecurityLayer();
- private SectionEncoder _sectionEncoder = new SectionEncoderImpl(_typeRegistry);
-
- public Subscription_1_0(final SendingLink_1_0 link, final QueueDestination destination)
- {
- this(link, destination, ((Source)link.getEndpoint().getSource()).getDistributionMode() != StdDistMode.COPY);
- }
+ private final AMQPDescribedTypeRegistry _typeRegistry;
+ private final SectionEncoder _sectionEncoder;
+ private Consumer _consumer;
- public Subscription_1_0(final SendingLink_1_0 link, final QueueDestination destination, boolean acquires)
+ public ConsumerTarget_1_0(final SendingLink_1_0 link,
+ boolean acquires)
{
+ super(State.SUSPENDED);
_link = link;
- _queue = destination.getQueue();
- _id = getEndpoint().getLocalHandle().longValue();
+ _typeRegistry = link.getEndpoint().getSession().getConnection().getDescribedTypeRegistry();
+ _sectionEncoder = new SectionEncoderImpl(_typeRegistry);
_acquires = acquires;
}
- private SendingLinkEndpoint getEndpoint()
- {
- return _link.getEndpoint();
- }
-
- public LogActor getLogActor()
- {
- return null; //TODO
- }
-
- public boolean isTransient()
- {
- return true; //TODO
- }
-
- public AMQQueue getQueue()
+ public Consumer getConsumer()
{
- return _queue;
+ return _consumer;
}
- public QueueEntry.SubscriptionAcquiredState getOwningState()
- {
- return _owningState;
- }
-
- public void setQueue(final AMQQueue queue, final boolean exclusive)
- {
- //TODO
- }
-
- public void setNoLocal(final boolean noLocal)
- {
- _noLocal = noLocal;
- }
-
- public long getSubscriptionID()
+ private SendingLinkEndpoint getEndpoint()
{
- return _id;
+ return _link.getEndpoint();
}
public boolean isSuspended()
{
- return _link.getSession().getConnectionModel().isStopped() || !isActive();// || !getEndpoint().hasCreditToSend();
+ return _link.getSession().getConnectionModel().isStopped() || getState() != State.ACTIVE;// || !getEndpoint().hasCreditToSend();
}
- public boolean hasInterest(final QueueEntry entry)
+ public boolean close()
{
- if(_noLocal && entry.getMessage().getConnectionReference() == getSession().getConnection().getReference())
+ boolean closed = false;
+ State state = getState();
+
+ getConsumer().getSendLock();
+ try
{
- return false;
+ while(!closed && state != State.CLOSED)
+ {
+ closed = updateState(state, State.CLOSED);
+ if(!closed)
+ {
+ state = getState();
+ }
+ }
+ return closed;
}
- else if(!(entry.getMessage() instanceof Message_1_0)
- && MessageConverterRegistry.getConverter(entry.getMessage().getClass(), Message_1_0.class)==null)
+ finally
{
- return false;
+ getConsumer().releaseSendLock();
}
- return checkFilters(entry);
-
- }
-
- private boolean checkFilters(final QueueEntry entry)
- {
- return (_filters == null) || _filters.allAllow(entry.asFilterable());
- }
-
- public boolean isClosed()
- {
- return !getEndpoint().isAttached();
- }
-
- public boolean acquires()
- {
- return _acquires;
- }
-
- public boolean seesRequeues()
- {
- // TODO
- return acquires();
- }
-
- public void close()
- {
- getEndpoint().detach();
}
- public void send(QueueEntry entry, boolean batch) throws AMQException
+ public void send(MessageInstance entry, boolean batch) throws AMQException
{
// TODO
send(entry);
@@ -198,7 +123,7 @@ class
// TODO
}
- public void send(final QueueEntry queueEntry) throws AMQException
+ public void send(final MessageInstance queueEntry) throws AMQException
{
ServerMessage serverMessage = queueEntry.getMessage();
Message_1_0 message;
@@ -209,7 +134,7 @@ class
else
{
final MessageConverter converter = MessageConverterRegistry.getConverter(serverMessage.getClass(), Message_1_0.class);
- message = (Message_1_0) converter.convert(serverMessage, queueEntry.getQueue().getVirtualHost());
+ message = (Message_1_0) converter.convert(serverMessage, _link.getVirtualHost());
}
Transfer transfer = new Transfer();
@@ -329,7 +254,7 @@ class
public void onRollback()
{
- if(queueEntry.isAcquiredBy(Subscription_1_0.this))
+ if(queueEntry.isAcquiredBy(getConsumer()))
{
queueEntry.release();
_link.getEndpoint().updateDisposition(tag, (DeliveryState)null, true);
@@ -352,14 +277,14 @@ class
}
- public void queueDeleted(final AMQQueue queue)
+ public void queueDeleted()
{
//TODO
getEndpoint().setSource(null);
getEndpoint().detach();
}
- public boolean wouldSuspend(final QueueEntry msg)
+ public boolean allocateCredit(final ServerMessage msg)
{
synchronized (_link.getLock())
{
@@ -369,103 +294,32 @@ class
suspend();
}
- return !hasCredit;
+ return hasCredit;
}
}
- public boolean trySendLock()
- {
- return _stateChangeLock.tryLock();
- }
public void suspend()
{
synchronized(_link.getLock())
{
- if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
- {
- _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
- }
+ updateState(State.ACTIVE, State.SUSPENDED);
}
}
- public void getSendLock()
- {
- _stateChangeLock.lock();
- }
-
- public void releaseSendLock()
- {
- _stateChangeLock.unlock();
- }
-
- public void releaseQueueEntry(QueueEntry queueEntryImpl)
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public void onDequeue(final QueueEntry queueEntry)
+ public void restoreCredit(final ServerMessage message)
{
//TODO
}
- public void restoreCredit(final QueueEntry queueEntry)
- {
- //TODO
- }
-
- public void setStateListener(final StateListener listener)
- {
- _stateListener = listener;
- }
-
- public State getState()
- {
- return _state.get();
- }
-
- public AMQQueue.Context getQueueContext()
- {
- return _queueContext;
- }
-
- public void setQueueContext(AMQQueue.Context queueContext)
- {
- _queueContext = queueContext;
- }
-
-
- public boolean isActive()
- {
- return getState() == State.ACTIVE;
- }
-
- public void set(String key, Object value)
- {
- _properties.put(key, value);
- }
-
- public Object get(String key)
- {
- return _properties.get(key);
- }
-
- public boolean isSessionTransactional()
- {
- return false; //TODO
- }
-
public void queueEmpty()
{
synchronized(_link.getLock())
{
if(_link.drained())
{
- if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
- {
- _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
- }
+ updateState(State.ACTIVE, State.SUSPENDED);
}
}
}
@@ -476,10 +330,7 @@ class
{
if(isSuspended() && getEndpoint() != null)
{
- if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE))
- {
- _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE);
- }
+ updateState(State.SUSPENDED, State.ACTIVE);
_transactionId = _link.getTransactionId();
}
}
@@ -493,10 +344,10 @@ class
private class DispositionAction implements UnsettledAction
{
- private final QueueEntry _queueEntry;
+ private final MessageInstance _queueEntry;
private final Binary _deliveryTag;
- public DispositionAction(Binary tag, QueueEntry queueEntry)
+ public DispositionAction(Binary tag, MessageInstance queueEntry)
{
_deliveryTag = tag;
_queueEntry = queueEntry;
@@ -527,13 +378,13 @@ class
if(outcome instanceof Accepted)
{
- txn.dequeue(_queueEntry.getQueue(), _queueEntry.getMessage(),
+ txn.dequeue(_queueEntry.getOwningResource(), _queueEntry.getMessage(),
new ServerTransaction.Action()
{
public void postCommit()
{
- if(_queueEntry.isAcquiredBy(Subscription_1_0.this))
+ if(_queueEntry.isAcquiredBy(getConsumer()))
{
_queueEntry.delete();
}
@@ -618,7 +469,7 @@ class
private class DoNothingAction implements UnsettledAction
{
public DoNothingAction(final Binary tag,
- final QueueEntry queueEntry)
+ final MessageInstance queueEntry)
{
}
@@ -640,35 +491,22 @@ class
}
}
- public FilterManager getFilters()
- {
- return _filters;
- }
-
- public void setFilters(final FilterManager filters)
- {
- _filters = filters;
- }
-
@Override
public AMQSessionModel getSessionModel()
{
- // TODO
return getSession();
}
@Override
- public long getBytesOut()
+ public void consumerAdded(final Consumer sub)
{
- // TODO
- return 0;
+ _consumer = sub;
}
@Override
- public long getMessagesOut()
+ public void consumerRemoved(final Consumer sub)
{
- // TODO
- return 0;
+
}
@Override
@@ -685,10 +523,4 @@ class
return 0;
}
- @Override
- public String getConsumerName()
- {
- //TODO
- return "TODO";
- }
}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java
new file mode 100644
index 0000000000..f02908391a
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java
@@ -0,0 +1,140 @@
+/*
+ *
+ * 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.protocol.v1_0;
+
+import org.apache.qpid.amqp_1_0.messaging.SectionEncoder;
+import org.apache.qpid.amqp_1_0.type.Binary;
+import org.apache.qpid.amqp_1_0.type.Section;
+import org.apache.qpid.amqp_1_0.type.UnsignedByte;
+import org.apache.qpid.amqp_1_0.type.UnsignedInteger;
+import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue;
+import org.apache.qpid.amqp_1_0.type.messaging.ApplicationProperties;
+import org.apache.qpid.amqp_1_0.type.messaging.Data;
+import org.apache.qpid.amqp_1_0.type.messaging.Header;
+import org.apache.qpid.amqp_1_0.type.messaging.Properties;
+import org.apache.qpid.server.message.internal.InternalMessage;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+public class MessageConverter_Internal_to_v1_0 extends MessageConverter_to_1_0<InternalMessage>
+{
+ private static final Charset UTF_8 = Charset.forName("UTF-8");
+
+
+ public Class<InternalMessage> getInputClass()
+ {
+ return InternalMessage.class;
+ }
+
+
+ @Override
+ protected MessageMetaData_1_0 convertMetaData(final InternalMessage serverMessage,
+ final SectionEncoder sectionEncoder)
+ {
+ List<Section> sections = new ArrayList<Section>(3);
+ Header header = new Header();
+
+ header.setDurable(serverMessage.isPersistent());
+ header.setPriority(UnsignedByte.valueOf(serverMessage.getMessageHeader().getPriority()));
+ if(serverMessage.getExpiration() != 0l && serverMessage.getArrivalTime() !=0l && serverMessage.getExpiration() >= serverMessage.getArrivalTime())
+ {
+ header.setTtl(UnsignedInteger.valueOf(serverMessage.getExpiration()-serverMessage.getArrivalTime()));
+ }
+
+ sections.add(header);
+
+ Properties properties = new Properties();
+ properties.setCorrelationId(serverMessage.getMessageHeader().getCorrelationId());
+ properties.setCreationTime(new Date(serverMessage.getMessageHeader().getTimestamp()));
+ properties.setMessageId(serverMessage.getMessageHeader().getMessageId());
+ final String userId = serverMessage.getMessageHeader().getUserId();
+ if(userId != null)
+ {
+ properties.setUserId(new Binary(userId.getBytes(UTF_8)));
+ }
+ properties.setReplyTo(serverMessage.getMessageHeader().getReplyTo());
+
+ sections.add(properties);
+
+ if(!serverMessage.getMessageHeader().getHeaderNames().isEmpty())
+ {
+ ApplicationProperties applicationProperties = new ApplicationProperties(serverMessage.getMessageHeader().getHeaderMap() );
+ sections.add(applicationProperties);
+ }
+ return new MessageMetaData_1_0(sections, sectionEncoder);
+
+ }
+
+ protected Section getBodySection(final InternalMessage serverMessage, final String mimeType)
+ {
+ return convertToBody(serverMessage.getMessageBody());
+ }
+
+
+ @Override
+ public String getType()
+ {
+ return "Internal to v1-0";
+ }
+
+
+ public Section convertToBody(Object object)
+ {
+ if(object instanceof String)
+ {
+ return new AmqpValue(object);
+ }
+ else if(object instanceof byte[])
+ {
+ return new Data(new Binary((byte[])object));
+ }
+ else if(object instanceof Map)
+ {
+ return new AmqpValue(MessageConverter_to_1_0.fixMapValues((Map)object));
+ }
+ else if(object instanceof List)
+ {
+ return new AmqpValue(MessageConverter_to_1_0.fixListValues((List)object));
+ }
+ else
+ {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ try
+ {
+ ObjectOutputStream os = new ObjectOutputStream(bytesOut);
+ os.writeObject(object);
+ return new Data(new Binary(bytesOut.toByteArray()));
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java
index 78ca9ff2a6..a8a203b247 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java
@@ -23,7 +23,6 @@ package org.apache.qpid.server.protocol.v1_0;
import java.io.EOFException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
@@ -157,7 +156,7 @@ public abstract class MessageConverter_to_1_0<M extends ServerMessage> implement
}
}
- private static Map fixMapValues(final Map<String, Object> map)
+ static Map fixMapValues(final Map<String, Object> map)
{
for(Map.Entry<String,Object> entry : map.entrySet())
{
@@ -166,7 +165,7 @@ public abstract class MessageConverter_to_1_0<M extends ServerMessage> implement
return map;
}
- private static Object fixValue(final Object value)
+ static Object fixValue(final Object value)
{
if(value instanceof byte[])
{
@@ -186,7 +185,7 @@ public abstract class MessageConverter_to_1_0<M extends ServerMessage> implement
}
}
- private static List fixListValues(final List list)
+ static List fixListValues(final List list)
{
ListIterator iterator = list.listIterator();
while(iterator.hasNext())
@@ -199,83 +198,88 @@ public abstract class MessageConverter_to_1_0<M extends ServerMessage> implement
}
private StoredMessage<MessageMetaData_1_0> convertServerMessage(final MessageMetaData_1_0 metaData,
- final ServerMessage serverMessage,
+ final M serverMessage,
SectionEncoder sectionEncoder)
{
- final String mimeType = serverMessage.getMessageHeader().getMimeType();
- byte[] data = new byte[(int) serverMessage.getSize()];
- serverMessage.getContent(ByteBuffer.wrap(data), 0);
+ final String mimeType = serverMessage.getMessageHeader().getMimeType();
+ Section bodySection = getBodySection(serverMessage, mimeType);
- Section bodySection = convertMessageBody(mimeType, data);
+ final ByteBuffer allData = encodeConvertedMessage(metaData, bodySection, sectionEncoder);
- final ByteBuffer allData = encodeConvertedMessage(metaData, bodySection, sectionEncoder);
-
- return new StoredMessage<MessageMetaData_1_0>()
- {
- @Override
- public MessageMetaData_1_0 getMetaData()
- {
- return metaData;
- }
-
- @Override
- public long getMessageNumber()
- {
- return serverMessage.getMessageNumber();
- }
-
- @Override
- public void addContent(int offsetInMessage, ByteBuffer src)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getContent(int offsetInMessage, ByteBuffer dst)
- {
- ByteBuffer buf = allData.duplicate();
- buf.position(offsetInMessage);
- buf = buf.slice();
- int size;
- if(dst.remaining()<buf.remaining())
- {
- buf.limit(dst.remaining());
- size = dst.remaining();
- }
- else
+ return new StoredMessage<MessageMetaData_1_0>()
{
- size = buf.remaining();
- }
- dst.put(buf);
- return size;
- }
-
- @Override
- public ByteBuffer getContent(int offsetInMessage, int size)
- {
- ByteBuffer buf = allData.duplicate();
- buf.position(offsetInMessage);
- buf = buf.slice();
- if(size < buf.remaining())
- {
- buf.limit(size);
- }
- return buf;
- }
+ @Override
+ public MessageMetaData_1_0 getMetaData()
+ {
+ return metaData;
+ }
+
+ @Override
+ public long getMessageNumber()
+ {
+ return serverMessage.getMessageNumber();
+ }
+
+ @Override
+ public void addContent(int offsetInMessage, ByteBuffer src)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getContent(int offsetInMessage, ByteBuffer dst)
+ {
+ ByteBuffer buf = allData.duplicate();
+ buf.position(offsetInMessage);
+ buf = buf.slice();
+ int size;
+ if(dst.remaining()<buf.remaining())
+ {
+ buf.limit(dst.remaining());
+ size = dst.remaining();
+ }
+ else
+ {
+ size = buf.remaining();
+ }
+ dst.put(buf);
+ return size;
+ }
+
+ @Override
+ public ByteBuffer getContent(int offsetInMessage, int size)
+ {
+ ByteBuffer buf = allData.duplicate();
+ buf.position(offsetInMessage);
+ buf = buf.slice();
+ if(size < buf.remaining())
+ {
+ buf.limit(size);
+ }
+ return buf;
+ }
+
+ @Override
+ public StoreFuture flushToStore()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
- @Override
- public StoreFuture flushToStore()
- {
- throw new UnsupportedOperationException();
- }
+ protected Section getBodySection(final M serverMessage, final String mimeType)
+ {
+ byte[] data = new byte[(int) serverMessage.getSize()];
+ serverMessage.getContent(ByteBuffer.wrap(data), 0);
- @Override
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
- };
- }
+ return convertMessageBody(mimeType, data);
+ }
private ByteBuffer encodeConvertedMessage(MessageMetaData_1_0 metaData, Section bodySection, SectionEncoder sectionEncoder)
{
@@ -286,7 +290,7 @@ public abstract class MessageConverter_to_1_0<M extends ServerMessage> implement
Binary dataEncoding = sectionEncoder.getEncoding();
final ByteBuffer allData = ByteBuffer.allocate(headerSize + dataEncoding.getLength());
- metaData.writeToBuffer(0,allData);
+ metaData.writeToBuffer(allData);
allData.put(dataEncoding.getArray(),dataEncoding.getArrayOffset(),dataEncoding.getLength());
return allData;
}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java
new file mode 100644
index 0000000000..f639f98dba
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java
@@ -0,0 +1,281 @@
+/*
+ *
+ * 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.protocol.v1_0;
+
+import org.apache.qpid.amqp_1_0.messaging.SectionDecoderImpl;
+import org.apache.qpid.amqp_1_0.type.AmqpErrorException;
+import org.apache.qpid.amqp_1_0.type.Binary;
+import org.apache.qpid.amqp_1_0.type.Section;
+import org.apache.qpid.amqp_1_0.type.codec.AMQPDescribedTypeRegistry;
+import org.apache.qpid.amqp_1_0.type.messaging.AmqpSequence;
+import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue;
+import org.apache.qpid.amqp_1_0.type.messaging.Data;
+import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.plugin.MessageConverter;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.typedmessage.TypedBytesContentReader;
+import org.apache.qpid.typedmessage.TypedBytesFormatException;
+
+import java.io.EOFException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+public class MessageConverter_v1_0_to_Internal implements MessageConverter<Message_1_0, InternalMessage>
+{
+
+ static final AMQPDescribedTypeRegistry TYPE_REGISTRY = AMQPDescribedTypeRegistry.newInstance();
+ static
+ {
+ TYPE_REGISTRY.registerTransportLayer();
+ TYPE_REGISTRY.registerMessagingLayer();
+ TYPE_REGISTRY.registerTransactionLayer();
+ TYPE_REGISTRY.registerSecurityLayer();
+ }
+
+ @Override
+ public Class<Message_1_0> getInputClass()
+ {
+ return Message_1_0.class;
+ }
+
+ @Override
+ public Class<InternalMessage> getOutputClass()
+ {
+ return InternalMessage.class;
+ }
+
+ @Override
+ public InternalMessage convert(Message_1_0 serverMessage, VirtualHost vhost)
+ {
+ final String mimeType = serverMessage.getMessageHeader().getMimeType();
+
+
+
+
+ byte[] data = new byte[(int) serverMessage.getSize()];
+ serverMessage.getStoredMessage().getContent(0,ByteBuffer.wrap(data));
+
+ SectionDecoderImpl sectionDecoder = new SectionDecoderImpl(TYPE_REGISTRY);
+
+ try
+ {
+ List<Section> sections = sectionDecoder.parseAll(ByteBuffer.wrap(data));
+ ListIterator<Section> iterator = sections.listIterator();
+ Section previousSection = null;
+ while(iterator.hasNext())
+ {
+ Section section = iterator.next();
+ if(!(section instanceof AmqpValue || section instanceof Data || section instanceof AmqpSequence))
+ {
+ iterator.remove();
+ }
+ else
+ {
+ if(previousSection != null && (previousSection.getClass() != section.getClass() || section instanceof AmqpValue))
+ {
+ throw new RuntimeException("Message is badly formed and has multiple body section which are not all Data or not all AmqpSequence");
+ }
+ else
+ {
+ previousSection = section;
+ }
+ }
+ }
+
+ Object bodyObject;
+
+ if(sections.isEmpty())
+ {
+ // should actually be illegal
+ bodyObject = new byte[0];
+ }
+ else
+ {
+ Section firstBodySection = sections.get(0);
+ if(firstBodySection instanceof AmqpValue)
+ {
+ bodyObject = fixObject(((AmqpValue)firstBodySection).getValue());
+ }
+ else if(firstBodySection instanceof Data)
+ {
+ int totalSize = 0;
+ for(Section section : sections)
+ {
+ totalSize += ((Data)section).getValue().getLength();
+ }
+ byte[] bodyData = new byte[totalSize];
+ ByteBuffer buf = ByteBuffer.wrap(bodyData);
+ for(Section section : sections)
+ {
+ buf.put(((Data)section).getValue().asByteBuffer());
+ }
+ bodyObject = bodyData;
+ }
+ else
+ {
+ ArrayList totalSequence = new ArrayList();
+ for(Section section : sections)
+ {
+ totalSequence.addAll(((AmqpSequence)section).getValue());
+ }
+ bodyObject = fixObject(totalSequence);
+ }
+ }
+ return InternalMessage.convert(serverMessage.getMessageNumber(), serverMessage.isPersistent(), serverMessage.getMessageHeader(), bodyObject);
+
+ }
+ catch (AmqpErrorException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+
+
+
+ }
+
+ private Object fixObject(final Object value)
+ {
+ if(value instanceof Binary)
+ {
+ final Binary binaryValue = (Binary) value;
+ byte[] data = new byte[binaryValue.getLength()];
+ binaryValue.asByteBuffer().get(data);
+ return data;
+ }
+ else if(value instanceof List)
+ {
+ List listValue = (List) value;
+ List fixedValue = new ArrayList(listValue.size());
+ for(Object o : listValue)
+ {
+ fixedValue.add(fixObject(o));
+ }
+ return fixedValue;
+ }
+ else if(value instanceof Map)
+ {
+ Map<?,?> mapValue = (Map) value;
+ Map fixedValue = new LinkedHashMap(mapValue.size());
+ for(Map.Entry<?,?> entry : mapValue.entrySet())
+ {
+ fixedValue.put(fixObject(entry.getKey()),fixObject(entry.getValue()));
+ }
+ return fixedValue;
+ }
+ else
+ {
+ return value;
+ }
+
+ }
+
+ private static Object convertMessageBody(String mimeType, byte[] data)
+ {
+ if("text/plain".equals(mimeType) || "text/xml".equals(mimeType))
+ {
+ String text = new String(data);
+ return text;
+ }
+ else if("jms/map-message".equals(mimeType))
+ {
+ TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data));
+
+ LinkedHashMap map = new LinkedHashMap();
+ final int entries = reader.readIntImpl();
+ for (int i = 0; i < entries; i++)
+ {
+ try
+ {
+ String propName = reader.readStringImpl();
+ Object value = reader.readObject();
+
+ map.put(propName, value);
+ }
+ catch (EOFException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ catch (TypedBytesFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+
+ }
+
+ return map;
+
+ }
+ else if("amqp/map".equals(mimeType))
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(data));
+ final Map<String,Object> map = decoder.readMap();
+
+ return map;
+
+ }
+ else if("amqp/list".equals(mimeType))
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(data));
+ return decoder.readList();
+ }
+ else if("jms/stream-message".equals(mimeType))
+ {
+ TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data));
+
+ List list = new ArrayList();
+ while (reader.remaining() != 0)
+ {
+ try
+ {
+ list.add(reader.readObject());
+ }
+ catch (TypedBytesFormatException e)
+ {
+ throw new RuntimeException(e); // TODO - Implement
+ }
+ catch (EOFException e)
+ {
+ throw new RuntimeException(e); // TODO - Implement
+ }
+ }
+ return list;
+ }
+ else
+ {
+ return data;
+
+ }
+ }
+
+ @Override
+ public String getType()
+ {
+ return "v0-8 to Internal";
+ }
+}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java
index 5026007360..be9d7a2d60 100755
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java
@@ -314,7 +314,7 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData
return buf;
}
- public int writeToBuffer(int offsetInMetaData, ByteBuffer dest)
+ public int writeToBuffer(ByteBuffer dest)
{
ByteBuffer buf = _encoded;
@@ -326,7 +326,7 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData
buf = buf.duplicate();
- buf.position(offsetInMetaData);
+ buf.position(0);
if(dest.remaining() < buf.limit())
{
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageSourceDestination.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageSourceDestination.java
new file mode 100644
index 0000000000..6f37d2d831
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageSourceDestination.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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.protocol.v1_0;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.amqp_1_0.type.Outcome;
+import org.apache.qpid.amqp_1_0.type.messaging.Accepted;
+import org.apache.qpid.server.message.MessageSource;
+import org.apache.qpid.server.txn.ServerTransaction;
+
+public class MessageSourceDestination implements SendingDestination
+{
+ private static final Logger _logger = Logger.getLogger(MessageSourceDestination.class);
+ private static final Accepted ACCEPTED = new Accepted();
+ private static final Outcome[] OUTCOMES = new Outcome[] { ACCEPTED };
+
+
+ private MessageSource _queue;
+
+ public MessageSourceDestination(MessageSource queue)
+ {
+ _queue = queue;
+ }
+
+ public Outcome[] getOutcomes()
+ {
+ return OUTCOMES;
+ }
+
+ public int getCredit()
+ {
+ // TODO - fix
+ return 100;
+ }
+
+ public MessageSource getQueue()
+ {
+ return _queue;
+ }
+
+}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/NodeReceivingDestination.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/NodeReceivingDestination.java
new file mode 100644
index 0000000000..70f659b546
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/NodeReceivingDestination.java
@@ -0,0 +1,106 @@
+/*
+ *
+ * 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.protocol.v1_0;
+
+import org.apache.qpid.amqp_1_0.type.Outcome;
+import org.apache.qpid.amqp_1_0.type.messaging.Accepted;
+import org.apache.qpid.amqp_1_0.type.messaging.Rejected;
+import org.apache.qpid.amqp_1_0.type.messaging.TerminusDurability;
+import org.apache.qpid.amqp_1_0.type.messaging.TerminusExpiryPolicy;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.txn.ServerTransaction;
+
+public class NodeReceivingDestination implements ReceivingDestination
+{
+ private static final Accepted ACCEPTED = new Accepted();
+ public static final Rejected REJECTED = new Rejected();
+ private static final Outcome[] OUTCOMES = { ACCEPTED, REJECTED};
+
+ private MessageDestination _exchange;
+ private TerminusDurability _durability;
+ private TerminusExpiryPolicy _expiryPolicy;
+
+ public NodeReceivingDestination(MessageDestination exchange, TerminusDurability durable, TerminusExpiryPolicy expiryPolicy)
+ {
+ _exchange = exchange;
+ _durability = durable;
+ _expiryPolicy = expiryPolicy;
+ }
+
+ public Outcome[] getOutcomes()
+ {
+ return OUTCOMES;
+ }
+
+ public Outcome send(final Message_1_0 message, ServerTransaction txn)
+ {
+ final InstanceProperties instanceProperties =
+ new InstanceProperties()
+ {
+
+ @Override
+ public Object getProperty(final Property prop)
+ {
+ switch(prop)
+ {
+ case MANDATORY:
+ return false;
+ case REDELIVERED:
+ return false;
+ case PERSISTENT:
+ return message.isPersistent();
+ case IMMEDIATE:
+ return false;
+ case EXPIRATION:
+ return message.getExpiration();
+ }
+ return null;
+ }};
+
+ int enqueues = _exchange.send(message, instanceProperties, txn, null);
+
+
+ return enqueues == 0 ? REJECTED : ACCEPTED;
+ }
+
+ TerminusDurability getDurability()
+ {
+ return _durability;
+ }
+
+ TerminusExpiryPolicy getExpiryPolicy()
+ {
+ return _expiryPolicy;
+ }
+
+ public int getCredit()
+ {
+ // TODO - fix
+ return 20000;
+ }
+
+ public MessageDestination getDestination()
+ {
+ return _exchange;
+ }
+}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java
index b9c10b925f..3d6bb5e3db 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java
@@ -24,22 +24,21 @@ import org.apache.log4j.Logger;
import org.apache.qpid.amqp_1_0.type.Outcome;
import org.apache.qpid.amqp_1_0.type.messaging.Accepted;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.txn.ServerTransaction;
-public class QueueDestination implements SendingDestination, ReceivingDestination
+public class QueueDestination extends MessageSourceDestination implements SendingDestination, ReceivingDestination
{
private static final Logger _logger = Logger.getLogger(QueueDestination.class);
private static final Accepted ACCEPTED = new Accepted();
private static final Outcome[] OUTCOMES = new Outcome[] { ACCEPTED };
- private AMQQueue _queue;
-
public QueueDestination(AMQQueue queue)
{
- _queue = queue;
+ super(queue);
}
public Outcome[] getOutcomes()
@@ -52,7 +51,7 @@ public class QueueDestination implements SendingDestination, ReceivingDestinatio
try
{
- txn.enqueue(_queue,message, new ServerTransaction.Action()
+ txn.enqueue(getQueue(),message, new ServerTransaction.Action()
{
@@ -60,8 +59,7 @@ public class QueueDestination implements SendingDestination, ReceivingDestinatio
{
try
{
-
- _queue.enqueue(message);
+ getQueue().enqueue(message,null);
}
catch (Exception e)
{
@@ -93,7 +91,7 @@ public class QueueDestination implements SendingDestination, ReceivingDestinatio
public AMQQueue getQueue()
{
- return _queue;
+ return (AMQQueue) super.getQueue();
}
}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
index 4abf1bf76b..f796a4b2e3 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.protocol.v1_0;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -42,16 +43,7 @@ import org.apache.qpid.amqp_1_0.type.DeliveryState;
import org.apache.qpid.amqp_1_0.type.Outcome;
import org.apache.qpid.amqp_1_0.type.Symbol;
import org.apache.qpid.amqp_1_0.type.UnsignedInteger;
-import org.apache.qpid.amqp_1_0.type.messaging.Accepted;
-import org.apache.qpid.amqp_1_0.type.messaging.ExactSubjectFilter;
-import org.apache.qpid.amqp_1_0.type.messaging.Filter;
-import org.apache.qpid.amqp_1_0.type.messaging.MatchingSubjectFilter;
-import org.apache.qpid.amqp_1_0.type.messaging.Modified;
-import org.apache.qpid.amqp_1_0.type.messaging.NoLocalFilter;
-import org.apache.qpid.amqp_1_0.type.messaging.Released;
-import org.apache.qpid.amqp_1_0.type.messaging.Source;
-import org.apache.qpid.amqp_1_0.type.messaging.StdDistMode;
-import org.apache.qpid.amqp_1_0.type.messaging.TerminusDurability;
+import org.apache.qpid.amqp_1_0.type.messaging.*;
import org.apache.qpid.amqp_1_0.type.transport.AmqpError;
import org.apache.qpid.amqp_1_0.type.transport.Detach;
import org.apache.qpid.amqp_1_0.type.transport.Error;
@@ -64,11 +56,14 @@ import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.TopicExchange;
import org.apache.qpid.server.filter.JMSSelectorFilter;
import org.apache.qpid.server.filter.SimpleFilterManager;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.consumer.Consumer;
import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryStateHandler
@@ -78,18 +73,22 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
private VirtualHost _vhost;
private SendingDestination _destination;
- private Subscription_1_0 _subscription;
+ private Consumer _consumer;
+ private ConsumerTarget_1_0 _target;
+
private boolean _draining;
- private final Map<Binary, QueueEntry> _unsettledMap =
- new HashMap<Binary, QueueEntry>();
+ private final Map<Binary, MessageInstance> _unsettledMap =
+ new HashMap<Binary, MessageInstance>();
private final ConcurrentHashMap<Binary, UnsettledAction> _unsettledActionMap =
new ConcurrentHashMap<Binary, UnsettledAction>();
private volatile SendingLinkAttachment _linkAttachment;
private TerminusDurability _durability;
- private List<QueueEntry> _resumeFullTransfers = new ArrayList<QueueEntry>();
+ private List<MessageInstance> _resumeFullTransfers = new ArrayList<MessageInstance>();
private List<Binary> _resumeAcceptedTransfers = new ArrayList<Binary>();
private Runnable _closeAction;
+ private final MessageSource _queue;
+
public SendingLink_1_0(final SendingLinkAttachment linkAttachment,
final VirtualHost vhost,
@@ -103,24 +102,22 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
_durability = source.getDurable();
linkAttachment.setDeliveryStateHandler(this);
QueueDestination qd = null;
- AMQQueue queue = null;
+ EnumSet<Consumer.Option> options = EnumSet.noneOf(Consumer.Option.class);
boolean noLocal = false;
JMSSelectorFilter messageFilter = null;
- if(destination instanceof QueueDestination)
+ if(destination instanceof MessageSourceDestination)
{
- queue = ((QueueDestination) _destination).getQueue();
+ _queue = ((MessageSourceDestination) _destination).getQueue();
- if(queue.getAvailableAttributes().contains("topic"))
+ if(_queue instanceof AMQQueue && ((AMQQueue)_queue).getAvailableAttributes().contains("topic"))
{
source.setDistributionMode(StdDistMode.COPY);
}
- qd = (QueueDestination) destination;
-
Map<Symbol,Filter> filters = source.getFilter();
Map<Symbol,Filter> actualFilters = new HashMap<Symbol,Filter>();
@@ -167,7 +164,13 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
}
source.setFilter(actualFilters.isEmpty() ? null : actualFilters);
- _subscription = new Subscription_1_0(this, qd, source.getDistributionMode() != StdDistMode.COPY);
+ _target = new ConsumerTarget_1_0(this, source.getDistributionMode() != StdDistMode.COPY);
+ if(source.getDistributionMode() != StdDistMode.COPY)
+ {
+ options.add(Consumer.Option.ACQUIRES);
+ options.add(Consumer.Option.SEES_REQUEUES);
+ }
+
}
else if(destination instanceof ExchangeDestination)
{
@@ -199,7 +202,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
name = UUID.randomUUID().toString();
}
- queue = _vhost.getQueue(name);
+ AMQQueue queue = _vhost.getQueue(name);
Exchange exchange = exchangeDestination.getExchange();
if(queue == null)
@@ -299,9 +302,10 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
}
}
}
+ _queue = queue;
source.setFilter(actualFilters.isEmpty() ? null : actualFilters);
- exchange.addBinding(binding,queue,null);
+ exchange.addBinding(binding, queue,null);
source.setDistributionMode(StdDistMode.COPY);
if(!isDurable)
@@ -309,10 +313,10 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
final String queueName = name;
final AMQQueue tempQueue = queue;
- final Connection_1_0.Task deleteQueueTask =
- new Connection_1_0.Task()
+ final Action<Connection_1_0> deleteQueueTask =
+ new Action<Connection_1_0>()
{
- public void doTask(Connection_1_0 session)
+ public void performAction(Connection_1_0 session)
{
if (_vhost.getQueue(queueName) == tempQueue)
{
@@ -331,9 +335,9 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
getSession().getConnection().addConnectionCloseTask(deleteQueueTask);
- queue.addQueueDeleteTask(new AMQQueue.Task()
+ queue.addQueueDeleteTask(new Action<AMQQueue>()
{
- public void doTask(AMQQueue queue)
+ public void performAction(AMQQueue queue)
{
getSession().getConnection().removeConnectionCloseTask(deleteQueueTask);
}
@@ -347,31 +351,52 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
catch (AMQSecurityException e)
{
_logger.error("Security error", e);
+ throw new RuntimeException(e);
}
catch (AMQInternalException e)
{
_logger.error("Internal error", e);
+ throw new RuntimeException(e);
}
catch (AMQException e)
{
_logger.error("Error", e);
+ throw new RuntimeException(e);
}
- _subscription = new Subscription_1_0(this, qd, true);
+
+ _target = new ConsumerTarget_1_0(this, true);
+ options.add(Consumer.Option.ACQUIRES);
+ options.add(Consumer.Option.SEES_REQUEUES);
+
+ }
+ else
+ {
+ throw new RuntimeException("Unknown destination type");
}
- if(_subscription != null)
+ if(_target != null)
{
- _subscription.setNoLocal(noLocal);
- if(messageFilter!=null)
+ if(noLocal)
{
- _subscription.setFilters(new SimpleFilterManager(messageFilter));
+ options.add(Consumer.Option.NO_LOCAL);
}
try
{
-
- queue.registerSubscription(_subscription, false);
+ final String name;
+ if(getEndpoint().getTarget() instanceof Target)
+ {
+ Target target = (Target) getEndpoint().getTarget();
+ name = target.getAddress() == null ? getEndpoint().getName() : target.getAddress();
+ }
+ else
+ {
+ name = getEndpoint().getName();
+ }
+ _consumer = _queue.addConsumer(_target,
+ messageFilter == null ? null : new SimpleFilterManager(messageFilter),
+ Message_1_0.class, name, options);
}
catch (AMQException e)
{
@@ -394,12 +419,11 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
// if not durable or close
if(!TerminusDurability.UNSETTLED_STATE.equals(_durability))
{
- AMQQueue queue = _subscription.getQueue();
try
{
- queue.unregisterSubscription(_subscription);
+ _consumer.close();
}
catch (AMQException e)
@@ -426,7 +450,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
{
try
{
- queue.getVirtualHost().removeQueue(queue);
+ _vhost.removeQueue((AMQQueue)_queue);
}
catch(AMQException e)
{
@@ -443,7 +467,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
else if(detach == null || detach.getError() != null)
{
_linkAttachment = null;
- _subscription.flowStateChanged();
+ _target.flowStateChanged();
}
else
{
@@ -491,7 +515,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
}
if(_resumeAcceptedTransfers.isEmpty())
{
- _subscription.flowStateChanged();
+ _target.flowStateChanged();
}
}
@@ -531,7 +555,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
}
}
- public void addUnsettled(Binary tag, UnsettledAction unsettledAction, QueueEntry queueEntry)
+ public void addUnsettled(Binary tag, UnsettledAction unsettledAction, MessageInstance queueEntry)
{
_unsettledActionMap.put(tag,unsettledAction);
if(getTransactionId() == null)
@@ -593,9 +617,9 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
public synchronized void setLinkAttachment(SendingLinkAttachment linkAttachment)
{
- if(_subscription.isActive())
+ if(_consumer.isActive())
{
- _subscription.suspend();
+ _target.suspend();
}
_linkAttachment = linkAttachment;
@@ -603,14 +627,14 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
SendingLinkEndpoint endpoint = linkAttachment.getEndpoint();
endpoint.setDeliveryStateHandler(this);
Map initialUnsettledMap = endpoint.getInitialUnsettledMap();
- Map<Binary, QueueEntry> unsettledCopy = new HashMap<Binary, QueueEntry>(_unsettledMap);
+ Map<Binary, MessageInstance> unsettledCopy = new HashMap<Binary, MessageInstance>(_unsettledMap);
_resumeAcceptedTransfers.clear();
_resumeFullTransfers.clear();
- for(Map.Entry<Binary, QueueEntry> entry : unsettledCopy.entrySet())
+ for(Map.Entry<Binary, MessageInstance> entry : unsettledCopy.entrySet())
{
Binary deliveryTag = entry.getKey();
- final QueueEntry queueEntry = entry.getValue();
+ final MessageInstance queueEntry = entry.getValue();
if(initialUnsettledMap == null || !initialUnsettledMap.containsKey(deliveryTag))
{
queueEntry.setRedelivered();
@@ -624,7 +648,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
if(outcome instanceof Accepted)
{
AutoCommitTransaction txn = new AutoCommitTransaction(_vhost.getMessageStore());
- if(_subscription.acquires())
+ if(_consumer.acquires())
{
txn.dequeue(Collections.singleton(queueEntry),
new ServerTransaction.Action()
@@ -644,7 +668,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
else if(outcome instanceof Released)
{
AutoCommitTransaction txn = new AutoCommitTransaction(_vhost.getMessageStore());
- if(_subscription.acquires())
+ if(_consumer.acquires())
{
txn.dequeue(Collections.singleton(queueEntry),
new ServerTransaction.Action()
@@ -678,9 +702,9 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
public Map getUnsettledOutcomeMap()
{
- Map<Binary, QueueEntry> unsettled = new HashMap<Binary, QueueEntry>(_unsettledMap);
+ Map<Binary, MessageInstance> unsettled = new HashMap<Binary, MessageInstance>(_unsettledMap);
- for(Map.Entry<Binary, QueueEntry> entry : unsettled.entrySet())
+ for(Map.Entry<Binary, MessageInstance> entry : unsettled.entrySet())
{
entry.setValue(null);
}
@@ -692,4 +716,9 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
{
_closeAction = action;
}
+
+ public VirtualHost getVirtualHost()
+ {
+ return _vhost;
+ }
}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
index 823e4cb16d..beed6be84b 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
@@ -41,6 +41,8 @@ import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
@@ -48,6 +50,7 @@ import org.apache.qpid.server.protocol.LinkRegistry;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.*;
@@ -108,11 +111,11 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu
source.setAddress(tempQueue.getName());
}
String addr = source.getAddress();
- AMQQueue queue = _vhost.getQueue(addr);
+ MessageSource queue = _vhost.getMessageSource(addr);
if(queue != null)
{
- destination = new QueueDestination(queue);
+ destination = new MessageSourceDestination(queue);
@@ -249,11 +252,11 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu
}
String addr = target.getAddress();
- Exchange exchg = _vhost.getExchange(addr);
- if(exchg != null)
+ MessageDestination messageDestination = _vhost.getMessageDestination(addr);
+ if(messageDestination != null)
{
- destination = new ExchangeDestination(exchg, target.getDurable(),
- target.getExpiryPolicy());
+ destination = new NodeReceivingDestination(messageDestination, target.getDurable(),
+ target.getExpiryPolicy());
}
else
{
@@ -343,10 +346,10 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu
if (lifetimePolicy == null || lifetimePolicy instanceof DeleteOnClose)
{
- final Connection_1_0.Task deleteQueueTask =
- new Connection_1_0.Task()
+ final Action<Connection_1_0> deleteQueueTask =
+ new Action<Connection_1_0>()
{
- public void doTask(Connection_1_0 session)
+ public void performAction(Connection_1_0 session)
{
if (_vhost.getQueue(queueName) == tempQueue)
{
@@ -365,9 +368,9 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu
_connection.addConnectionCloseTask(deleteQueueTask);
- queue.addQueueDeleteTask(new AMQQueue.Task()
+ queue.addQueueDeleteTask(new Action<AMQQueue>()
{
- public void doTask(AMQQueue queue)
+ public void performAction(AMQQueue queue)
{
_connection.removeConnectionCloseTask(deleteQueueTask);
}
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter
new file mode 100644
index 0000000000..aa24847805
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+org.apache.qpid.server.protocol.v1_0.MessageConverter_Internal_to_v1_0
+org.apache.qpid.server.protocol.v1_0.MessageConverter_v1_0_to_Internal \ No newline at end of file
diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/pom.xml b/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/pom.xml
index 1403caee0a..38ff043377 100644
--- a/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/pom.xml
+++ b/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/pom.xml
@@ -16,50 +16,50 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-amqp-msg-conv-0-10-to-1-0</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 0-10 to 1-0 Message Conversion Broker Plug-in</name>
+ <description>AMQP message conversion (0-10 to 1-0) broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-10-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-amqp-1-0-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-1-0-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
</dependencies>
diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/pom.xml b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/pom.xml
index deccb6cf22..016f777212 100644
--- a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/pom.xml
+++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/pom.xml
@@ -16,43 +16,44 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-amqp-msg-conv-0-8-to-0-10</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 0-8 to 0-10 Message Conversion Broker Plug-in</name>
+ <description>AMQP message conversion (0-8, 0-9 and 0-9-1 to 0-10) broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-8-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-10-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
</dependencies>
diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java
index f1843de8ac..0c83c31ad4 100644
--- a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java
+++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java
@@ -61,7 +61,7 @@ public class MessageConverter_0_10_to_0_8 implements MessageConverter<MessageTra
{
if(deliveryProps.hasDeliveryMode())
{
- props.setDeliveryMode((byte) (deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT
+ props.setDeliveryMode((deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT
? BasicContentHeaderProperties.PERSISTENT
: BasicContentHeaderProperties.NON_PERSISTENT));
}
diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/pom.xml b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/pom.xml
index ec725e7e57..a01760f139 100644
--- a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/pom.xml
+++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/pom.xml
@@ -16,50 +16,50 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-amqp-msg-conv-0-8-to-1-0</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 0-8 to 1-0 Message Conversion Broker Plug-in</name>
+ <description>AMQP message conversion (0-8, 0-9 and 0-9-1 to 1-0) broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-8-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-amqp-1-0-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-1-0-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
</dependencies>
diff --git a/qpid/java/broker-plugins/derby-store/pom.xml b/qpid/java/broker-plugins/derby-store/pom.xml
index 9b55875aa8..58088d7a75 100644
--- a/qpid/java/broker-plugins/derby-store/pom.xml
+++ b/qpid/java/broker-plugins/derby-store/pom.xml
@@ -16,50 +16,49 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-derby-store</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Derby Message Store</name>
+ <description>Apache Derby DB message store broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
- <version>10.8.2.2</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
diff --git a/qpid/java/broker-plugins/jdbc-provider-bone/pom.xml b/qpid/java/broker-plugins/jdbc-provider-bone/pom.xml
index 52631a44e3..af468af3af 100644
--- a/qpid/java/broker-plugins/jdbc-provider-bone/pom.xml
+++ b/qpid/java/broker-plugins/jdbc-provider-bone/pom.xml
@@ -16,29 +16,31 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-jdbc-provider-bone</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid JDBC Message Store Connection Pooling Plug-in</name>
+ <description>JDBC Message Store Connection Pooling broker plug-in using BoneCP</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp</artifactId>
- <version>0.7.1.RELEASE</version>
- <scope>compile</scope>
<exclusions>
<exclusion>
<!-- exclude and specify a fixed version below -->
@@ -51,7 +53,6 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
- <version>14.0.1</version>
<scope>runtime</scope>
</dependency>
diff --git a/qpid/java/broker-plugins/jdbc-store/pom.xml b/qpid/java/broker-plugins/jdbc-store/pom.xml
index ca861a42f3..a2541ec913 100644
--- a/qpid/java/broker-plugins/jdbc-store/pom.xml
+++ b/qpid/java/broker-plugins/jdbc-store/pom.xml
@@ -16,43 +16,45 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-jdbc-store</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid JDBC Message Store Broker Plug-in</name>
+ <description>JDBC message store broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
@@ -60,7 +62,6 @@
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
- <version>10.8.2.2</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/broker-plugins/management-amqp/build.xml b/qpid/java/broker-plugins/management-amqp/build.xml
new file mode 100644
index 0000000000..542bb952f1
--- /dev/null
+++ b/qpid/java/broker-plugins/management-amqp/build.xml
@@ -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.
+ -->
+<project name="Qpid Broker-Plugins AMQP Management" default="build">
+ <property name="module.depends" value="common broker-core" />
+ <property name="module.test.depends" value="qpid-test-utils broker-core/tests" />
+
+ <property name="module.genpom" value="true"/>
+ <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker-core=provided"/>
+
+ <property name="broker.plugin" value="true"/>
+ <property name="broker-plugins-management-amqp.libs" value="" />
+
+ <import file="../../module.xml" />
+
+ <target name="bundle" depends="bundle-tasks"/>
+</project>
diff --git a/qpid/java/broker-plugins/management-amqp/pom.xml b/qpid/java/broker-plugins/management-amqp/pom.xml
new file mode 100644
index 0000000000..83873a61f2
--- /dev/null
+++ b/qpid/java/broker-plugins/management-amqp/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>qpid-parent</artifactId>
+ <groupId>org.apache.qpid</groupId>
+ <version>1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>qpid-broker-plugins-management-amqp</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>AMQP Management Protocol Plug-in</name>
+ <description>AMQP Management broker plug-in</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-broker-core</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ </build>
+
+</project>
diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagedEntityType.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagedEntityType.java
new file mode 100644
index 0000000000..10a16faa56
--- /dev/null
+++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagedEntityType.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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.management.amqp;
+
+import java.util.Arrays;
+
+class ManagedEntityType
+{
+ private final String _name;
+ private final ManagedEntityType[] _parents;
+ private final String[] _attributes;
+ private final String[] _operations;
+
+ ManagedEntityType(final String name,
+ final ManagedEntityType[] parents,
+ final String[] attributes,
+ final String[] operations)
+ {
+ _name = name;
+ _parents = parents;
+ _attributes = attributes;
+ _operations = operations;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public ManagedEntityType[] getParents()
+ {
+ return _parents;
+ }
+
+ public String[] getAttributes()
+ {
+ return _attributes;
+ }
+
+ public String[] getOperations()
+ {
+ return _operations;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ManagedEntityType{" +
+ "name='" + _name + '\'' +
+ ", parents=" + Arrays.toString(_parents) +
+ ", attributes=" + Arrays.toString(_attributes) +
+ ", operations=" + Arrays.toString(_operations) +
+ '}';
+ }
+}
diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java
new file mode 100644
index 0000000000..2b94aae5b7
--- /dev/null
+++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java
@@ -0,0 +1,1402 @@
+/*
+ *
+ * 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.management.amqp;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.filter.FilterManager;
+import org.apache.qpid.server.filter.Filterable;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageSource;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.message.internal.InternalMessageHeader;
+import org.apache.qpid.server.model.AmqpManagement;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.plugin.MessageConverter;
+import org.apache.qpid.server.plugin.SystemNodeCreator;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.MessageConverterRegistry;
+import org.apache.qpid.server.security.AuthorizationHolder;
+import org.apache.qpid.server.store.StorableMessageMetaData;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.util.StateChangeListener;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import java.nio.charset.Charset;
+import java.security.AccessControlException;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+class ManagementNode implements MessageSource<ManagementNodeConsumer,ManagementNode>, MessageDestination
+{
+
+ public static final String NAME_ATTRIBUTE = "name";
+ public static final String IDENTITY_ATTRIBUTE = "identity";
+ public static final String TYPE_ATTRIBUTE = "type";
+ public static final String OPERATION_HEADER = "operation";
+ public static final String SELF_NODE_NAME = "self";
+ public static final String MANAGEMENT_TYPE = "org.amqp.management";
+ public static final String GET_TYPES = "GET-TYPES";
+ public static final String GET_ATTRIBUTES = "GET-ATTRIBUTES";
+ public static final String GET_OPERATIONS = "GET-OPERATIONS";
+ public static final String QUERY = "QUERY";
+ public static final String ENTITY_TYPES_HEADER = "entityTypes";
+ public static final String STATUS_CODE_HEADER = "statusCode";
+ public static final int STATUS_CODE_OK = 200;
+ public static final String ATTRIBUTES_HEADER = "attributes";
+ public static final String OFFSET_HEADER = "offset";
+ public static final String COUNT_HEADER = "count";
+ public static final String MANAGEMENT_NODE_NAME = "$management";
+ public static final String CREATE_OPERATION = "CREATE";
+ public static final String READ_OPERATION = "READ";
+ public static final String UPDATE_OPERATION = "UPDATE";
+ public static final String DELETE_OPERATION = "DELETE";
+ public static final String STATUS_DESCRIPTION_HEADER = "statusDescription";
+ public static final int NOT_FOUND_STATUS_CODE = 404;
+ public static final int NOT_IMPLEMENTED_STATUS_CODE = 501;
+ public static final int STATUS_CODE_NO_CONTENT = 204;
+ public static final int STATUS_CODE_FORBIDDEN = 403;
+ public static final int STATUS_CODE_BAD_REQUEST = 400;
+ public static final int STATUS_CODE_INTERNAL_ERROR = 500;
+
+
+ private final VirtualHost _virtualHost;
+
+ private final UUID _id;
+
+ private final CopyOnWriteArrayList<ConsumerRegistrationListener<ManagementNode>> _consumerRegistrationListeners =
+ new CopyOnWriteArrayList<ConsumerRegistrationListener<ManagementNode>>();
+
+ private final SystemNodeCreator.SystemNodeRegistry _registry;
+ private final ConfiguredObject _managedObject;
+ private Map<String, ManagementNodeConsumer> _consumers = new ConcurrentHashMap<String, ManagementNodeConsumer>();
+
+ private Map<String,ManagedEntityType> _entityTypes = Collections.synchronizedMap(new LinkedHashMap<String, ManagedEntityType>());
+
+ private Map<ManagedEntityType,Map<String,ConfiguredObject>> _entities = Collections.synchronizedMap(new LinkedHashMap<ManagedEntityType,Map<String,ConfiguredObject>>());
+
+
+ public ManagementNode(final SystemNodeCreator.SystemNodeRegistry registry,
+ final ConfiguredObject configuredObject)
+ {
+ _virtualHost = registry.getVirtualHost();
+ _registry = registry;
+ final String name = configuredObject.getId() + MANAGEMENT_NODE_NAME;
+ _id = UUID.nameUUIDFromBytes(name.getBytes(Charset.defaultCharset()));
+
+
+ _managedObject = configuredObject;
+
+ populateTypeMetaData(configuredObject.getClass(), false);
+
+ configuredObject.addChangeListener(new ModelObjectListener());
+
+ final Class managementClass = getManagementClass(_managedObject.getClass());
+ _entities.get(_entityTypes.get(managementClass.getName())).put(_managedObject.getName(), _managedObject);
+
+ Collection<Class<? extends ConfiguredObject>> childClasses = Model.getInstance().getChildTypes(managementClass);
+ for(Class<? extends ConfiguredObject> childClass : childClasses)
+ {
+ if(getManagementClass(childClass) != null)
+ {
+ for(ConfiguredObject child : _managedObject.getChildren(childClass))
+ {
+ _entities.get(_entityTypes.get(getManagementClass(childClass).getName())).put(child.getName(), child);
+ }
+ }
+ }
+
+ }
+
+ private Class getManagementClass(Class objectClass)
+ {
+ List<Class> allClasses = new ArrayList<Class>();
+ allClasses.add(objectClass);
+ allClasses.addAll(Arrays.asList(objectClass.getInterfaces()));
+ allClasses.add(objectClass.getSuperclass());
+ for(Class clazz : allClasses)
+ {
+ AmqpManagement annotation = (AmqpManagement) clazz.getAnnotation(AmqpManagement.class);
+ if(annotation != null)
+ {
+ return clazz;
+ }
+ }
+ return null;
+ }
+
+ private boolean populateTypeMetaData(final Class<? extends ConfiguredObject> objectClass, boolean allowCreate)
+ {
+ Class clazz = getManagementClass(objectClass);
+ if( clazz != null)
+ {
+ AmqpManagement annotation = (AmqpManagement) clazz.getAnnotation(AmqpManagement.class);
+ populateTypeMetaData(clazz, annotation);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private ManagedEntityType populateTypeMetaData(Class clazz,
+ final AmqpManagement entityType)
+ {
+
+ ManagedEntityType managedEntityType = _entityTypes.get(clazz.getName());
+
+ if(managedEntityType == null)
+ {
+ List<String> opsList = new ArrayList<String>(Arrays.asList(entityType.operations()));
+ if(entityType.creatable())
+ {
+ boolean isCreatableChild = false;
+ for(Class<? extends ConfiguredObject> parentConfig : Model.getInstance().getParentTypes(clazz))
+ {
+ isCreatableChild = parentConfig.isAssignableFrom(_managedObject.getClass());
+ if(isCreatableChild)
+ {
+ opsList.add(CREATE_OPERATION);
+ break;
+ }
+ }
+ }
+ opsList.addAll(Arrays.asList(READ_OPERATION, UPDATE_OPERATION, DELETE_OPERATION));
+
+ Set<ManagedEntityType> parentSet = new HashSet<ManagedEntityType>();
+
+ List<Class> allClasses = new ArrayList<Class>(Arrays.asList(clazz.getInterfaces()));
+ if(clazz.getSuperclass() != null)
+ {
+ allClasses.add(clazz.getSuperclass());
+ }
+
+ for(Class parentClazz : allClasses)
+ {
+ if(parentClazz.getAnnotation(AmqpManagement.class) != null)
+ {
+ ManagedEntityType parentType = populateTypeMetaData(parentClazz,
+ (AmqpManagement) parentClazz.getAnnotation(
+ AmqpManagement.class)
+ );
+ parentSet.add(parentType);
+ parentSet.addAll(Arrays.asList(parentType.getParents()));
+
+ }
+ }
+ managedEntityType = new ManagedEntityType(clazz.getName(), parentSet.toArray(new ManagedEntityType[parentSet.size()]), entityType.attributes(), opsList.toArray(new String[opsList.size()]));
+ _entityTypes.put(clazz.getName(),managedEntityType);
+ _entities.put(managedEntityType, Collections.synchronizedMap(new LinkedHashMap<String, ConfiguredObject>()));
+
+ if(ConfiguredObject.class.isAssignableFrom(clazz))
+ {
+ Collection<Class<? extends ConfiguredObject>> childTypes = Model.getInstance().getChildTypes(clazz);
+ for(Class<? extends ConfiguredObject> childClass : childTypes)
+ {
+ populateTypeMetaData(childClass, true);
+ }
+ }
+
+ }
+
+ return managedEntityType;
+
+ }
+
+ @Override
+ public <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message,
+ final InstanceProperties instanceProperties,
+ final ServerTransaction txn,
+ final Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction)
+ {
+
+ @SuppressWarnings("unchecked")
+ MessageConverter converter =
+ MessageConverterRegistry.getConverter(message.getClass(), InternalMessage.class);
+
+ final InternalMessage msg = (InternalMessage) converter.convert(message, _virtualHost);
+
+ if(validateMessage(msg))
+ {
+ txn.addPostTransactionAction(new ServerTransaction.Action()
+ {
+ @Override
+ public void postCommit()
+ {
+ enqueue(msg, instanceProperties, postEnqueueAction);
+ }
+
+ @Override
+ public void onRollback()
+ {
+
+ }
+ });
+
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private boolean validateMessage(final ServerMessage message)
+ {
+ AMQMessageHeader header = message.getMessageHeader();
+ return containsStringHeader(header, TYPE_ATTRIBUTE) && containsStringHeader(header, OPERATION_HEADER)
+ && (containsStringHeader(header, NAME_ATTRIBUTE) || containsStringHeader(header, IDENTITY_ATTRIBUTE));
+ }
+
+ private boolean containsStringHeader(final AMQMessageHeader header, String name)
+ {
+ return header.containsHeader(name) && header.getHeader(name) instanceof String;
+ }
+
+ synchronized void enqueue(InternalMessage message, InstanceProperties properties, Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction)
+ {
+ if(postEnqueueAction != null)
+ {
+ postEnqueueAction.performAction(new ConsumedMessageInstance(message, properties));
+ }
+
+
+
+ String name = (String) message.getMessageHeader().getHeader(NAME_ATTRIBUTE);
+ String id = (String) message.getMessageHeader().getHeader(IDENTITY_ATTRIBUTE);
+ String type = (String) message.getMessageHeader().getHeader(TYPE_ATTRIBUTE);
+ String operation = (String) message.getMessageHeader().getHeader(OPERATION_HEADER);
+
+ InternalMessage response;
+
+ if(SELF_NODE_NAME.equals(name) && type.equals(MANAGEMENT_TYPE))
+ {
+ response = performManagementOperation(message);
+ }
+ else if(CREATE_OPERATION.equals(operation))
+ {
+ response = performCreateOperation(message, type);
+ }
+ else
+ {
+
+ ConfiguredObject entity = findSubject(name, id, type);
+
+ if(entity != null)
+ {
+ response = performOperation(message, entity);
+ }
+ else
+ {
+ if(id != null)
+ {
+ response = createFailureResponse(message,
+ NOT_FOUND_STATUS_CODE,
+ "No entity with id {0} of type {1} found", id, type);
+ }
+ else
+ {
+ response = createFailureResponse(message,
+ NOT_FOUND_STATUS_CODE,
+ "No entity with name {0} of type {1} found", name, type);
+ }
+ }
+ }
+
+
+ ManagementNodeConsumer consumer = _consumers.get(message.getMessageHeader().getReplyTo());
+ if(consumer != null)
+ {
+ // TODO - check same owner
+ consumer.send(response);
+ }
+ // TODO - route to a queue
+
+ }
+
+ private InternalMessage performCreateOperation(final InternalMessage message, final String type)
+ {
+ InternalMessage response;
+ ManagedEntityType entityType = _entityTypes.get(type);
+ if(type != null)
+ {
+ if(Arrays.asList(entityType.getOperations()).contains(CREATE_OPERATION))
+ {
+ Object messageBody = message.getMessageBody();
+ if(messageBody instanceof Map)
+ {
+ try
+ {
+
+ Class<? extends ConfiguredObject> clazz =
+ (Class<? extends ConfiguredObject>) Class.forName(type);
+ try
+ {
+ ConfiguredObject child = _managedObject.createChild(clazz, (Map) messageBody);
+ if(child == null)
+ {
+ child = _entities.get(entityType).get(message.getMessageHeader().getHeader(NAME_ATTRIBUTE));
+ }
+ response = performReadOperation(message, child);
+ }
+ catch(RuntimeException e)
+ {
+ if (e instanceof AccessControlException || e.getCause() instanceof AMQSecurityException)
+ {
+ response = createFailureResponse(message, STATUS_CODE_FORBIDDEN, e.getMessage());
+ }
+ else
+ {
+ throw e;
+ }
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ response = createFailureResponse(message,
+ STATUS_CODE_INTERNAL_ERROR, "Unable to instantiate an instance of {0} ", type);
+ }
+ }
+ else
+ {
+ response = createFailureResponse(message,
+ STATUS_CODE_BAD_REQUEST,
+ "The message body in the request was not of the correct type");
+ }
+ }
+ else
+ {
+ response = createFailureResponse(message,
+ STATUS_CODE_FORBIDDEN,
+ "Cannot CREATE entities of type {0}", type);
+ }
+ }
+ else
+ {
+ response = createFailureResponse(message,
+ NOT_FOUND_STATUS_CODE,
+ "Unknown type {0}",type);
+ }
+ return response;
+ }
+
+ private InternalMessage performOperation(final InternalMessage requestMessage, final ConfiguredObject entity)
+ {
+ String operation = (String) requestMessage.getMessageHeader().getHeader(OPERATION_HEADER);
+
+ if(READ_OPERATION.equals(operation))
+ {
+ return performReadOperation(requestMessage, entity);
+ }
+ else if(DELETE_OPERATION.equals(operation))
+ {
+ return performDeleteOperation(requestMessage, entity);
+ }
+ else if(UPDATE_OPERATION.equals(operation))
+ {
+ return performUpdateOperation(requestMessage, entity);
+ }
+ else
+ {
+ return createFailureResponse(requestMessage, NOT_IMPLEMENTED_STATUS_CODE, "Unable to perform the {0} operation",operation);
+ }
+ }
+
+ private InternalMessage performReadOperation(final InternalMessage requestMessage, final ConfiguredObject entity)
+ {
+ final InternalMessageHeader requestHeader = requestMessage.getMessageHeader();
+ final MutableMessageHeader responseHeader = new MutableMessageHeader();
+ responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null
+ ? requestHeader.getMessageId()
+ : requestHeader.getCorrelationId());
+ responseHeader.setMessageId(UUID.randomUUID().toString());
+ responseHeader.setHeader(NAME_ATTRIBUTE, entity.getName());
+ responseHeader.setHeader(IDENTITY_ATTRIBUTE, entity.getId().toString());
+ responseHeader.setHeader(STATUS_CODE_HEADER,STATUS_CODE_OK);
+ final String type = getManagementClass(entity.getClass()).getName();
+ responseHeader.setHeader(TYPE_ATTRIBUTE, type);
+
+ Map<String,Object> responseBody = new LinkedHashMap<String, Object>();
+ final ManagedEntityType entityType = _entityTypes.get(type);
+ for(String attribute : entityType.getAttributes())
+ {
+ responseBody.put(attribute, fixValue(entity.getAttribute(attribute)));
+ }
+
+ return InternalMessage.createMapMessage(_virtualHost.getMessageStore(),responseHeader, responseBody);
+ }
+
+
+ private InternalMessage performDeleteOperation(final InternalMessage requestMessage, final ConfiguredObject entity)
+ {
+ final InternalMessageHeader requestHeader = requestMessage.getMessageHeader();
+ final MutableMessageHeader responseHeader = new MutableMessageHeader();
+ responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null
+ ? requestHeader.getMessageId()
+ : requestHeader.getCorrelationId());
+ responseHeader.setMessageId(UUID.randomUUID().toString());
+ responseHeader.setHeader(NAME_ATTRIBUTE, entity.getName());
+ responseHeader.setHeader(IDENTITY_ATTRIBUTE, entity.getId().toString());
+ final String type = getManagementClass(entity.getClass()).getName();
+ responseHeader.setHeader(TYPE_ATTRIBUTE, type);
+ try
+ {
+ entity.setDesiredState(entity.getActualState(),State.DELETED);
+ responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_NO_CONTENT);
+ }
+ catch(RuntimeException e)
+ {
+ if (e instanceof AccessControlException || e.getCause() instanceof AMQSecurityException)
+ {
+ responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_FORBIDDEN);
+ }
+ else
+ {
+ throw e;
+ }
+
+ }
+
+ return InternalMessage.createMapMessage(_virtualHost.getMessageStore(),responseHeader, Collections.emptyMap());
+ }
+
+
+ private InternalMessage performUpdateOperation(final InternalMessage requestMessage, final ConfiguredObject entity)
+ {
+ final InternalMessageHeader requestHeader = requestMessage.getMessageHeader();
+ final MutableMessageHeader responseHeader = new MutableMessageHeader();
+ responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null
+ ? requestHeader.getMessageId()
+ : requestHeader.getCorrelationId());
+ responseHeader.setMessageId(UUID.randomUUID().toString());
+ responseHeader.setHeader(NAME_ATTRIBUTE, entity.getName());
+ responseHeader.setHeader(IDENTITY_ATTRIBUTE, entity.getId().toString());
+ final String type = getManagementClass(entity.getClass()).getName();
+ responseHeader.setHeader(TYPE_ATTRIBUTE, type);
+
+ Object messageBody = requestMessage.getMessageBody();
+ if(messageBody instanceof Map)
+ {
+ try
+ {
+ entity.setAttributes((Map)messageBody);
+ return performReadOperation(requestMessage, entity);
+ }
+ catch(RuntimeException e)
+ {
+ if (e instanceof AccessControlException || e.getCause() instanceof AMQSecurityException)
+ {
+ return createFailureResponse(requestMessage, STATUS_CODE_FORBIDDEN, e.getMessage());
+ }
+ else
+ {
+ throw e;
+ }
+ }
+ }
+ else
+ {
+ return createFailureResponse(requestMessage,
+ STATUS_CODE_BAD_REQUEST,
+ "The message body in the request was not of the correct type");
+ }
+
+
+ }
+
+ private ConfiguredObject findSubject(final String name, final String id, final String type)
+ {
+ ConfiguredObject subject;
+ ManagedEntityType met = _entityTypes.get(type);
+ if(met == null)
+ {
+ return null;
+ }
+
+ subject = findSubject(name, id, met);
+ if(subject == null)
+ {
+ ArrayList<ManagedEntityType> allTypes = new ArrayList<ManagedEntityType>(_entityTypes.values());
+ for(ManagedEntityType entityType : allTypes)
+ {
+ if(Arrays.asList(entityType.getParents()).contains(met))
+ {
+ subject = findSubject(name, id, entityType);
+ if(subject != null)
+ {
+ return subject;
+ }
+ }
+ }
+ }
+ return subject;
+ }
+
+ private ConfiguredObject findSubject(final String name, final String id, final ManagedEntityType entityType)
+ {
+
+ Map<String, ConfiguredObject> objects = _entities.get(entityType);
+ if(name != null)
+ {
+ ConfiguredObject subject = objects.get(name);
+ if(subject != null)
+ {
+ return subject;
+ }
+ }
+ else
+ {
+ final Collection<ConfiguredObject> values = new ArrayList<ConfiguredObject>(objects.values());
+ for(ConfiguredObject o : values)
+ {
+ if(o.getId().toString().equals(id))
+ {
+ return o;
+ }
+ }
+ }
+ return null;
+ }
+
+ private InternalMessage createFailureResponse(final InternalMessage requestMessage,
+ final int statusCode,
+ final String stateDescription,
+ String... params)
+ {
+ final InternalMessageHeader requestHeader = requestMessage.getMessageHeader();
+ final MutableMessageHeader responseHeader = new MutableMessageHeader();
+ responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null
+ ? requestHeader.getMessageId()
+ : requestHeader.getCorrelationId());
+ responseHeader.setMessageId(UUID.randomUUID().toString());
+ for(String header : requestHeader.getHeaderNames())
+ {
+ responseHeader.setHeader(header, requestHeader.getHeader(header));
+ }
+ responseHeader.setHeader(STATUS_CODE_HEADER, statusCode);
+ responseHeader.setHeader(STATUS_DESCRIPTION_HEADER, MessageFormat.format(stateDescription, params));
+ return InternalMessage.createBytesMessage(_virtualHost.getMessageStore(), responseHeader, new byte[0]);
+
+ }
+
+ private InternalMessage performManagementOperation(final InternalMessage msg)
+ {
+ final InternalMessage responseMessage;
+ final InternalMessageHeader requestHeader = msg.getMessageHeader();
+ final MutableMessageHeader responseHeader = new MutableMessageHeader();
+ responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null
+ ? requestHeader.getMessageId()
+ : requestHeader.getCorrelationId());
+ responseHeader.setMessageId(UUID.randomUUID().toString());
+
+
+ String operation = (String) requestHeader.getHeader(OPERATION_HEADER);
+ if(GET_TYPES.equals(operation))
+ {
+ responseMessage = performGetTypes(requestHeader, responseHeader);
+ }
+ else if(GET_ATTRIBUTES.equals(operation))
+ {
+ responseMessage = performGetAttributes(requestHeader, responseHeader);
+ }
+ else if(GET_OPERATIONS.equals(operation))
+ {
+ responseMessage = performGetOperations(requestHeader, responseHeader);
+ }
+ else if(QUERY.equals(operation))
+ {
+ responseMessage = performQuery(requestHeader, responseHeader);
+ }
+ else
+ {
+ responseMessage = InternalMessage.createBytesMessage(_virtualHost.getMessageStore(), requestHeader, new byte[0]);
+ }
+ return responseMessage;
+ }
+
+ private InternalMessage performGetTypes(final InternalMessageHeader requestHeader,
+ final MutableMessageHeader responseHeader)
+ {
+ final InternalMessage responseMessage;
+ List<String> restriction;
+ if(requestHeader.containsHeader(ENTITY_TYPES_HEADER))
+ {
+ restriction = (List<String>) requestHeader.getHeader(ENTITY_TYPES_HEADER);
+ }
+ else
+ {
+ restriction = null;
+ }
+
+ responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_OK);
+ Map<String,Object> responseMap = new LinkedHashMap<String, Object>();
+ Map<String,ManagedEntityType> entityMapCopy;
+ synchronized (_entityTypes)
+ {
+ entityMapCopy = new LinkedHashMap<String, ManagedEntityType>(_entityTypes);
+ }
+
+ for(ManagedEntityType type : entityMapCopy.values())
+ {
+ if(restriction == null || meetsIndirectRestriction(type,restriction))
+ {
+ final ManagedEntityType[] parents = type.getParents();
+ List<String> parentNames = new ArrayList<String>();
+ if(parents != null)
+ {
+ for(ManagedEntityType parent : parents)
+ {
+ parentNames.add(parent.getName());
+ }
+ }
+ responseMap.put(type.getName(), parentNames);
+ }
+ }
+ responseMessage = InternalMessage.createMapMessage(_virtualHost.getMessageStore(), responseHeader, responseMap);
+ return responseMessage;
+ }
+
+ private InternalMessage performGetAttributes(final InternalMessageHeader requestHeader,
+ final MutableMessageHeader responseHeader)
+ {
+ final InternalMessage responseMessage;
+ List<String> restriction;
+ if(requestHeader.containsHeader(ENTITY_TYPES_HEADER))
+ {
+ restriction = (List<String>) requestHeader.getHeader(ENTITY_TYPES_HEADER);
+ }
+ else
+ {
+ restriction = null;
+ }
+
+ responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_OK);
+ Map<String,Object> responseMap = new LinkedHashMap<String, Object>();
+ Map<String,ManagedEntityType> entityMapCopy;
+ synchronized (_entityTypes)
+ {
+ entityMapCopy = new LinkedHashMap<String, ManagedEntityType>(_entityTypes);
+ }
+
+ for(ManagedEntityType type : entityMapCopy.values())
+ {
+ if(restriction == null || restriction.contains(type.getName()))
+ {
+ responseMap.put(type.getName(), Arrays.asList(type.getAttributes()));
+ }
+ }
+ responseMessage = InternalMessage.createMapMessage(_virtualHost.getMessageStore(), responseHeader, responseMap);
+ return responseMessage;
+ }
+
+
+ private InternalMessage performGetOperations(final InternalMessageHeader requestHeader,
+ final MutableMessageHeader responseHeader)
+ {
+ final InternalMessage responseMessage;
+ List<String> restriction;
+ if(requestHeader.containsHeader(ENTITY_TYPES_HEADER))
+ {
+ restriction = (List<String>) requestHeader.getHeader(ENTITY_TYPES_HEADER);
+ }
+ else
+ {
+ restriction = null;
+ }
+
+ responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_OK);
+ Map<String,Object> responseMap = new LinkedHashMap<String, Object>();
+ Map<String,ManagedEntityType> entityMapCopy;
+ synchronized (_entityTypes)
+ {
+ entityMapCopy = new LinkedHashMap<String, ManagedEntityType>(_entityTypes);
+ }
+
+ for(ManagedEntityType type : entityMapCopy.values())
+ {
+ if(restriction == null || restriction.contains(type.getName()))
+ {
+ responseMap.put(type.getName(), Arrays.asList(type.getOperations()));
+ }
+ }
+ responseMessage = InternalMessage.createMapMessage(_virtualHost.getMessageStore(), responseHeader, responseMap);
+ return responseMessage;
+ }
+
+ private InternalMessage performQuery(final InternalMessageHeader requestHeader,
+ final MutableMessageHeader responseHeader)
+ {
+ final InternalMessage responseMessage;
+ List<String> restriction;
+ List<String> attributes;
+ int offset;
+ int count;
+
+ if(requestHeader.containsHeader(ENTITY_TYPES_HEADER))
+ {
+ restriction = (List<String>) requestHeader.getHeader(ENTITY_TYPES_HEADER);
+ responseHeader.setHeader(ENTITY_TYPES_HEADER, restriction);
+ }
+ else
+ {
+ restriction = new ArrayList<String>(_entityTypes.keySet());
+ }
+
+
+ if(requestHeader.containsHeader(ATTRIBUTES_HEADER))
+ {
+ attributes = (List<String>) requestHeader.getHeader(ATTRIBUTES_HEADER);
+ }
+ else
+ {
+ LinkedHashMap<String,Void> attributeSet = new LinkedHashMap<String, Void>();
+ for(String entityType : restriction)
+ {
+ ManagedEntityType type = _entityTypes.get(entityType);
+ if(type != null)
+ {
+ for(String attributeName : type.getAttributes())
+ {
+ attributeSet.put(attributeName, null);
+ }
+ }
+ }
+ attributes = new ArrayList<String>(attributeSet.keySet());
+
+ }
+
+ if(requestHeader.containsHeader(OFFSET_HEADER))
+ {
+ offset = ((Number) requestHeader.getHeader(OFFSET_HEADER)).intValue();
+ responseHeader.setHeader(OFFSET_HEADER,offset);
+ }
+ else
+ {
+ offset = 0;
+ }
+
+ if(requestHeader.containsHeader(COUNT_HEADER))
+ {
+ count = ((Number) requestHeader.getHeader(COUNT_HEADER)).intValue();
+ }
+ else
+ {
+ count = Integer.MAX_VALUE;
+ }
+
+ responseHeader.setHeader(ATTRIBUTES_HEADER, attributes);
+
+ responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_OK);
+ List<List<Object>> responseList = new ArrayList<List<Object>>();
+
+ int rowNo = 0;
+ for(String type : restriction)
+ {
+ ManagedEntityType entityType = _entityTypes.get(type);
+ if(entityType != null)
+ {
+ Map<String, ConfiguredObject> entityMap = _entities.get(entityType);
+ if(entityMap != null)
+ {
+ List<ConfiguredObject> entities;
+ synchronized(entityMap)
+ {
+ entities = new ArrayList<ConfiguredObject>(entityMap.values());
+ }
+ for(ConfiguredObject entity : entities)
+ {
+ if(rowNo++ >= offset)
+ {
+ Object[] attrValue = new Object[attributes.size()];
+ int col = 0;
+ for(String attr : attributes)
+ {
+ Object value;
+ if(TYPE_ATTRIBUTE.equals(attr))
+ {
+ value = entityType.getName();
+ }
+ else
+ {
+ value = fixValue(entity.getAttribute(attr));
+ }
+ attrValue[col++] = value;
+ }
+ responseList.add(Arrays.asList(attrValue));
+ }
+ if(responseList.size()==count)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if(responseList.size()==count)
+ {
+ break;
+ }
+ }
+ responseHeader.setHeader(COUNT_HEADER, count);
+ responseMessage = InternalMessage.createListMessage(_virtualHost.getMessageStore(),
+ responseHeader,
+ responseList);
+ return responseMessage;
+ }
+
+ private Object fixValue(final Object value)
+ {
+ Object fixedValue;
+ if(value instanceof Enum)
+ {
+ fixedValue = value.toString();
+ }
+ else if(value instanceof Map)
+ {
+ Map<Object, Object> oldValue = (Map<Object, Object>) value;
+ Map<Object, Object> newValue = new LinkedHashMap<Object, Object>();
+ for(Map.Entry<Object, Object> entry : oldValue.entrySet())
+ {
+ newValue.put(fixValue(entry.getKey()),fixValue(entry.getValue()));
+ }
+ fixedValue = newValue;
+ }
+ else if(value instanceof Collection)
+ {
+ Collection oldValue = (Collection) value;
+ List newValue = new ArrayList(oldValue.size());
+ for(Object o : oldValue)
+ {
+ newValue.add(fixValue(o));
+ }
+ fixedValue = newValue;
+ }
+ else if(value != null && value.getClass().isArray() && !(value instanceof byte[]))
+ {
+ fixedValue = fixValue(Arrays.asList((Object[])value));
+ }
+ else
+ {
+ fixedValue = value;
+ }
+ return fixedValue;
+
+ }
+
+
+ private boolean meetsIndirectRestriction(final ManagedEntityType type, final List<String> restriction)
+ {
+ if(restriction.contains(type.getName()))
+ {
+ return true;
+ }
+ if(type.getParents() != null)
+ {
+ for(ManagedEntityType parent : type.getParents())
+ {
+ if(meetsIndirectRestriction(parent, restriction))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized <T extends ConsumerTarget> ManagementNodeConsumer addConsumer(final T target,
+ final FilterManager filters,
+ final Class<? extends ServerMessage> messageClass,
+ final String consumerName,
+ final EnumSet<Consumer.Option> options) throws AMQException
+ {
+
+ final ManagementNodeConsumer managementNodeConsumer = new ManagementNodeConsumer(consumerName,this, target);
+ target.consumerAdded(managementNodeConsumer);
+ _consumers.put(consumerName, managementNodeConsumer);
+ for(ConsumerRegistrationListener<ManagementNode> listener : _consumerRegistrationListeners)
+ {
+ listener.consumerAdded(this, managementNodeConsumer);
+ }
+ return managementNodeConsumer;
+ }
+
+ @Override
+ public synchronized Collection<ManagementNodeConsumer> getConsumers()
+ {
+ return new ArrayList<ManagementNodeConsumer>(_consumers.values());
+ }
+
+ @Override
+ public void addConsumerRegistrationListener(final ConsumerRegistrationListener<ManagementNode> listener)
+ {
+ _consumerRegistrationListeners.add(listener);
+ }
+
+ @Override
+ public void removeConsumerRegistrationListener(final ConsumerRegistrationListener listener)
+ {
+ _consumerRegistrationListeners.remove(listener);
+ }
+
+ @Override
+ public AuthorizationHolder getAuthorizationHolder()
+ {
+ return null;
+ }
+
+ @Override
+ public void setAuthorizationHolder(final AuthorizationHolder principalHolder)
+ {
+
+ }
+
+ @Override
+ public void setExclusiveOwningSession(final AMQSessionModel owner)
+ {
+
+ }
+
+ @Override
+ public AMQSessionModel getExclusiveOwningSession()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isExclusive()
+ {
+ return false;
+ }
+
+ @Override
+ public String getName()
+ {
+ return MANAGEMENT_NODE_NAME;
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return _id;
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return false;
+ }
+
+ private class ConsumedMessageInstance implements MessageInstance<ConsumedMessageInstance,Consumer>
+ {
+ private final ServerMessage _message;
+ private final InstanceProperties _properties;
+
+ public ConsumedMessageInstance(final ServerMessage message,
+ final InstanceProperties properties)
+ {
+ _message = message;
+ _properties = properties;
+ }
+
+ @Override
+ public int getDeliveryCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public void incrementDeliveryCount()
+ {
+
+ }
+
+ @Override
+ public void decrementDeliveryCount()
+ {
+
+ }
+
+ @Override
+ public void addStateChangeListener(final StateChangeListener<? super ConsumedMessageInstance, State> listener)
+ {
+
+ }
+
+ @Override
+ public boolean removeStateChangeListener(final StateChangeListener<? super ConsumedMessageInstance, State> listener)
+ {
+ return false;
+ }
+
+
+ @Override
+ public boolean acquiredByConsumer()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isAcquiredBy(final Consumer consumer)
+ {
+ return false;
+ }
+
+ @Override
+ public void setRedelivered()
+ {
+
+ }
+
+ @Override
+ public boolean isRedelivered()
+ {
+ return false;
+ }
+
+ @Override
+ public Consumer getDeliveredConsumer()
+ {
+ return null;
+ }
+
+ @Override
+ public void reject()
+ {
+
+ }
+
+ @Override
+ public boolean isRejectedBy(final Consumer consumer)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean getDeliveredToConsumer()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean expired() throws AMQException
+ {
+ return false;
+ }
+
+ @Override
+ public boolean acquire(final Consumer sub)
+ {
+ return false;
+ }
+
+ @Override
+ public int getMaximumDeliveryCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public int routeToAlternate(final Action<? super MessageInstance<?, ? extends Consumer>> action,
+ final ServerTransaction txn)
+ {
+ return 0;
+ }
+
+
+ @Override
+ public Filterable asFilterable()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isAvailable()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean acquire()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isAcquired()
+ {
+ return false;
+ }
+
+ @Override
+ public void release()
+ {
+
+ }
+
+ @Override
+ public boolean resend() throws AMQException
+ {
+ return false;
+ }
+
+ @Override
+ public void delete()
+ {
+
+ }
+
+ @Override
+ public boolean isDeleted()
+ {
+ return false;
+ }
+
+ @Override
+ public ServerMessage getMessage()
+ {
+ return _message;
+ }
+
+ @Override
+ public InstanceProperties getInstanceProperties()
+ {
+ return _properties;
+ }
+
+ @Override
+ public TransactionLogResource getOwningResource()
+ {
+ return ManagementNode.this;
+ }
+ }
+
+ private class ModelObjectListener implements ConfigurationChangeListener
+ {
+ @Override
+ public void stateChanged(final ConfiguredObject object, final State oldState, final State newState)
+ {
+ if(newState == State.DELETED)
+ {
+ _registry.removeSystemNode(ManagementNode.this);
+ }
+ }
+
+ @Override
+ public void childAdded(final ConfiguredObject object, final ConfiguredObject child)
+ {
+ final ManagedEntityType entityType = _entityTypes.get(getManagementClass(child.getClass()).getName());
+ if(entityType != null)
+ {
+ _entities.get(entityType).put(child.getName(), child);
+ }
+ }
+
+ @Override
+ public void childRemoved(final ConfiguredObject object, final ConfiguredObject child)
+ {
+ final ManagedEntityType entityType = _entityTypes.get(getManagementClass(child.getClass()).getName());
+ if(entityType != null)
+ {
+ _entities.get(entityType).remove(child.getName());
+ }
+ }
+
+ @Override
+ public void attributeSet(final ConfiguredObject object,
+ final String attributeName,
+ final Object oldAttributeValue,
+ final Object newAttributeValue)
+ {
+
+ }
+ }
+
+ private static class MutableMessageHeader implements AMQMessageHeader
+ {
+ private final LinkedHashMap<String, Object> _headers = new LinkedHashMap<String, Object>();
+ private String _correlationId;
+ private long _expiration;
+ private String _userId;
+ private String _appId;
+ private String _messageId;
+ private String _mimeType;
+ private String _encoding;
+ private byte _priority;
+ private long _timestamp;
+ private String _type;
+ private String _replyTo;
+
+ public void setCorrelationId(final String correlationId)
+ {
+ _correlationId = correlationId;
+ }
+
+ public void setExpiration(final long expiration)
+ {
+ _expiration = expiration;
+ }
+
+ public void setUserId(final String userId)
+ {
+ _userId = userId;
+ }
+
+ public void setAppId(final String appId)
+ {
+ _appId = appId;
+ }
+
+ public void setMessageId(final String messageId)
+ {
+ _messageId = messageId;
+ }
+
+ public void setMimeType(final String mimeType)
+ {
+ _mimeType = mimeType;
+ }
+
+ public void setEncoding(final String encoding)
+ {
+ _encoding = encoding;
+ }
+
+ public void setPriority(final byte priority)
+ {
+ _priority = priority;
+ }
+
+ public void setTimestamp(final long timestamp)
+ {
+ _timestamp = timestamp;
+ }
+
+ public void setType(final String type)
+ {
+ _type = type;
+ }
+
+ public void setReplyTo(final String replyTo)
+ {
+ _replyTo = replyTo;
+ }
+
+ public String getCorrelationId()
+ {
+ return _correlationId;
+ }
+
+ public long getExpiration()
+ {
+ return _expiration;
+ }
+
+ public String getUserId()
+ {
+ return _userId;
+ }
+
+ public String getAppId()
+ {
+ return _appId;
+ }
+
+ public String getMessageId()
+ {
+ return _messageId;
+ }
+
+ public String getMimeType()
+ {
+ return _mimeType;
+ }
+
+ public String getEncoding()
+ {
+ return _encoding;
+ }
+
+ public byte getPriority()
+ {
+ return _priority;
+ }
+
+ public long getTimestamp()
+ {
+ return _timestamp;
+ }
+
+ public String getType()
+ {
+ return _type;
+ }
+
+ public String getReplyTo()
+ {
+ return _replyTo;
+ }
+
+ @Override
+ public Object getHeader(final String name)
+ {
+ return _headers.get(name);
+ }
+
+ @Override
+ public boolean containsHeaders(final Set<String> names)
+ {
+ return _headers.keySet().containsAll(names);
+ }
+
+ @Override
+ public boolean containsHeader(final String name)
+ {
+ return _headers.containsKey(name);
+ }
+
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ return Collections.unmodifiableCollection(_headers.keySet());
+ }
+
+ public void setHeader(String header, Object value)
+ {
+ _headers.put(header,value);
+ }
+
+ }
+}
diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java
new file mode 100644
index 0000000000..98bb20d364
--- /dev/null
+++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java
@@ -0,0 +1,242 @@
+/*
+ *
+ * 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.management.amqp;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.util.StateChangeListener;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+class ManagementNodeConsumer implements Consumer
+{
+ private final long _id = Consumer.SUB_ID_GENERATOR.getAndIncrement();
+ private final ManagementNode _managementNode;
+ private final List<ManagementResponse> _queue = Collections.synchronizedList(new ArrayList<ManagementResponse>());
+ private final ConsumerTarget _target;
+ private final Lock _stateChangeLock = new ReentrantLock();
+ private final String _name;
+ private final StateChangeListener<ConsumerTarget, ConsumerTarget.State> _targetChangeListener = new TargetChangeListener();
+
+
+ public ManagementNodeConsumer(final String consumerName, final ManagementNode managementNode, ConsumerTarget target)
+ {
+ _name = consumerName;
+ _managementNode = managementNode;
+ _target = target;
+ target.setStateListener(_targetChangeListener);
+ }
+
+ @Override
+ public void externalStateChange()
+ {
+
+ }
+
+ @Override
+ public long getBytesOut()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getMessagesOut()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getUnacknowledgedBytes()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getUnacknowledgedMessages()
+ {
+ return 0;
+ }
+
+ @Override
+ public AMQSessionModel getSessionModel()
+ {
+ return _target.getSessionModel();
+ }
+
+ @Override
+ public void setNoLocal(final boolean noLocal)
+ {
+ }
+
+ @Override
+ public long getId()
+ {
+ return _id;
+ }
+
+ @Override
+ public boolean isSuspended()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isClosed()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean acquires()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean seesRequeues()
+ {
+ return false;
+ }
+
+ @Override
+ public void close() throws AMQException
+ {
+
+ }
+
+ @Override
+ public boolean trySendLock()
+ {
+ return _stateChangeLock.tryLock();
+ }
+
+ @Override
+ public void getSendLock()
+ {
+ _stateChangeLock.lock();
+ }
+
+ @Override
+ public void releaseSendLock()
+ {
+ _stateChangeLock.unlock();
+ }
+
+
+ @Override
+ public boolean isActive()
+ {
+ return false;
+ }
+
+ @Override
+ public String getName()
+ {
+ return _name;
+ }
+
+ @Override
+ public void flush() throws AMQException
+ {
+
+ }
+
+ ManagementNode getManagementNode()
+ {
+ return _managementNode;
+ }
+
+ void send(final InternalMessage response)
+ {
+ getSendLock();
+ try
+ {
+ final ManagementResponse responseEntry = new ManagementResponse(this, response);
+ if(_queue.isEmpty() && _target.allocateCredit(response))
+ {
+ _target.send(responseEntry,false);
+ }
+ else
+ {
+ _queue.add(responseEntry);
+ }
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ releaseSendLock();
+ }
+ }
+
+ private class TargetChangeListener implements StateChangeListener<ConsumerTarget, ConsumerTarget.State>
+ {
+ @Override
+ public void stateChanged(final ConsumerTarget object,
+ final ConsumerTarget.State oldState,
+ final ConsumerTarget.State newState)
+ {
+ if(newState == ConsumerTarget.State.ACTIVE)
+ {
+ deliverMessages();
+ }
+ }
+ }
+
+ private void deliverMessages()
+ {
+ getSendLock();
+ try
+ {
+ while(!_queue.isEmpty())
+ {
+
+ final ManagementResponse managementResponse = _queue.get(0);
+ if(!_target.isSuspended() && _target.allocateCredit(managementResponse.getMessage()))
+ {
+ _queue.remove(0);
+ _target.send(managementResponse,false);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ releaseSendLock();
+ }
+ }
+}
diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeCreator.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeCreator.java
new file mode 100644
index 0000000000..cdb71f4859
--- /dev/null
+++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeCreator.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.management.amqp;
+
+import org.apache.qpid.server.plugin.SystemNodeCreator;
+
+public class ManagementNodeCreator implements SystemNodeCreator
+{
+ @Override
+ public void register(final SystemNodeRegistry registry)
+ {
+ ManagementNode managementNode = new ManagementNode(registry,registry.getVirtualHostModel());
+ registry.registerSystemNode(managementNode);
+ }
+
+ @Override
+ public String getType()
+ {
+ return "AMQP-VIRTUALHOST-MANAGEMENT";
+ }
+}
diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java
new file mode 100644
index 0000000000..e25f327420
--- /dev/null
+++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java
@@ -0,0 +1,220 @@
+/*
+ *
+ * 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.management.amqp;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.consumer.Consumer;
+import org.apache.qpid.server.filter.Filterable;
+import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.util.StateChangeListener;
+
+class ManagementResponse implements MessageInstance<ManagementResponse,ManagementNodeConsumer>
+{
+ private final ManagementNodeConsumer _consumer;
+ private int _deliveryCount;
+ private boolean _isRedelivered;
+ private boolean _isDelivered;
+ private boolean _isDeleted;
+ private InternalMessage _message;
+
+ ManagementResponse(final ManagementNodeConsumer consumer, final InternalMessage message)
+ {
+ _consumer = consumer;
+ _message = message;
+ }
+
+ @Override
+ public int getDeliveryCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public void incrementDeliveryCount()
+ {
+ _deliveryCount++;
+ }
+
+ @Override
+ public void decrementDeliveryCount()
+ {
+ _deliveryCount--;
+ }
+
+ @Override
+ public void addStateChangeListener(final StateChangeListener<? super ManagementResponse, State> listener)
+ {
+
+ }
+
+ @Override
+ public boolean removeStateChangeListener(final StateChangeListener<? super ManagementResponse, State> listener)
+ {
+ return false;
+ }
+
+
+ @Override
+ public boolean acquiredByConsumer()
+ {
+ return !isDeleted();
+ }
+
+ @Override
+ public boolean isAcquiredBy(final ManagementNodeConsumer consumer)
+ {
+ return consumer == _consumer && !isDeleted();
+ }
+
+ @Override
+ public void setRedelivered()
+ {
+ _isRedelivered = true;
+ }
+
+ @Override
+ public boolean isRedelivered()
+ {
+ return _isRedelivered;
+ }
+
+ @Override
+ public ManagementNodeConsumer getDeliveredConsumer()
+ {
+ return isDeleted() ? null : _consumer;
+ }
+
+ @Override
+ public void reject()
+ {
+ delete();
+ }
+
+ @Override
+ public boolean isRejectedBy(final ManagementNodeConsumer consumer)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean getDeliveredToConsumer()
+ {
+ return _isDelivered;
+ }
+
+ @Override
+ public boolean expired() throws AMQException
+ {
+ return false;
+ }
+
+ @Override
+ public boolean acquire(final ManagementNodeConsumer sub)
+ {
+ return false;
+ }
+
+ @Override
+ public int getMaximumDeliveryCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public int routeToAlternate(final Action<? super MessageInstance<?, ? extends Consumer>> action,
+ final ServerTransaction txn)
+ {
+ return 0;
+ }
+
+
+ @Override
+ public Filterable asFilterable()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isAvailable()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean acquire()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isAcquired()
+ {
+ return !isDeleted();
+ }
+
+ @Override
+ public void release()
+ {
+ delete();
+ }
+
+ @Override
+ public boolean resend() throws AMQException
+ {
+ return false;
+ }
+
+ @Override
+ public void delete()
+ {
+ // TODO
+ }
+
+ @Override
+ public boolean isDeleted()
+ {
+ return _isDeleted;
+ }
+
+ @Override
+ public ServerMessage getMessage()
+ {
+ return _message;
+ }
+
+ @Override
+ public InstanceProperties getInstanceProperties()
+ {
+ return InstanceProperties.EMPTY;
+ }
+
+ @Override
+ public TransactionLogResource getOwningResource()
+ {
+ return _consumer.getManagementNode();
+ }
+}
diff --git a/qpid/java/broker-plugins/management-amqp/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.SystemNodeCreator b/qpid/java/broker-plugins/management-amqp/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.SystemNodeCreator
new file mode 100644
index 0000000000..767f93782b
--- /dev/null
+++ b/qpid/java/broker-plugins/management-amqp/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.SystemNodeCreator
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+org.apache.qpid.server.management.amqp.ManagementNodeCreator
diff --git a/qpid/java/broker-plugins/management-http/pom.xml b/qpid/java/broker-plugins/management-http/pom.xml
index 57b2dd863b..d614bbf0b1 100644
--- a/qpid/java/broker-plugins/management-http/pom.xml
+++ b/qpid/java/broker-plugins/management-http/pom.xml
@@ -16,151 +16,51 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-management-http</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid HTTP Management Broker Plug-in</name>
+ <description>HTTP Management broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_3.0_spec</artifactId>
- <version>1.0</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty.orbit</groupId>
- <artifactId>javax.servlet</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-continuation</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-continuation</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-security</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-security</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-websocket</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
@@ -174,7 +74,7 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java
index 4d85d52997..0329379713 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java
@@ -19,9 +19,6 @@ package org.apache.qpid.server.management.plugin.servlet.rest;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
index a71d833fc3..9ca23ce1ce 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
@@ -20,7 +20,6 @@ package org.apache.qpid.server.management.plugin.servlet.rest;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@@ -40,7 +39,7 @@ import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.queue.QueueEntryVisitor;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.access.Operation;
-import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.consumer.Consumer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
@@ -327,8 +326,8 @@ public class MessageServlet extends AbstractServlet
: entry.isAcquired()
? "Acquired"
: "");
- final Subscription deliveredSubscription = entry.getDeliveredSubscription();
- object.put("deliveredTo", deliveredSubscription == null ? null : deliveredSubscription.getSubscriptionID());
+ final Consumer deliveredConsumer = entry.getDeliveredConsumer();
+ object.put("deliveredTo", deliveredConsumer == null ? null : deliveredConsumer.getId());
ServerMessage message = entry.getMessage();
if(message != null)
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
index 9a24e23407..410a5d23ca 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
@@ -35,16 +35,16 @@
<tr>
<td valign="top"><strong>Queue Type: </strong></td>
<td>
- <input type="radio" id="formAddQueueTypeStandard" name="type" value="standard" checked="checked" dojoType="dijit.form.RadioButton" />
+ <input type="radio" id="formAddQueueTypeStandard" name="queueType" value="standard" checked="checked" dojoType="dijit.form.RadioButton" />
<label for="formAddQueueTypeStandard">Standard</label>
&nbsp;&nbsp;
- <input type="radio" id="formAddQueueTypePriority" name="type" value="priority" dojoType="dijit.form.RadioButton" />
+ <input type="radio" id="formAddQueueTypePriority" name="queueType" value="priority" dojoType="dijit.form.RadioButton" />
<label for="formAddQueueTypePriority">Priority</label>
&nbsp;&nbsp;
- <input type="radio" id="formAddQueueTypeLVQ" name="type" value="lvq" dojoType="dijit.form.RadioButton" />
+ <input type="radio" id="formAddQueueTypeLVQ" name="queueType" value="lvq" dojoType="dijit.form.RadioButton" />
<label for="formAddQueueTypeLVQ">LVQ</label>
&nbsp;&nbsp;
- <input type="radio" id="formAddQueueTypeSorted" name="type" value="sorted" dojoType="dijit.form.RadioButton" />
+ <input type="radio" id="formAddQueueTypeSorted" name="queueType" value="sorted" dojoType="dijit.form.RadioButton" />
<label for="formAddQueueTypeSorted">Sorted</label>
</td>
</tr>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
index 54cfe225c8..606f95e349 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
@@ -277,7 +277,7 @@ define(["dojo/_base/xhr",
"exclusive",
"owner",
"lifetimePolicy",
- "type",
+ "queueType",
"typeQualifier",
"alertRepeatGap",
"alertRepeatGapUnits",
@@ -359,14 +359,14 @@ define(["dojo/_base/xhr",
bytesDepth = formatter.formatBytes( this.queueData["unacknowledgedBytes"] );
this.unacknowledgedBytes.innerHTML = "(" + bytesDepth.value;
this.unacknowledgedBytesUnits.innerHTML = bytesDepth.units + ")";
- this.type.innerHTML = entities.encode(this.queueData[ "type" ]);
- if (this.queueData.type == "standard")
+ this.queueType.innerHTML = entities.encode(this.queueData[ "queueType" ]);
+ if (this.queueData.queueType == "standard")
{
this.typeQualifier.style.display = "none";
}
else
{
- this.typeQualifier.innerHTML = entities.encode("(" + queueTypeKeyNames[this.queueData.type] + ": " + this.queueData[queueTypeKeys[this.queueData.type]] + ")");
+ this.typeQualifier.innerHTML = entities.encode("(" + queueTypeKeyNames[this.queueData.queueType] + ": " + this.queueData[queueTypeKeys[this.queueData.queueType]] + ")");
}
if(this.queueData["messageGroupKey"])
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
index e8b8dd1721..64e821b2dd 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
@@ -96,7 +96,7 @@ define(["dojo/_base/xhr",
}
}
else if (!typeSpecificFields.hasOwnProperty(propName) ||
- formValues.type === typeSpecificFields[ propName ]) {
+ formValues.queueType === typeSpecificFields[ propName ]) {
if(formValues[ propName ] !== "") {
if (fieldConverters.hasOwnProperty(propName))
{
@@ -130,7 +130,7 @@ define(["dojo/_base/xhr",
theForm = registry.byId("formAddQueue");
array.forEach(theForm.getDescendants(), function(widget)
{
- if(widget.name === "type") {
+ if(widget.name === "queueType") {
widget.on("change", function(isChecked) {
var objId = widget.id + ":fields";
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
index 89b7327957..252deb3100 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
@@ -47,7 +47,7 @@
<div style="clear:both">
<div class="formLabel-labelCell" style="float:left; width: 150px;">Type:</div>
<div style="float:left;">
- <span class="type"></span>
+ <span class="queueType"></span>
<span class="typeQualifier"></span>
</div>
</div>
diff --git a/qpid/java/broker-plugins/management-jmx/pom.xml b/qpid/java/broker-plugins/management-jmx/pom.xml
index 8a06fcf185..78b7f327ec 100644
--- a/qpid/java/broker-plugins/management-jmx/pom.xml
+++ b/qpid/java/broker-plugins/management-jmx/pom.xml
@@ -16,43 +16,44 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-management-jmx</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid JMX Management Broker Plug-in</name>
+ <description>JMX management broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-management-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
index 49cb6aa8cb..d74aa41244 100644
--- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
+++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
@@ -183,7 +183,7 @@ public class QueueMBean extends AMQManagedObject implements ManagedQueue, QueueN
@Override
public String getQueueType()
{
- return (String) _queue.getAttribute(Queue.TYPE);
+ return (String) _queue.getAttribute(Queue.QUEUE_TYPE);
}
public boolean isDurable()
diff --git a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java
index 3711a90f3b..f94c206512 100644
--- a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java
+++ b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java
@@ -127,7 +127,7 @@ public class QueueMBeanTest extends QpidTestCase
public void testQueueType() throws Exception
{
- assertAttribute("queueType", QUEUE_TYPE, Queue.TYPE);
+ assertAttribute("queueType", QUEUE_TYPE, Queue.QUEUE_TYPE);
}
public void testMaximumDeliveryCount() throws Exception
diff --git a/qpid/java/broker-plugins/memory-store/pom.xml b/qpid/java/broker-plugins/memory-store/pom.xml
index 6bfd2a8d49..bdf503cd89 100644
--- a/qpid/java/broker-plugins/memory-store/pom.xml
+++ b/qpid/java/broker-plugins/memory-store/pom.xml
@@ -16,21 +16,25 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-memory-store</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Memory Message Store Broker Plug-in</name>
+ <description>Memory message store broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/broker-plugins/websocket/pom.xml b/qpid/java/broker-plugins/websocket/pom.xml
index fb55be05c8..f7d9c45638 100644
--- a/qpid/java/broker-plugins/websocket/pom.xml
+++ b/qpid/java/broker-plugins/websocket/pom.xml
@@ -15,142 +15,45 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
- <artifactId>qpid-project</artifactId>
<groupId>org.apache.qpid</groupId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker-plugins-websocket</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid WebSocket Broker Plug-in</name>
+ <description>WebSocket broker plug-in</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_3.0_spec</artifactId>
- <version>1.0</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty.orbit</groupId>
- <artifactId>javax.servlet</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-continuation</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-continuation</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-security</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-servlet</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-security</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
- <version>8.1.14.v20131031</version>
- <scope>compile</scope>
- <exclusions>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- </exclusion>
- </exclusions>
</dependency>
- </dependencies>
+
+ </dependencies>
<build>
</build>
diff --git a/qpid/java/broker/pom.xml b/qpid/java/broker/pom.xml
index 6eb51a4b2e..9761819542 100644
--- a/qpid/java/broker/pom.xml
+++ b/qpid/java/broker/pom.xml
@@ -16,132 +16,130 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-broker</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Java Broker</name>
+ <description>Broker configuration and executable</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
- <version>1.2</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-access-control</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-8-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-10-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-1-0-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-msg-conv-0-8-to-0-10</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-msg-conv-0-8-to-1-0</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-msg-conv-0-10-to-1-0</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-derby-store</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-jdbc-provider-bone</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-jdbc-store</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-management-http</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-management-jmx</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-memory-store</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
@@ -149,7 +147,7 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-bdbstore</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
@@ -157,7 +155,7 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-bdbstore-jmx</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
@@ -166,7 +164,7 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/build.deps b/qpid/java/build.deps
index 4dc5b0ca46..0aa35954bf 100644
--- a/qpid/java/build.deps
+++ b/qpid/java/build.deps
@@ -103,6 +103,7 @@ perftests.test.libs=${test.libs}
qpid-test-utils.libs = ${test.libs} ${geronimo-jms}
broker-plugins-access-control.test.libs=${test.libs}
+broker-plugins-management-amqp.test.libs=${test.libs}
broker-plugins-management-http.test.libs=${test.libs}
broker-plugins-management-jmx.test.libs=${test.libs}
broker-plugins-jdbc-store.test.libs=${test.libs}
diff --git a/qpid/java/client/pom.xml b/qpid/java/client/pom.xml
index 3d9508eb16..f5623ff53c 100644
--- a/qpid/java/client/pom.xml
+++ b/qpid/java/client/pom.xml
@@ -16,42 +16,42 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-client</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid AMQP 0.x JMS Client</name>
+ <description>JMS client supporting AMQP 0-8, 0-9, 0-9-1 and 0-10.</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
- <version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java
index b408ad8ad1..b5a4166b55 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java
@@ -64,7 +64,7 @@ public class FieldTableKeyEnumeratorTest extends TestCase
}
- public void testPropertEnu()
+ public void testPropertyEnum()
{
try
{
diff --git a/qpid/java/common/pom.xml b/qpid/java/common/pom.xml
index d931c799a3..7ea7f5907a 100644
--- a/qpid/java/common/pom.xml
+++ b/qpid/java/common/pom.xml
@@ -16,14 +16,18 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-common</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Common</name>
+ <description>Common functionality</description>
<properties>
<!-- used during the antrun-plugin execution -->
@@ -37,15 +41,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
@@ -91,17 +93,17 @@
<dependency>
<groupId>velocity</groupId>
<artifactId>velocity</artifactId>
- <version>1.4</version>
+ <version>${velocity-version}</version>
</dependency>
<dependency>
<groupId>velocity</groupId>
<artifactId>velocity-dep</artifactId>
- <version>1.4</version>
+ <version>${velocity-version}</version>
</dependency>
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
- <version>2.5.3</version>
+ <version>${jython-version}</version>
</dependency>
</dependencies>
</plugin>
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
index 60dac24cfc..fe8c94cee1 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
@@ -30,8 +30,8 @@ import java.io.IOException;
public class BasicContentHeaderProperties
{
//persistent & non-persistent constants, values as per JMS DeliveryMode
- public static final int NON_PERSISTENT = 1;
- public static final int PERSISTENT = 2;
+ public static final byte NON_PERSISTENT = 1;
+ public static final byte PERSISTENT = 2;
private static final Logger _logger = LoggerFactory.getLogger(BasicContentHeaderProperties.class);
diff --git a/qpid/java/ivy.nexus.xml b/qpid/java/ivy.nexus.xml
index 55b2d2d729..8683062288 100644
--- a/qpid/java/ivy.nexus.xml
+++ b/qpid/java/ivy.nexus.xml
@@ -51,6 +51,12 @@
<artifact name="qpid-broker-plugins-access-control" type="jar.asc" ext="jar.asc"/>
<artifact name="qpid-broker-plugins-access-control" type="source" ext="jar" e:classifier="sources"/>
<artifact name="qpid-broker-plugins-access-control" type="source.asc" ext="jar.asc" e:classifier="sources"/>
+ <artifact name="qpid-broker-plugins-management-amqp" type="pom" ext="pom"/>
+ <artifact name="qpid-broker-plugins-management-amqp" type="pom.asc" ext="pom.asc"/>
+ <artifact name="qpid-broker-plugins-management-amqp" type="jar" ext="jar"/>
+ <artifact name="qpid-broker-plugins-management-amqp" type="jar.asc" ext="jar.asc"/>
+ <artifact name="qpid-broker-plugins-management-amqp" type="source" ext="jar" e:classifier="sources"/>
+ <artifact name="qpid-broker-plugins-management-amqp" type="source.asc" ext="jar.asc" e:classifier="sources"/>
<artifact name="qpid-broker-plugins-management-http" type="pom" ext="pom"/>
<artifact name="qpid-broker-plugins-management-http" type="pom.asc" ext="pom.asc"/>
<artifact name="qpid-broker-plugins-management-http" type="jar" ext="jar"/>
diff --git a/qpid/java/jca/pom.xml b/qpid/java/jca/pom.xml
index c7a8de61fe..ecff05f95a 100644
--- a/qpid/java/jca/pom.xml
+++ b/qpid/java/jca/pom.xml
@@ -16,69 +16,65 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-jca</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid JCA</name>
+ <description>J2EE Connector Architecture code</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-client</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-j2ee-connector_1.5_spec</artifactId>
- <version>2.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.1_spec</artifactId>
- <version>1.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
- <version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-ejb_3.0_spec</artifactId>
- <version>1.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_3.0_spec</artifactId>
- <version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.framework</groupId>
<artifactId>geronimo-kernel</artifactId>
- <version>2.2.1</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@@ -116,7 +112,7 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/jca/rar/pom.xml b/qpid/java/jca/rar/pom.xml
index fca35dba14..1f1aa5e6e0 100644
--- a/qpid/java/jca/rar/pom.xml
+++ b/qpid/java/jca/rar/pom.xml
@@ -16,22 +16,26 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-ra</artifactId>
+ <version>0.28-SNAPSHOT</version>
<packaging>rar</packaging>
+ <name>Qpid Resource Adaptor</name>
+ <description>Resource Adaptor</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-client</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
@@ -44,7 +48,7 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-jca</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
@@ -63,30 +67,4 @@
</plugins>
</build>
-<!-- <profiles>
- <profile>
- <id>deploy</id>
- <build>
- <defaultGoal>deploy</defaultGoal>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- <version>2.1.2</version>
- <configuration>
- <attach>false</attach>
- </configuration>
- <executions>
- <execution>
- <id>attach-sources</id>
- <goals>
- <goal>jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles> -->
</project>
diff --git a/qpid/java/management/common/pom.xml b/qpid/java/management/common/pom.xml
index ad5d103165..e08338ff8e 100644
--- a/qpid/java/management/common/pom.xml
+++ b/qpid/java/management/common/pom.xml
@@ -16,15 +16,19 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-management-common</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Management Common</name>
+ <description>Common management code</description>
<dependencies>
</dependencies>
diff --git a/qpid/java/management/example/pom.xml b/qpid/java/management/example/pom.xml
index bdddc3d2dc..d70d16c647 100644
--- a/qpid/java/management/example/pom.xml
+++ b/qpid/java/management/example/pom.xml
@@ -16,22 +16,25 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-management-examples</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Management Examples</name>
+ <description>Example management code</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-management-common</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
</dependencies>
diff --git a/qpid/java/perftests/pom.xml b/qpid/java/perftests/pom.xml
index 2a1dbd4350..ce60b13703 100644
--- a/qpid/java/perftests/pom.xml
+++ b/qpid/java/perftests/pom.xml
@@ -16,14 +16,18 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-perftests</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Performance Tests</name>
+ <description>Performance testing configuration, code and tests</description>
<properties>
<broker.home.dir>target${file.separator}qpid-broker${file.separator}${project.version}</broker.home.dir>
@@ -37,28 +41,22 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-client</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
- <version>1.0</version>
<scope>provided</scope>
</dependency>
@@ -66,35 +64,26 @@
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
- <version>2.6</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
- <version>3.2.1</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils-core</artifactId>
- <version>1.8.3</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
- <version>2.0</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
- <version>10.8.2.2</version>
<scope>runtime</scope>
</dependency>
@@ -102,14 +91,14 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-systests</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/perftests/visualisation-jfc/pom.xml b/qpid/java/perftests/visualisation-jfc/pom.xml
index d677491a03..ea0979de39 100644
--- a/qpid/java/perftests/visualisation-jfc/pom.xml
+++ b/qpid/java/perftests/visualisation-jfc/pom.xml
@@ -16,35 +16,35 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-perftests-visualisation-jfc</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Performance Tests Visualisation JFC</name>
+ <description>Performance testing visualisation using JFreeChart</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-perftests</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
- <version>10.8.2.2</version>
<scope>runtime</scope>
</dependency>
@@ -52,14 +52,14 @@
<dependency>
<groupId>net.sourceforge.csvjdbc</groupId>
<artifactId>csvjdbc</artifactId>
- <version>1.0.8</version>
+ <version>${csvjdbc-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jfree</groupId>
<artifactId>jfreechart</artifactId>
- <version>1.0.13</version>
+ <version>${jfreechart-version}</version>
<scope>provided</scope>
</dependency>
@@ -67,7 +67,7 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -109,4 +109,17 @@
</plugins>
</build>
+ <repositories>
+ <repository>
+ <id>csvjdbc.releases</id>
+ <url>http://csvjdbc.sourceforge.net/maven2</url>
+ <layout>default</layout>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
</project>
diff --git a/qpid/java/pom.xml b/qpid/java/pom.xml
index 54395ed4fe..3a5c9fd2e8 100644
--- a/qpid/java/pom.xml
+++ b/qpid/java/pom.xml
@@ -16,47 +16,56 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>12</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
- <!-- ###### TODO ######
- - Add the Excludes files, log4j config, etc test resources to a module (qpid-test-utils?) which can be
- used (extracted?) by the others to prevent them having to reference outside their directly for the files.
- - Fix what the systests/perftests do to copy the test-profiles dir to the necessary location.
- - Fix the log4j configuration property to work with all the modules.
- - Fix the version numbers in all the modules.
- - Decide on a final name for this parent module, qpid-project isnt necessarily appropriate given it doesnt encompass the whole project.
- - Test deploying the modules to a local Nexus instance (by overriding the repo properties locally).
- - Ensure we dont deploy modules we aren't already doing so, it will make changing them later less of a pain for everyone.
- - Figure out dependency setup for optional bdbstore tests.
- - Add the other test profiles, e.g. derby and other protocols.
- - Generate HTML reports of the test results
- - Decide on how to handle the surefire report target re-running the tests (there is a report-only task that doesnt, provided as a workaround)
- - Add LICENCE, NOTICE, README files to the binary assemblies.
- - Complete setting properties for all the dependency version numbers from the modules.
- - Use dependancy management sections to control the version numbers?
- - Align the XML in the pom files consistently, fix whitepsace errors.
-
- === Once the Ant build is removed ===
- - Move all the resources to be in the /src/foo/resources folders.
- - Make qpidversion.properties in common be a filtered resource instead of generated.
- - Get rid of the antrun-plugin execution in common, directly invoke the required java elements.
- - Do the above in the generate-sources-common profile instead of current default config.
- - Get rid of the antrun-plugin execution in broker-core, directly invoke the required java elements.
- - Fix the tests not to be dependant on the working dir being the java dir.
- - Fix the tests not to be dependant on the test config/output dirs being children of qpid.home.
- - Remove the QBTC output file mechanics, rely on Surefire to do it?
- - JUnit test profiles instead of Exludes files?
- -->
+ <name>Qpid</name>
+ <url>http://qpid.apache.org</url>
+ <description>Apache Qpidâ„¢ makes messaging tools that speak AMQP and support many languages and platforms. AMQP is an open internet protocol for reliably sending and receiving messages. It makes it possible for everyone to build a diverse, coherent messaging ecosystem.</description>
+
+ <issueManagement>
+ <system>JIRA</system>
+ <url>https://issues.apache.org/jira/browse/QPID</url>
+ </issueManagement>
+
+ <ciManagement>
+ <system>Jenkins</system>
+ <url>https://builds.apache.org/view/M-R/view/Qpid/</url>
+ </ciManagement>
+
+ <mailingLists>
+ <mailingList>
+ <name>Apache Qpid Users</name>
+ <subscribe>users-subscribe@qpid.apache.org</subscribe>
+ <unsubscribe>users-unsubscribe@qpid.apache.org</unsubscribe>
+ <post>users@qpid.apache.org</post>
+ <archive>http://mail-archives.apache.org/mod_mbox/qpid-users/</archive>
+ </mailingList>
+ <mailingList>
+ <name>Apache Qpid Developers</name>
+ <subscribe>dev-subscribe@qpid.apache.org</subscribe>
+ <unsubscribe>dev-unsubscribe@qpid.apache.org</unsubscribe>
+ <post>dev@qpid.apache.org</post>
+ <archive>http://mail-archives.apache.org/mod_mbox/qpid-dev/</archive>
+ </mailingList>
+ </mailingLists>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/qpid/trunk/qpid/java</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/qpid/trunk/qpid/java</developerConnection>
+ <url>http://svn.apache.org/viewvc/qpid/trunk/qpid/java</url>
+ </scm>
+
<prerequisites>
<maven>3.0.0</maven>
</prerequisites>
@@ -64,12 +73,39 @@
<properties>
<!-- dependency version numbers -->
<dojo-version>1.9.1</dojo-version>
+ <log4j-version>1.2.16</log4j-version>
+ <slf4j-version>1.6.4</slf4j-version>
+ <jetty-version>8.1.14.v20131031</jetty-version>
+ <jackson-version>1.9.1</jackson-version>
+ <bdb-version>5.0.97</bdb-version>
+ <gson-version>2.0</gson-version>
+ <guava-version>14.0.1</guava-version>
+ <bonecp-version>0.7.1.RELEASE</bonecp-version>
+ <commons-beanutils-version>1.8.3</commons-beanutils-version>
+ <commons-cli-version>1.2</commons-cli-version>
+ <commons-codec-version>1.6</commons-codec-version>
+ <commons-collections-version>3.2.1</commons-collections-version>
+ <commons-configuration-version>1.8</commons-configuration-version>
+ <commons-digester-version>1.8.1</commons-digester-version>
+ <commons-lang-version>2.6</commons-lang-version>
+ <commons-logging-version>1.1.1</commons-logging-version>
+ <geronimo-jms-version>1.0</geronimo-jms-version>
+ <geronimo-gta-version>1.1.1</geronimo-gta-version>
+ <geronimo-servlet-version>1.0</geronimo-servlet-version>
+ <geronimo-j2ee-connector-version>2.0.0</geronimo-j2ee-connector-version>
+ <geronimo-ejb-version>1.0.1</geronimo-ejb-version>
+ <geronimo-kernel-version>2.2.1</geronimo-kernel-version>
+ <xalan-version>2.7.0</xalan-version>
+ <bcel-version>5.2</bcel-version>
+ <velocity-version>1.4</velocity-version>
+ <derby-version>10.8.2.2</derby-version>
+ <jython-version>2.5.3</jython-version>
+ <csvjdbc-version>1.0.8</csvjdbc-version>
+ <jfreechart-version>1.0.13</jfreechart-version>
<!-- test dependency version numbers -->
<junit-version>3.8.1</junit-version>
<mockito-version>1.9.0</mockito-version>
- <log4j-version>1.2.16</log4j-version>
- <slf4j-version>1.6.4</slf4j-version>
<!-- plugin version numbers -->
<maven-antrun-plugin-version>1.7</maven-antrun-plugin-version>
@@ -105,7 +141,7 @@
<java.target>1.6</java.target>
<!-- enforcer plugin config properties -->
- <supported-test-profiles-regex>(java-mms.0-9-1|java-mms.0-10)</supported-test-profiles-regex>
+ <supported-test-profiles-regex>(java-mms.0-9-1|java-mms.0-10|java-bdb.0-10)</supported-test-profiles-regex>
<!-- test properties -->
<qpid.home>${basedir}</qpid.home> <!-- override for broker tests -->
@@ -120,30 +156,13 @@
<profile.excludes>${profile.excludes.java-mms.0-10}</profile.excludes>
</properties>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>${junit-version}</version>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <version>${mockito-version}</version>
- <scope>test</scope>
- </dependency>
-
- </dependencies>
-
<modules>
+ <module>amqp-1-0-common</module>
<module>amqp-1-0-client</module>
<module>amqp-1-0-client-jms</module>
<module>amqp-1-0-client-websocket</module>
- <module>amqp-1-0-common</module>
- <module>broker</module>
<module>broker-core</module>
+ <module>broker</module>
<module>broker-plugins/access-control</module>
<module>broker-plugins/amqp-0-8-protocol</module>
<module>broker-plugins/amqp-0-10-protocol</module>
@@ -154,6 +173,7 @@
<module>broker-plugins/derby-store</module>
<module>broker-plugins/jdbc-provider-bone</module>
<module>broker-plugins/jdbc-store</module>
+ <module>broker-plugins/management-amqp</module>
<module>broker-plugins/management-http</module>
<module>broker-plugins/management-jmx</module>
<module>broker-plugins/memory-store</module>
@@ -177,32 +197,263 @@
<module>bdbstore/systests</module>
</modules>
- <repositories>
- <!-- For the BDB JE dependency of the optional bdbstore plugin modules-->
- <repository>
- <id>oracle.releases</id>
- <url>http://download.oracle.com/maven</url>
- <layout>default</layout>
- <releases>
- <enabled>true</enabled>
- </releases>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- </repository>
- <!-- For the CSVJDBC dependency of the optional perftests-visualistion-jfc module-->
- <repository>
- <id>csvjdbc.releases</id>
- <url>http://csvjdbc.sourceforge.net/maven2</url>
- <layout>default</layout>
- <releases>
- <enabled>true</enabled>
- </releases>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- </repository>
- </repositories>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <dependencyManagement>
+ <dependencies>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit-version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>${mockito-version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>${log4j-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4j-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${jetty-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ <version>${jetty-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${jetty-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-core-asl</artifactId>
+ <version>${jackson-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ <version>${jackson-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.dojotoolkit</groupId>
+ <artifactId>dojo</artifactId>
+ <version>${dojo-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.sleepycat</groupId>
+ <artifactId>je</artifactId>
+ <version>${bdb-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils-core</artifactId>
+ <version>${commons-beanutils-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-digester</groupId>
+ <artifactId>commons-digester</artifactId>
+ <version>${commons-digester-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>${commons-lang-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>${commons-cli-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>${commons-codec-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>${commons-collections-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-configuration</groupId>
+ <artifactId>commons-configuration</artifactId>
+ <version>${commons-configuration-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>${commons-logging-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jms_1.1_spec</artifactId>
+ <version>${geronimo-jms-version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jta_1.1_spec</artifactId>
+ <version>${geronimo-gta-version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-servlet_3.0_spec</artifactId>
+ <version>${geronimo-servlet-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-j2ee-connector_1.5_spec</artifactId>
+ <version>${geronimo-j2ee-connector-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-ejb_3.0_spec</artifactId>
+ <version>${geronimo-ejb-version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.framework</groupId>
+ <artifactId>geronimo-kernel</artifactId>
+ <version>${geronimo-kernel-version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>xalan</groupId>
+ <artifactId>xalan</artifactId>
+ <version>${xalan-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.bcel</groupId>
+ <artifactId>bcel</artifactId>
+ <version>${bcel-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>velocity</groupId>
+ <artifactId>velocity</artifactId>
+ <version>${velocity-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>velocity</groupId>
+ <artifactId>velocity-dep</artifactId>
+ <version>${velocity-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <version>${derby-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.jolbox</groupId>
+ <artifactId>bonecp</artifactId>
+ <version>${bonecp-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>${gson-version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ </dependencies>
+ </dependencyManagement>
<build>
<pluginManagement>
@@ -497,41 +748,6 @@
</plugins>
</build>
- <description>
- Apache Qpidâ„¢ makes messaging tools that speak AMQP and support many languages and platforms.
- AMQP is an open internet protocol for reliably sending and receiving messages. It makes it possible for everyone to build a diverse, coherent messaging ecosystem.
- </description>
-
- <url>http://qpid.apache.org</url>
-
- <issueManagement>
- <system>JIRA</system>
- <url>https://issues.apache.org/jira/browse/QPID</url>
- </issueManagement>
-
- <mailingLists>
- <mailingList>
- <name>Apache Qpid Users</name>
- <subscribe>users-subscribe@qpid.apache.org</subscribe>
- <unsubscribe>users-unsubscribe@qpid.apache.org</unsubscribe>
- <post>users@qpid.apache.org</post>
- <archive>http://mail-archives.apache.org/mod_mbox/qpid-users/</archive>
- </mailingList>
- <mailingList>
- <name>Apache Qpid Developers</name>
- <subscribe>dev-subscribe@qpid.apache.org</subscribe>
- <unsubscribe>dev-unsubscribe@qpid.apache.org</unsubscribe>
- <post>dev@qpid.apache.org</post>
- <archive>http://mail-archives.apache.org/mod_mbox/qpid-dev/</archive>
- </mailingList>
- </mailingLists>
-
- <scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/qpid/trunk/qpid</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/qpid/trunk/qpid</developerConnection>
- <url>http://svn.apache.org/viewvc/qpid/</url>
- </scm>
-
<reporting>
<plugins>
<plugin>
@@ -548,6 +764,21 @@
</plugins>
</reporting>
+ <repositories>
+ <!-- For the BDB JE dependency of the optional bdbstore plugin modules-->
+ <repository>
+ <id>oracle.releases</id>
+ <url>http://download.oracle.com/maven</url>
+ <layout>default</layout>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
<profiles>
<profile>
<!-- Everything in this profile should already be set above by default in case someone sets an explicit non-test
@@ -605,6 +836,35 @@
</plugins>
</build>
</profile>
+
+ <profile>
+ <id>java-bdb.0-10</id>
+ <activation>
+ <property>
+ <name>profile</name>
+ <value>java-bdb.0-10</value>
+ </property>
+ </activation>
+ <properties>
+ <profile>java-bdb.0-10</profile>
+ <profile.excludes>JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes</profile.excludes>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <broker.version>v0_10</broker.version>
+ <qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</qpid.broker_default_amqp_protocol_excludes>
+ <broker.persistent>true</broker.persistent>
+ <messagestore.class.name>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</messagestore.class.name>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
</project>
diff --git a/qpid/java/qpid-test-utils/pom.xml b/qpid/java/qpid-test-utils/pom.xml
index a0acfec072..6e11616f4a 100644
--- a/qpid/java/qpid-test-utils/pom.xml
+++ b/qpid/java/qpid-test-utils/pom.xml
@@ -16,48 +16,44 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-test-utils</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Test Utilities</name>
+ <description>Testing utilities</description>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>${junit-version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
- <version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
diff --git a/qpid/java/systests/pom.xml b/qpid/java/systests/pom.xml
index 98086bbe9e..a556841240 100644
--- a/qpid/java/systests/pom.xml
+++ b/qpid/java/systests/pom.xml
@@ -16,14 +16,18 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-systests</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid System Tests</name>
+ <description>System testing configuration, code and tests</description>
<properties>
<broker.home.dir>target${file.separator}qpid-broker${file.separator}${project.version}</broker.home.dir>
@@ -51,36 +55,29 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-test-utils</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<!-- client deps -->
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-client</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
- <version>1.0</version>
<scope>provided</scope>
</dependency>
@@ -88,21 +85,17 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-jca</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-j2ee-connector_1.5_spec</artifactId>
- <version>2.0.0</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.1_spec</artifactId>
- <version>1.1.1</version>
<scope>runtime</scope>
</dependency>
@@ -110,125 +103,117 @@
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-core</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <version>${project.version}</version>
<type>test-jar</type>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-access-control</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-8-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-0-10-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-1-0-protocol</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-msg-conv-0-8-to-0-10</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-msg-conv-0-8-to-1-0</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-amqp-msg-conv-0-10-to-1-0</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-derby-store</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-jdbc-provider-bone</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-jdbc-store</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-management-http</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-management-jmx</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-broker-plugins-memory-store</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
- <!-- optional broker plugin modules
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-bdbstore</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
+ <scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-bdbstore-jmx</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>com.sleepycat</groupId>
+ <artifactId>je</artifactId>
+ <scope>test</scope>
<optional>true</optional>
- </dependency> -->
+ </dependency>
+
</dependencies>
<build>
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ConsumerLoggingTest.java
index 9f532ec5f7..db6da6f739 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ConsumerLoggingTest.java
@@ -46,7 +46,7 @@ import java.util.List;
* SUB-1002 : Close
* SUB-1003 : State : <state>
*/
-public class SubscriptionLoggingTest extends AbstractTestLogging
+public class ConsumerLoggingTest extends AbstractTestLogging
{
static final String SUB_PREFIX = "SUB-";
@@ -177,7 +177,8 @@ public class SubscriptionLoggingTest extends AbstractTestLogging
List<String> results = findMatches(SUB_PREFIX);
- assertEquals("Result set larger than expected.", 2, results.size());
+ final int expected = isBroker010() ? 5 : 2;
+ assertEquals("Result set larger than expected.", expected, results.size());
String log = getLogMessage(results, 0);
@@ -185,14 +186,10 @@ public class SubscriptionLoggingTest extends AbstractTestLogging
String message = getMessageString(fromMessage(log));
assertTrue("Browser not on log message:" + message, message.contains("Browser"));
- if(!isBroker010())
- {
- assertTrue("AutoClose not on log message:" + message, message.contains("AutoClose"));
- }
// Beacause it is an auto close and we have no messages on the queue we
// will get a close message
- log = getLogMessage(results, 1);
+ log = getLogMessage(results, expected-1);
validateMessageID("SUB-1002", log);
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java
index 17847fbdfc..2b21f4aeaa 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java
@@ -48,11 +48,10 @@ import org.apache.qpid.server.protocol.v0_8.MessageMetaData;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.plugin.ExchangeType;
-import org.apache.qpid.server.queue.AMQPriorityQueue;
+import org.apache.qpid.server.queue.PriorityQueue;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.ConflationQueue;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
+import org.apache.qpid.server.queue.StandardQueue;
import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.util.BrokerTestHelper;
@@ -574,9 +573,9 @@ public class MessageStoreTest extends QpidTestCase
if (usePriority)
{
- assertEquals("Queue is no longer a Priority Queue", AMQPriorityQueue.class, queue.getClass());
+ assertEquals("Queue is no longer a Priority Queue", PriorityQueue.class, queue.getClass());
assertEquals("Priority Queue does not have set priorities",
- DEFAULT_PRIORTY_LEVEL, ((AMQPriorityQueue) queue).getPriorities());
+ DEFAULT_PRIORTY_LEVEL, ((PriorityQueue) queue).getPriorities());
}
else if (lastValueQueue)
{
@@ -585,7 +584,7 @@ public class MessageStoreTest extends QpidTestCase
}
else
{
- assertEquals("Queue is not 'simple'", SimpleAMQQueue.class, queue.getClass());
+ assertEquals("Queue is not 'simple'", StandardQueue.class, queue.getClass());
}
assertEquals("Queue owner is not as expected", queueOwner, queue.getOwner());
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
index 2d6943f643..3c15a45203 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
@@ -26,11 +26,9 @@ import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.management.common.mbeans.ManagedBroker;
import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.NotificationCheckTest;
import org.apache.qpid.server.queue.QueueArgumentsConverter;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
-import org.apache.qpid.server.queue.SimpleAMQQueueTest;
+import org.apache.qpid.server.queue.StandardQueue;
import org.apache.qpid.test.client.destination.AddressBasedDestinationTest;
import org.apache.qpid.test.utils.JMXTestUtils;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
@@ -661,7 +659,7 @@ public class QueueManagementTest extends QpidBrokerTestCase
final Object messageGroupKey = "test";
final Map<String, Object> arguments = new HashMap<String, Object>(2);
arguments.put(QueueArgumentsConverter.QPID_GROUP_HEADER_KEY, messageGroupKey);
- arguments.put(QueueArgumentsConverter.QPID_SHARED_MSG_GROUP, SimpleAMQQueue.SHARED_MSG_GROUP_ARG_VALUE);
+ arguments.put(QueueArgumentsConverter.QPID_SHARED_MSG_GROUP, StandardQueue.SHARED_MSG_GROUP_ARG_VALUE);
managedBroker.createNewQueue(queueName, null, true, arguments);
final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
index cd9f6e721b..5dc1717751 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
@@ -98,7 +98,7 @@ public class Asserts
assertEquals("Unexpected value of queue attribute " + Queue.STATE, State.ACTIVE.name(), queueData.get(Queue.STATE));
assertEquals("Unexpected value of queue attribute " + Queue.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
queueData.get(Queue.LIFETIME_POLICY));
- assertEquals("Unexpected value of queue attribute " + Queue.TYPE, queueType, queueData.get(Queue.TYPE));
+ assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_TYPE, queueType, queueData.get(Queue.QUEUE_TYPE));
if (expectedAttributes == null)
{
assertEquals("Unexpected value of queue attribute " + Queue.EXCLUSIVE, Boolean.FALSE, queueData.get(Queue.EXCLUSIVE));
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java
index 05c8e362a1..d558e07ed7 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java
@@ -67,16 +67,15 @@ public class ConnectionRestTest extends QpidRestTestCase
producer.send(_session.createTextMessage("Test-" + i));
}
_session.commit();
-
Message m = consumer.receive(1000l);
- assertNotNull("Message was not received", m);
+ assertNotNull("First message was not received", m);
_session.commit();
// receive the rest of messages for rollback
for (int i = 0; i < MESSAGE_NUMBER - 1; i++)
{
m = consumer.receive(1000l);
- assertNotNull("Message was not received", m);
+ assertNotNull("Subsequent messages were not received", m);
}
_session.rollback();
@@ -84,7 +83,7 @@ public class ConnectionRestTest extends QpidRestTestCase
for (int i = 0; i < MESSAGE_NUMBER - 1; i++)
{
m = consumer.receive(1000l);
- assertNotNull("Message was not received", m);
+ assertNotNull("Message was not received after rollback", m);
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java
index d53b9f8fd6..4a8b321997 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java
@@ -677,7 +677,7 @@ public class VirtualHostRestTest extends QpidRestTestCase
queueData.put(Queue.DURABLE, Boolean.TRUE);
if (queueType != null)
{
- queueData.put(Queue.TYPE, queueType);
+ queueData.put(Queue.QUEUE_TYPE, queueType);
}
if (attributes != null)
{
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java
index 54c3225cec..b6f81da690 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java
@@ -32,6 +32,7 @@ import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -169,7 +170,8 @@ public class RollbackOrderTest extends QpidBrokerTestCase
//Start the session now so we
_connection.start();
- count.await();
+ count.await(10l, TimeUnit.SECONDS);
+ assertEquals("Not all message received. Count should be 0.", 0, count.getCount());
for (Exception e : exceptions)
{
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java
index 40db17f799..6356b17e6f 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java
@@ -26,6 +26,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.client.RejectBehaviour;
import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
@@ -86,7 +87,7 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
// dead-lettered or requeued.
if (!isBroker010())
{
- setTestClientSystemProperty(ClientProperties.REJECT_BEHAVIOUR_PROP_NAME, "server");
+ setTestClientSystemProperty(ClientProperties.REJECT_BEHAVIOUR_PROP_NAME, RejectBehaviour.SERVER.toString());
}
super.setUp();
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java
index 610628a02d..14914664d6 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.test.unit.transacted;
+import org.apache.qpid.client.RejectBehaviour;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -638,4 +639,44 @@ public class CommitRollbackTest extends QpidBrokerTestCase
}
}
}
+
+
+ public void testResendUnseenMessagesAfterRollback() throws Exception
+ {
+ resendAfterRollback();
+ }
+
+ public void testResendUnseenMessagesAfterRollbackWithServerReject() throws Exception
+ {
+ setTestSystemProperty(ClientProperties.REJECT_BEHAVIOUR_PROP_NAME, RejectBehaviour.SERVER.toString());
+ resendAfterRollback();
+ }
+
+ private void resendAfterRollback() throws Exception
+ {
+ newConnection();
+
+ assertTrue("session is not transacted", _session.getTransacted());
+ assertTrue("session is not transacted", _pubSession.getTransacted());
+
+ _logger.info("sending test message");
+ String MESSAGE_TEXT = "message text";
+
+ _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT));
+ _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT));
+
+ _pubSession.commit();
+
+ assertNotNull("two messages were sent, but none has been received", _consumer.receive(1000));
+
+ _session.rollback();
+
+ _logger.info("receiving result");
+
+ assertNotNull("two messages were sent, but none has been received", _consumer.receive(1000));
+ assertNotNull("two messages were sent, but only one has been received", _consumer.receive(1000));
+ assertNull("Only two messages were sent, but more have been received", _consumer.receive(100));
+
+ _session.commit();
+ }
}
diff --git a/qpid/java/test-profiles/Java010Excludes b/qpid/java/test-profiles/Java010Excludes
index 8da2b5edd8..67c2fcd5ad 100755
--- a/qpid/java/test-profiles/Java010Excludes
+++ b/qpid/java/test-profiles/Java010Excludes
@@ -33,7 +33,7 @@ org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testUnsubscribeWhenUsing
// 0-10 and 0-9 connections dont generate the exact same logging due to protocol differences
org.apache.qpid.server.logging.ChannelLoggingTest#testChannelStartsFlowStopped
org.apache.qpid.server.logging.ChannelLoggingTest#testChannelStartConsumerFlowStarted
-org.apache.qpid.server.logging.SubscriptionLoggingTest#testSubscriptionSuspend
+org.apache.qpid.server.logging.ConsumerLoggingTest#testSubscriptionSuspend
org.apache.qpid.server.logging.ChannelLoggingTest#testChannelClosedOnQueueArgumentsMismatch
// 0-10 is not supported by the MethodRegistry
diff --git a/qpid/java/test-profiles/python_tests/Java010PythonExcludes b/qpid/java/test-profiles/python_tests/Java010PythonExcludes
index de870e5e27..474480bdd0 100644
--- a/qpid/java/test-profiles/python_tests/Java010PythonExcludes
+++ b/qpid/java/test-profiles/python_tests/Java010PythonExcludes
@@ -50,6 +50,9 @@ qpid_tests.broker_0_10.priority.PriorityTests.test_prioritised_delivery_with_ali
#The broker does not support the autodelete property on exchanges
qpid_tests.broker_0_10.exchange.AutodeleteTests.testAutodelete*
+# QPID-5531 : Changes to the C++ behaviour in having a default timeout for every transaction not implemented in Java Broker
+qpid_tests.broker_0_10.dtx.DtxTests.test_get_timeout
+
###### Behavioural differences between Java & CPP Broker ######
#Tests changed/added in QPID-5280 and QPID-5283
diff --git a/qpid/java/tools/pom.xml b/qpid/java/tools/pom.xml
index 0afaa1d274..9da9ca0443 100644
--- a/qpid/java/tools/pom.xml
+++ b/qpid/java/tools/pom.xml
@@ -16,42 +16,39 @@
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid-project</artifactId>
- <version>0.26-SNAPSHOT</version>
+ <artifactId>qpid-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
</parent>
- <modelVersion>4.0.0</modelVersion>
<artifactId>qpid-tools</artifactId>
+ <version>0.28-SNAPSHOT</version>
+ <name>Qpid Tools</name>
+ <description>Tools</description>
<dependencies>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-client</artifactId>
- <version>0.26-SNAPSHOT</version>
- <scope>compile</scope>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
- <version>${log4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>${slf4j-version}</version>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
- <version>1.0</version>
- <scope>compile</scope>
</dependency>
</dependencies>
diff --git a/qpid/tests/src/py/qpid_tests/broker_0_10/dtx.py b/qpid/tests/src/py/qpid_tests/broker_0_10/dtx.py
index f8d6533a78..a9619bcdb8 100644
--- a/qpid/tests/src/py/qpid_tests/broker_0_10/dtx.py
+++ b/qpid/tests/src/py/qpid_tests/broker_0_10/dtx.py
@@ -594,9 +594,10 @@ class DtxTests(TestBase010):
session.dtx_select()
session.dtx_start(xid=tx)
- self.assertEqual(0, session.dtx_get_timeout(xid=tx).timeout)
- session.dtx_set_timeout(xid=tx, timeout=60)
+ # below test checks for default value of dtx-default-timeout broker option
self.assertEqual(60, session.dtx_get_timeout(xid=tx).timeout)
+ session.dtx_set_timeout(xid=tx, timeout=200)
+ self.assertEqual(200, session.dtx_get_timeout(xid=tx).timeout)
self.assertEqual(self.XA_OK, session.dtx_end(xid=tx).status)
self.assertEqual(self.XA_OK, session.dtx_rollback(xid=tx).status)
@@ -628,6 +629,21 @@ class DtxTests(TestBase010):
self.assertEqual(self.XA_RBTIMEOUT, session.dtx_end(xid=tx).status)
self.assertEqual(self.XA_RBTIMEOUT, session.dtx_rollback(xid=tx).status)
+ def test_set_timeout_too_high(self):
+ """
+ Test the timeout can't be more than --dtx-max-timeout
+ broker option
+ """
+ session = self.session
+ tx = self.xid("dummy")
+
+ session.dtx_select()
+ session.dtx_start(xid=tx)
+ try:
+ session.dtx_set_timeout(xid=tx, timeout=3601)
+ except SessionException, e:
+ self.assertEquals(542, e.args[0].error_code)
+
def test_recover(self):
diff --git a/qpid/tools/src/py/qls/efp.py b/qpid/tools/src/py/qls/efp.py
index 3ad8104faa..abf289dc12 100644
--- a/qpid/tools/src/py/qls/efp.py
+++ b/qpid/tools/src/py/qls/efp.py
@@ -26,10 +26,11 @@ class EfpManager(object):
Top level class to analyze the Qpid Linear Store (QLS) directory for the partitions that make up the
Empty File Pool (EFP).
"""
- def __init__(self, directory):
+ def __init__(self, directory, args):
if not os.path.exists(directory):
raise qls.err.InvalidQlsDirectoryNameError(directory)
self.directory = directory
+ self.args = args
self.partitions = []
def report(self):
print 'Found', len(self.partitions), 'partition(s).'
diff --git a/qpid/tools/src/py/qls/err.py b/qpid/tools/src/py/qls/err.py
index d56d739915..702fbb9520 100644
--- a/qpid/tools/src/py/qls/err.py
+++ b/qpid/tools/src/py/qls/err.py
@@ -30,6 +30,16 @@ class QlsRecordError(QlsError):
QlsError.__init__(self)
self.file_header = file_header
self.record = record
+ def get_expected_fro(self):
+ return self.file_header.first_record_offset
+ def get_file_number(self):
+ return self.file_header.file_num
+ def get_queue_name(self):
+ return self.file_header.queue_name
+ def get_record_id(self):
+ return self.record.record_id
+ def get_record_offset(self):
+ return self.record.file_offset
def __str__(self):
return 'queue="%s" file_id=0x%x record_offset=0x%x record_id=0x%x' % \
(self.file_header.queue_name, self.file_header.file_num, self.record.file_offset, self.record.record_id)
diff --git a/qpid/tools/src/py/qls/jrnl.py b/qpid/tools/src/py/qls/jrnl.py
index ffd200ddba..5bce78bfad 100644
--- a/qpid/tools/src/py/qls/jrnl.py
+++ b/qpid/tools/src/py/qls/jrnl.py
@@ -23,6 +23,7 @@ import qls.err
import string
import struct
from time import gmtime, strftime
+import zlib
class HighCounter(object):
def __init__(self):
@@ -39,10 +40,11 @@ class HighCounter(object):
class JournalRecoveryManager(object):
TPL_DIR_NAME = 'tpl'
JRNL_DIR_NAME = 'jrnl'
- def __init__(self, directory):
+ def __init__(self, directory, args):
if not os.path.exists(directory):
raise qls.err.InvalidQlsDirectoryNameError(directory)
self.directory = directory
+ self.args = args
self.tpl = None
self.journals = {}
self.high_rid_counter = HighCounter()
@@ -54,20 +56,21 @@ class JournalRecoveryManager(object):
def run(self, args):
tpl_dir = os.path.join(self.directory, JournalRecoveryManager.TPL_DIR_NAME)
if os.path.exists(tpl_dir):
- self.tpl = Journal(tpl_dir, None)
+ self.tpl = Journal(tpl_dir, None, self.args)
self.tpl.recover(self.high_rid_counter)
print
jrnl_dir = os.path.join(self.directory, JournalRecoveryManager.JRNL_DIR_NAME)
- prepared_list = self.tpl.txn_map.get_prepared_list()
+ prepared_list = self.tpl.txn_map.get_prepared_list() if self.tpl is not None else {}
if os.path.exists(jrnl_dir):
for dir_entry in sorted(os.listdir(jrnl_dir)):
- jrnl = Journal(os.path.join(jrnl_dir, dir_entry), prepared_list)
+ jrnl = Journal(os.path.join(jrnl_dir, dir_entry), prepared_list, self.args)
jrnl.recover(self.high_rid_counter)
self.journals[jrnl.get_queue_name()] = jrnl
print
self._reconcile_transactions(prepared_list, args.txn)
def _reconcile_transactions(self, prepared_list, txn_flag):
print 'Transaction reconciliation report:'
+ print '=================================='
print len(prepared_list), 'open transaction(s) found in prepared transaction list:'
for xid in prepared_list.keys():
commit_flag = prepared_list[xid]
@@ -79,7 +82,7 @@ class JournalRecoveryManager(object):
status = '[Prepared, but interrupted during abort phase]'
print ' ', Utils.format_xid(xid), status
if prepared_list[xid] is None: # Prepared, but not committed or aborted
- enqueue_record = self.tpl.get_txn_map_record(xid)
+ enqueue_record = self.tpl.get_txn_map_record(xid)[0][1]
dequeue_record = Utils.create_record('QLSd', DequeueRecord.TXN_COMPLETE_COMMIT_FLAG, \
self.tpl.current_journal_file, self.high_rid_counter.get_next(), \
enqueue_record.record_id, xid, None)
@@ -141,7 +144,7 @@ class EnqueueMap(object):
lock_str = '[LOCKED]'
else:
lock_str = ''
- rstr += '\n %d:%s %s' % (journal_file.file_header.file_num, record, lock_str)
+ rstr += '\n 0x%x:%s %s' % (journal_file.file_header.file_num, record, lock_str)
else:
rstr += '.'
return rstr
@@ -245,7 +248,7 @@ class TransactionMap(object):
for xid, op_list in self.txn_map.iteritems():
rstr += '\n %s containing %d operations:' % (Utils.format_xid(xid), len(op_list))
for journal_file, record, _ in op_list:
- rstr += '\n %d:%s' % (journal_file.file_header.file_num, record)
+ rstr += '\n 0x%x:%s' % (journal_file.file_header.file_num, record)
else:
rstr += '.'
return rstr
@@ -303,7 +306,7 @@ class Journal(object):
"""
Instance of a Qpid Linear Store (QLS) journal.
"""
- def __init__(self, directory, xid_prepared_list):
+ def __init__(self, directory, xid_prepared_list, args):
self.directory = directory
self.queue_name = os.path.basename(directory)
self.files = {}
@@ -315,6 +318,10 @@ class Journal(object):
self.first_rec_flag = None
self.statistics = JournalStatistics()
self.xid_prepared_list = xid_prepared_list # This is None for the TPL instance only
+ self.args = args
+ self.last_record_offset = None # TODO: Move into JournalFile
+ self.num_filler_records_required = None # TODO: Move into JournalFile
+ self.fill_to_offset = None
def add_record(self, record):
if isinstance(record, EnqueueRecord) or isinstance(record, DequeueRecord):
if record.xid_size > 0:
@@ -334,15 +341,18 @@ class Journal(object):
def get_queue_name(self):
return self.queue_name
def recover(self, high_rid_counter):
- print 'Recovering', self.queue_name #DEBUG
+ print 'Recovering %s' % self.queue_name
self._analyze_files()
try:
while self._get_next_record(high_rid_counter):
pass
+ self._check_alignment()
except qls.err.NoMoreFilesInJournalError:
- #print '[No more files in journal]' # DEBUG
- #print #DEBUG
- pass
+ print 'No more files in journal'
+ except qls.err.FirstRecordOffsetMismatchError as err:
+ print '0x%08x: **** FRO ERROR: queue=\"%s\" fid=0x%x fro actual=0x%08x expected=0x%08x' % \
+ (err.get_expected_fro(), err.get_queue_name(), err.get_file_number(), err.get_record_offset(),
+ err.get_expected_fro())
def reconcile_transactions(self, prepared_list, txn_flag):
xid_list = self.txn_map.get_xid_list()
if len(xid_list) > 0:
@@ -363,11 +373,12 @@ class Journal(object):
if txn_flag:
self.txn_map.abort(xid)
else:
- print ' ', Utils.format_xid(xid), '- Aborting, not in prepared transaction list'
+ print ' ', Utils.format_xid(xid), '- Ignoring, not in prepared transaction list'
if txn_flag:
self.txn_map.abort(xid)
def report(self, print_stats_flag):
print 'Journal "%s":' % self.queue_name
+ print '=' * (11 + len(self.queue_name))
if print_stats_flag:
print str(self.statistics)
print self.enq_map.report_str(True, True)
@@ -375,6 +386,11 @@ class Journal(object):
JournalFile.report_header()
for file_num in sorted(self.files.keys()):
self.files[file_num].report()
+ #TODO: move this to JournalFile, append to file info
+ if self.num_filler_records_required is not None and self.fill_to_offset is not None:
+ print '0x%x:0x%08x: %d filler records required for DBLK alignment to 0x%08x' % \
+ (self.current_journal_file.file_header.file_num, self.last_record_offset,
+ self.num_filler_records_required, self.fill_to_offset)
print
#--- protected functions ---
def _analyze_files(self):
@@ -386,21 +402,35 @@ class Journal(object):
args = Utils.load_args(file_handle, RecordHeader)
file_hdr = FileHeader(*args)
file_hdr.init(file_handle, *Utils.load_args(file_handle, FileHeader))
- if not file_hdr.is_header_valid(file_hdr):
- break
- file_hdr.load(file_handle)
- if not file_hdr.is_valid():
- break
- Utils.skip(file_handle, file_hdr.file_header_size_sblks * Utils.SBLK_SIZE)
- self.files[file_hdr.file_num] = JournalFile(file_hdr)
+ if file_hdr.is_header_valid(file_hdr):
+ file_hdr.load(file_handle)
+ if file_hdr.is_valid():
+ Utils.skip(file_handle, file_hdr.file_header_size_sblks * Utils.SBLK_SIZE)
+ self.files[file_hdr.file_num] = JournalFile(file_hdr)
self.file_num_list = sorted(self.files.keys())
self.file_num_itr = iter(self.file_num_list)
+ def _check_alignment(self): # TODO: Move into JournalFile
+ remaining_sblks = self.last_record_offset % Utils.SBLK_SIZE
+ if remaining_sblks == 0:
+ self.num_filler_records_required = 0
+ else:
+ self.num_filler_records_required = (Utils.SBLK_SIZE - remaining_sblks) / Utils.DBLK_SIZE
+ self.fill_to_offset = self.last_record_offset + (self.num_filler_records_required * Utils.DBLK_SIZE)
+ if self.args.show_recs or self.args.show_all_recs:
+ print '0x%x:0x%08x: %d filler records required for DBLK alignment to 0x%08x' % \
+ (self.current_journal_file.file_header.file_num, self.last_record_offset,
+ self.num_filler_records_required, self.fill_to_offset)
def _check_file(self):
- if self.current_journal_file is not None and not self.current_journal_file.file_header.is_end_of_file():
- return
- self._get_next_file()
+ if self.current_journal_file is not None:
+ if not self.current_journal_file.file_header.is_end_of_file():
+ return True
+ if self.current_journal_file.file_header.is_end_of_file():
+ self.last_record_offset = self.current_journal_file.file_header.file_handle.tell()
+ if not self._get_next_file():
+ return False
fhdr = self.current_journal_file.file_header
fhdr.file_handle.seek(fhdr.first_record_offset)
+ return True
def _get_next_file(self):
if self.current_journal_file is not None:
file_handle = self.current_journal_file.file_header.file_handle
@@ -413,13 +443,16 @@ class Journal(object):
except StopIteration:
pass
if file_num == 0:
- raise qls.err.NoMoreFilesInJournalError(self.queue_name)
+ return False
self.current_journal_file = self.files[file_num]
self.first_rec_flag = True
- print self.current_journal_file.file_header
- #print '[file_num=0x%x]' % self.current_journal_file.file_num #DEBUG
+ if self.args.show_recs or self.args.show_all_recs:
+ print '0x%x:%s' % (self.current_journal_file.file_header.file_num, self.current_journal_file.file_header)
+ return True
def _get_next_record(self, high_rid_counter):
- self._check_file()
+ if not self._check_file():
+ return False
+ self.last_record_offset = self.current_journal_file.file_header.file_handle.tell()
this_record = Utils.load(self.current_journal_file.file_header.file_handle, RecordHeader)
if not this_record.is_header_valid(self.current_journal_file.file_header):
return False
@@ -427,32 +460,42 @@ class Journal(object):
if this_record.file_offset != self.current_journal_file.file_header.first_record_offset:
raise qls.err.FirstRecordOffsetMismatchError(self.current_journal_file.file_header, this_record)
self.first_rec_flag = False
- high_rid_counter.check(this_record.record_id)
self.statistics.total_record_count += 1
+ start_journal_file = self.current_journal_file
if isinstance(this_record, EnqueueRecord):
- self._handle_enqueue_record(this_record)
- print this_record
+ ok_flag = self._handle_enqueue_record(this_record, start_journal_file)
+ high_rid_counter.check(this_record.record_id)
+ if self.args.show_recs or self.args.show_all_recs:
+ print '0x%x:%s' % (start_journal_file.file_header.file_num, this_record)
elif isinstance(this_record, DequeueRecord):
- self._handle_dequeue_record(this_record)
- print this_record
+ ok_flag = self._handle_dequeue_record(this_record, start_journal_file)
+ high_rid_counter.check(this_record.record_id)
+ if self.args.show_recs or self.args.show_all_recs:
+ print '0x%x:%s' % (start_journal_file.file_header.file_num, this_record)
elif isinstance(this_record, TransactionRecord):
- self._handle_transaction_record(this_record)
- print this_record
+ ok_flag = self._handle_transaction_record(this_record, start_journal_file)
+ high_rid_counter.check(this_record.record_id)
+ if self.args.show_recs or self.args.show_all_recs:
+ print '0x%x:%s' % (start_journal_file.file_header.file_num, this_record)
else:
self.statistics.filler_record_count += 1
+ ok_flag = True
+ if self.args.show_all_recs:
+ print '0x%x:%s' % (start_journal_file.file_header.file_num, this_record)
Utils.skip(self.current_journal_file.file_header.file_handle, Utils.DBLK_SIZE)
- return True
- def _handle_enqueue_record(self, enqueue_record):
- start_journal_file = self.current_journal_file
+ return ok_flag
+ def _handle_enqueue_record(self, enqueue_record, start_journal_file):
while enqueue_record.load(self.current_journal_file.file_header.file_handle):
- self._get_next_file()
- if not enqueue_record.is_valid(self.current_journal_file):
- return
+ if not self._get_next_file():
+ enqueue_record.truncated_flag = True
+ return False
+ if not enqueue_record.is_valid(start_journal_file):
+ return False
if enqueue_record.is_external() and enqueue_record.data != None:
raise qls.err.ExternalDataError(self.current_journal_file.file_header, enqueue_record)
if enqueue_record.is_transient():
self.statistics.transient_record_count += 1
- return
+ return True
if enqueue_record.xid_size > 0:
self.txn_map.add(start_journal_file, enqueue_record)
self.statistics.transaction_operation_count += 1
@@ -462,13 +505,14 @@ class Journal(object):
self.enq_map.add(start_journal_file, enqueue_record, False)
start_journal_file.incr_enq_cnt()
self.statistics.enqueue_count += 1
- #print enqueue_record, # DEBUG
- def _handle_dequeue_record(self, dequeue_record):
- start_journal_file = self.current_journal_file
+ return True
+ def _handle_dequeue_record(self, dequeue_record, start_journal_file):
while dequeue_record.load(self.current_journal_file.file_header.file_handle):
- self._get_next_file()
- if not dequeue_record.is_valid(self.current_journal_file):
- return
+ if not self._get_next_file():
+ dequeue_record.truncated_flag = True
+ return False
+ if not dequeue_record.is_valid(start_journal_file):
+ return False
if dequeue_record.xid_size > 0:
if self.xid_prepared_list is None: # ie this is the TPL
dequeue_record.transaction_prepared_list_flag = True
@@ -484,12 +528,14 @@ class Journal(object):
except qls.err.RecordIdNotFoundError:
dequeue_record.warnings.append('NOT IN EMAP')
self.statistics.dequeue_count += 1
- #print dequeue_record, # DEBUG
- def _handle_transaction_record(self, transaction_record):
+ return True
+ def _handle_transaction_record(self, transaction_record, start_journal_file):
while transaction_record.load(self.current_journal_file.file_header.file_handle):
- self._get_next_file()
- if not transaction_record.is_valid(self.current_journal_file):
- return
+ if not self._get_next_file():
+ transaction_record.truncated_flag = True
+ return False
+ if not transaction_record.is_valid(start_journal_file):
+ return False
if transaction_record.magic[-1] == 'a':
self.statistics.transaction_abort_count += 1
else:
@@ -501,7 +547,7 @@ class Journal(object):
# if transaction_record.magic[-1] == 'c': # commits only
# self._txn_obj_list[hdr.xid] = hdr
self.statistics.transaction_record_count += 1
- #print transaction_record, # DEBUG
+ return True
def _load_data(self, record):
while not record.is_complete:
record.load(self.current_journal_file.file_handle)
@@ -511,6 +557,7 @@ class JournalFile(object):
self.file_header = file_header
self.enq_cnt = 0
self.deq_cnt = 0
+ self.num_filler_records_required = None
def incr_enq_cnt(self):
self.enq_cnt += 1
def decr_enq_cnt(self, record):
@@ -527,7 +574,8 @@ class JournalFile(object):
print '-------- ------- ---- ----- ------------'
def report(self):
comment = '<uninitialized>' if self.file_header.file_num == 0 else ''
- print '%8d %7d %4d %4dk %s %s' % (self.file_header.file_num, self.get_enq_cnt(), self.file_header.partition_num,
+ file_num_str = '0x%x' % self.file_header.file_num
+ print '%8s %7d %4d %4dk %s %s' % (file_num_str, self.get_enq_cnt(), self.file_header.partition_num,
self.file_header.efp_data_size_kb,
os.path.basename(self.file_header.file_handle.name), comment)
@@ -541,6 +589,9 @@ class RecordHeader(object):
self.serial = serial
self.record_id = record_id
self.warnings = []
+ self.truncated_flag = False
+ def checksum_encode(self):
+ return struct.pack(RecordHeader.FORMAT, self.magic, self.version, self.user_flags, self.serial, self.record_id)
def load(self, file_handle):
pass
@staticmethod
@@ -560,8 +611,6 @@ class RecordHeader(object):
if self.version != Utils.RECORD_VERSION:
raise qls.err.InvalidRecordVersionError(file_header, self, Utils.RECORD_VERSION)
if self.serial != file_header.serial:
- #print '[serial mismatch at 0x%x]' % self.file_offset #DEBUG
- #print #DEBUG
return False
return True
def _get_warnings(self):
@@ -606,8 +655,8 @@ class RecordTail(object):
return False
self.valid_flag = Utils.inv_str(self.xmagic) == record.magic and \
self.serial == record.serial and \
- self.record_id == record.record_id
- # TODO: When we can verify the checksum, add this here
+ self.record_id == record.record_id and \
+ Utils.adler32(record.checksum_encode()) == self.checksum
return self.valid_flag
def __str__(self):
"""Return a string representation of the this RecordTail instance"""
@@ -660,7 +709,7 @@ class FileHeader(RecordHeader):
return strftime(fstr, time)
def __str__(self):
"""Return a string representation of the this FileHeader instance"""
- return '%s fnum=%d fro=0x%08x p=%d s=%dk t=%s %s' % (RecordHeader.__str__(self), self.file_num,
+ return '%s fnum=0x%x fro=0x%08x p=%d s=%dk t=%s %s' % (RecordHeader.__str__(self), self.file_num,
self.first_record_offset, self.partition_num,
self.efp_data_size_kb, self.timestamp_str(),
self._get_warnings())
@@ -677,6 +726,9 @@ class EnqueueRecord(RecordHeader):
self.data = None
self.data_complete = False
self.record_tail = None
+ def checksum_encode(self):
+ return RecordHeader.checksum_encode(self) + struct.pack(self.FORMAT, self.xid_size, self.data_size) + \
+ self.xid + self.data
def is_external(self):
return self.user_flags & EnqueueRecord.EXTERNAL_FLAG_MASK > 0
def is_transient(self):
@@ -732,6 +784,9 @@ class EnqueueRecord(RecordHeader):
return fstr
def __str__(self):
"""Return a string representation of the this EnqueueRecord instance"""
+ if self.truncated_flag:
+ return '%s xid(%d) data(%d) [Truncated, no more files in journal]' % (RecordHeader.__str__(self),
+ self.xid_size, self.data_size)
if self.record_tail is None:
record_tail_str = ''
else:
@@ -750,6 +805,9 @@ class DequeueRecord(RecordHeader):
self.xid = None
self.xid_complete = False
self.record_tail = None
+ def checksum_encode(self):
+ return RecordHeader.checksum_encode(self) + struct.pack(self.FORMAT, self.dequeue_record_id, self.xid_size) + \
+ self.xid
def is_transaction_complete_commit(self):
return self.user_flags & DequeueRecord.TXN_COMPLETE_COMMIT_FLAG > 0
def is_valid(self, journal_file):
@@ -790,6 +848,10 @@ class DequeueRecord(RecordHeader):
return ''
def __str__(self):
"""Return a string representation of the this DequeueRecord instance"""
+ if self.truncated_flag:
+ return '%s xid(%d) drid=0x%x [Truncated, no more files in journal]' % (RecordHeader.__str__(self),
+ self.xid_size,
+ self.dequeue_record_id)
if self.record_tail is None:
record_tail_str = ''
else:
@@ -805,6 +867,8 @@ class TransactionRecord(RecordHeader):
self.xid = None
self.xid_complete = False
self.record_tail = None
+ def checksum_encode(self):
+ return RecordHeader.checksum_encode(self) + struct.pack(self.FORMAT, self.xid_size) + self.xid
def is_valid(self, journal_file):
if not RecordHeader.is_header_valid(self, journal_file.file_header):
return False
@@ -832,6 +896,8 @@ class TransactionRecord(RecordHeader):
return False
def __str__(self):
"""Return a string representation of the this TransactionRecord instance"""
+ if self.truncated_flag:
+ return '%s xid(%d) [Truncated, no more files in journal]' % (RecordHeader.__str__(self), self.xid_size)
if self.record_tail is None:
record_tail_str = ''
else:
@@ -845,6 +911,9 @@ class Utils(object):
RECORD_VERSION = 2
SBLK_SIZE = 4096
@staticmethod
+ def adler32(data):
+ return zlib.adler32(data) & 0xffffffff
+ @staticmethod
def create_record(magic, uflags, journal_file, record_id, dequeue_record_id, xid, data):
record_class = _CLASSES.get(magic[-1])
record = record_class(0, magic, Utils.RECORD_VERSION, uflags, journal_file.file_header.serial, record_id)
@@ -866,7 +935,7 @@ class Utils(object):
record.data_complete = True
record.record_tail = RecordTail(None)
record.record_tail.xmagic = Utils.inv_str(magic)
- record.record_tail.checksum = 0 # TODO: when we can calculate checksums, add this here
+ record.record_tail.checksum = Utils.adler32(record.checksum_encode())
record.record_tail.serial = record.serial
record.record_tail.record_id = record.record_id
return record
@@ -878,7 +947,7 @@ class Utils(object):
# << DEBUG >>
begin = data.find('msg')
end = data.find('\0', begin)
- return 'data="%s"' % data[begin:end]
+ return 'data(%d)="%s"' % (dsize, data[begin:end])
# << END DEBUG
if Utils._is_printable(data):
datastr = Utils._split_str(data)
@@ -941,7 +1010,8 @@ class Utils(object):
@staticmethod
def skip(file_handle, boundary):
"""Read and discard disk bytes until the next multiple of boundary"""
- file_handle.read(Utils._rem_bytes_in_block(file_handle, boundary))
+ if not file_handle.closed:
+ file_handle.read(Utils._rem_bytes_in_block(file_handle, boundary))
#--- protected functions ---
@staticmethod
def _hex_str(in_str, begin, end):
diff --git a/qpid/tools/src/py/qpid-ha b/qpid/tools/src/py/qpid-ha
index cf054409d8..daa73d3312 100755
--- a/qpid/tools/src/py/qpid-ha
+++ b/qpid/tools/src/py/qpid-ha
@@ -133,12 +133,10 @@ class SetCmd(Command):
Command.__init__(self, "set", "Set HA configuration settings")
self.add("--brokers-url", "<url>", "string", "URL with address of each broker in the cluster. Used by brokers to connect to each other.")
self.add("--public-url", "<url>", "string", "URL advertised to clients to connect to the cluster. May be a list or a VIP.")
- self.add("--backups", "<n>", "int", "Expect <n> backups to be running"),
def do_execute(self, qmf_broker, ha_broker, opts, args):
if (opts.brokers_url): qmf_broker._method("setBrokersUrl", {"url":opts.brokers_url}, HA_BROKER)
if (opts.public_url): qmf_broker._method("setPublicUrl", {"url":opts.public_url}, HA_BROKER)
- if (opts.backups): qmf_broker._method("setExpectedBackups", {"expectedBackups":opts.backups}, HA_BROKER)
SetCmd()
@@ -151,7 +149,6 @@ class QueryCmd(Command):
for x in [("Status:", hb.status),
("Brokers URL:", hb.brokersUrl),
("Public URL:", hb.publicUrl),
- ("Expected Backups:", hb.expectedBackups),
("Replicate: ", hb.replicateDefault)
]:
print "%-20s %s"%(x[0], x[1])
diff --git a/qpid/tools/src/py/qpid_qls_analyze.py b/qpid/tools/src/py/qpid_qls_analyze.py
index 165d41fe95..a540587547 100755
--- a/qpid/tools/src/py/qpid_qls_analyze.py
+++ b/qpid/tools/src/py/qpid_qls_analyze.py
@@ -37,8 +37,8 @@ class QqpdLinearStoreAnalyzer(object):
self.args = None
self._process_args()
self.qls_dir = os.path.abspath(self.args.qls_dir)
- self.efp_manager = efp.EfpManager(self.qls_dir)
- self.jrnl_recovery_mgr = jrnl.JournalRecoveryManager(self.qls_dir)
+ self.efp_manager = efp.EfpManager(self.qls_dir, self.args)
+ self.jrnl_recovery_mgr = jrnl.JournalRecoveryManager(self.qls_dir, self.args)
def _analyze_efp(self):
self.efp_manager.run(self.args)
def _analyze_journals(self):
@@ -49,6 +49,10 @@ class QqpdLinearStoreAnalyzer(object):
help='Qpid Linear Store (QLS) directory to be analyzed')
parser.add_argument('--efp', action='store_true',
help='Analyze the Emtpy File Pool (EFP) and show stats')
+ parser.add_argument('--show-recs', action='store_true',
+ help='Show material records found during recovery')
+ parser.add_argument('--show-all-recs', action='store_true',
+ help='Show all records (including fillers) found during recovery')
parser.add_argument('--stats', action='store_true',
help='Print journal record stats')
parser.add_argument('--txn', action='store_true',