summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2014-02-07 16:57:49 +0000
committerRobert Godfrey <rgodfrey@apache.org>2014-02-07 16:57:49 +0000
commit65b1a1ddfe95b9e273d4cdaf23067a0aaff9b1d1 (patch)
tree427d5ce851b9336fea70eb8fc6f87135ad239065
parent3ab4f9bdc9bbc8375534f45022a02257eb6e030d (diff)
downloadqpid-python-65b1a1ddfe95b9e273d4cdaf23067a0aaff9b1d1.tar.gz
QPID-5504 : Refactoring to allow for nodes other than queues to be subscribed from, and nodes other than exchanges to be sent to (merged from separate branch)
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1565726 13f79535-47bb-0310-9956-ffa450edef68
-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/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java36
-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.java39
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java6
-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/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.java44
-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/model/Session.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java7
-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.java54
-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.java15
-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/logging/actors/SubscriptionActor.java)27
-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.java104
-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)34
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java12
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java2
-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)65
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java (renamed from qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/MessageGroupManager.java)18
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java14
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java6
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java480
-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.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java191
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java99
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java2
-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.java510
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java6
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java7
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java8
-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.java12
-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.java75
-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/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.java17
-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/AMQPriorityQueueTest.java28
-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.java69
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java42
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java44
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java506
-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.java7
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java7
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java14
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java580
-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
-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.java95
-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-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java397
-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.java552
-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/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.java14
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java37
-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/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.java2
-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.java7
-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/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_to_1_0.java3
-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.java114
-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/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java7
-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/systest/rest/ConnectionRestTest.java7
-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
-rwxr-xr-xqpid/java/test-profiles/Java010Excludes2
132 files changed, 4890 insertions, 5163 deletions
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/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 0f4cdf1078..cecd39381e 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
@@ -416,10 +416,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();
@@ -454,10 +466,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();
@@ -511,10 +535,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/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..bc670bd848 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,17 @@ 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.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collection;
@@ -66,7 +70,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 +142,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 +155,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 +310,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);
}
@@ -421,7 +431,7 @@ public abstract class AbstractExchange implements Exchange
public final int send(final ServerMessage message,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final BaseQueue.PostEnqueueAction postEnqueueAction)
+ final Action<MessageInstance<? extends Consumer>> postEnqueueAction)
{
List<? extends BaseQueue> queues = route(message, instanceProperties);
@@ -579,8 +589,6 @@ public abstract class AbstractExchange implements Exchange
{
doRemoveBinding(b);
queue.removeBinding(b);
- removeCloseTask(b);
- queue.removeQueueDeleteTask(b);
if (b.isDurable())
{
@@ -659,8 +667,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 +679,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 +695,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 +729,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..33c5218b4c 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,22 @@ 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.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.VirtualHost;
public class DefaultExchange implements Exchange
@@ -334,7 +338,7 @@ public class DefaultExchange implements Exchange
public final int send(final ServerMessage message,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final BaseQueue.PostEnqueueAction postEnqueueAction)
+ final Action<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/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..967c629749
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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.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
+ */
+ int send(ServerMessage message,
+ InstanceProperties instanceProperties,
+ ServerTransaction txn,
+ Action<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..97cb66cce4 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<C extends Consumer>
{
+
+ /**
+ * Number of times this queue entry has been delivered.
+ *
+ * @return delivery count
+ */
+ int getDeliveryCount();
+
+ void incrementDeliveryCount();
+
+ void decrementDeliveryCount();
+
+ void addStateChangeListener(StateChangeListener<MessageInstance<C>, State> listener);
+
+ boolean removeStateChangeListener(StateChangeListener<MessageInstance<C>, 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<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..06ff76f103
--- /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> extends TransactionLogResource, MessageNode
+{
+ C addConsumer(ConsumerTarget target, FilterManager filters,
+ Class<? extends ServerMessage> messageClass,
+ String consumerName, EnumSet<Consumer.Option> options) throws AMQException;
+
+ Collection<C> getConsumers();
+
+ void addConsumerRegistrationListener(ConsumerRegistrationListener listener);
+
+ void removeConsumerRegistrationListener(ConsumerRegistrationListener listener);
+
+ AuthorizationHolder getAuthorizationHolder();
+
+ void setAuthorizationHolder(AuthorizationHolder principalHolder);
+
+ void setExclusiveOwningSession(AMQSessionModel owner);
+
+ AMQSessionModel getExclusiveOwningSession();
+
+ boolean isExclusive();
+
+ interface ConsumerRegistrationListener
+ {
+ void consumerAdded(AMQQueue queue, Consumer consumer);
+ void consumerRemoved(AMQQueue 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/model/Session.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java
index e813d0c129..355a1cf3b1 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
@@ -77,6 +77,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/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
index ae07005679..2b5176aa65 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
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.model;
+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;
@@ -144,11 +145,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..d59b13902b 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
@@ -35,7 +35,6 @@ import org.apache.qpid.server.binding.Binding;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
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,11 @@ 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 extends AbstractAdapter implements Queue,
+ AMQQueue.ConsumerRegistrationListener, AMQQueue.NotificationListener
{
@SuppressWarnings("serial")
static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{
@@ -69,8 +69,8 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
private final AMQQueue _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 Map<Consumer, ConsumerAdapter> _consumerAdapters =
+ new HashMap<Consumer, ConsumerAdapter>();
private final VirtualHostAdapter _vhost;
@@ -84,7 +84,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
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 +124,21 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs
private void populateConsumers()
{
- Collection<org.apache.qpid.server.subscription.Subscription> actualSubscriptions = _queue.getConsumers();
+ Collection<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)
+ Iterator<Consumer> iter = _consumerAdapters.keySet().iterator();
+ 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 +153,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());
}
}
@@ -502,7 +502,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 +587,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 +609,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 300b6e6618..f2ce20c74d 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
@@ -44,6 +44,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.configuration.XmlConfigurationUtilities.MyConfiguration;
+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;
@@ -759,11 +760,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()
{
@@ -777,7 +778,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();
@@ -788,7 +789,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
{
try
{
- toQueue.enqueue(message);
+ toQueue.enqueue(message, null);
}
catch(AMQException e)
{
@@ -803,7 +804,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();
@@ -817,7 +818,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
{
try
{
- toQueue.enqueue(message);
+ toQueue.enqueue(message, null);
}
catch (AMQException e)
{
@@ -830,7 +831,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/logging/actors/SubscriptionActor.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemNodeCreator.java
index 906cd6db3a..a117524254 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/plugin/SystemNodeCreator.java
@@ -18,29 +18,20 @@
* under the License.
*
*/
-package org.apache.qpid.server.logging.actors;
+package org.apache.qpid.server.plugin;
-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.MessageNode;
+import org.apache.qpid.server.virtualhost.VirtualHost;
-/**
- * The subscription actor provides formatted logging for actions that are
- * performed by the subscription. Such as STATE changes.
- */
-public class SubscriptionActor extends AbstractActor
+public interface SystemNodeCreator extends Pluggable
{
- private SubscriptionLogSubject _logSubject;
-
- public SubscriptionActor(RootMessageLogger logger, Subscription subscription)
+ interface SystemNodeRegistry
{
- super(logger);
+ void registerSystemNode(MessageNode node);
+ void removeSystemNode(MessageNode node);
- _logSubject = new SubscriptionLogSubject(subscription);
+ VirtualHost getVirtualHost();
}
- public String getLogMessage()
- {
- return _logSubject.toLogString();
- }
+ void register(SystemNodeRegistry registry);
}
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..62927edc29 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<C extends Consumer> extends Comparable<AMQQueue<C>>, ExchangeReferrer, BaseQueue,
+ MessageSource<C>, 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();
@@ -126,14 +102,14 @@ public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, Transa
void requeue(QueueEntry entry);
- void dequeue(QueueEntry entry, Subscription sub);
+ void dequeue(QueueEntry entry, Consumer sub);
void decrementUnackedMsgCount(QueueEntry queueEntry);
- boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException;
+ boolean resend(final QueueEntry entry, final Consumer consumer) throws AMQException;
- void addQueueDeleteTask(final Task task);
- void removeQueueDeleteTask(final Task task);
+ void addQueueDeleteTask(Action<AMQQueue> task);
+ void removeQueueDeleteTask(Action<AMQQueue> task);
@@ -209,16 +185,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 +196,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/subscription/AssignedSubscriptionMessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AssignedConsumerMessageGroupManager.java
index ae7e11afa4..a9b36c1b24 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 implements MessageGroupManager
{
- 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,13 +53,13 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
return val;
}
- public Subscription getAssignedSubscription(final QueueEntry entry)
+ public QueueConsumer getAssignedConsumer(final QueueEntry 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 sub, QueueEntry entry)
{
if(assignMessage(sub, entry))
{
@@ -73,7 +71,7 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
}
}
- private boolean assignMessage(Subscription sub, QueueEntry entry)
+ private boolean assignMessage(QueueConsumer sub, QueueEntry entry)
{
Object groupVal = entry.getMessage().getMessageHeader().getHeader(_groupId);
if(groupVal == null)
@@ -83,7 +81,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,7 +105,7 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
}
}
- public QueueEntry findEarliestAssignedAvailableEntry(Subscription sub)
+ public QueueEntry findEarliestAssignedAvailableEntry(QueueConsumer sub)
{
EntryFinder visitor = new EntryFinder(sub);
sub.getQueue().visit(visitor);
@@ -117,9 +115,9 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
private class EntryFinder implements QueueEntryVisitor
{
private QueueEntry _entry;
- private Subscription _sub;
+ private QueueConsumer _sub;
- public EntryFinder(final Subscription sub)
+ public EntryFinder(final QueueConsumer sub)
{
_sub = sub;
}
@@ -138,7 +136,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;
@@ -156,9 +154,9 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
}
}
- 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..c1c3bd37e6 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 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<MessageInstance<? extends Consumer>> action) throws AMQException;
boolean isDurable();
boolean isDeleted();
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..7469e95394 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
@@ -43,7 +43,7 @@ public class ConflationQueueList extends SimpleQueueEntryList
private final QueueEntry _deleteInProgress = new SimpleQueueEntryImpl(this);
private final QueueEntry _newerEntryAlreadyBeenAndGone = new SimpleQueueEntryImpl(this);
- public ConflationQueueList(AMQQueue queue, String conflationKey)
+ public ConflationQueueList(AMQQueue<QueueConsumer> queue, String conflationKey)
{
super(queue);
_conflationKey = 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..4c74e5ba0b 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,15 +18,16 @@
* 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;
@@ -38,23 +39,23 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
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 _resetHelper;
private final class Group
{
private final Object _group;
- private Subscription _subscription;
+ private QueueConsumer _consumer;
private int _activeCount;
- private Group(final Object key, final Subscription subscription)
+ private Group(final Object key, final QueueConsumer 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 getConsumer()
{
- return _subscription;
+ return _consumer;
}
@Override
@@ -113,28 +114,28 @@ 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 resetHelper)
{
_groupId = groupId;
_defaultGroup = defaultGroup;
_resetHelper = resetHelper;
}
- public synchronized Subscription getAssignedSubscription(final QueueEntry entry)
+ public synchronized QueueConsumer getAssignedConsumer(final QueueEntry 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 sub, final QueueEntry entry)
{
if(assignMessage(sub, entry))
{
@@ -146,7 +147,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
}
}
- private boolean assignMessage(final Subscription sub, final QueueEntry entry)
+ private boolean assignMessage(final QueueConsumer sub, final QueueEntry entry)
{
Object groupId = getKey(entry);
Group group = _groupMap.get(groupId);
@@ -158,15 +159,15 @@ 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)
{
@@ -179,7 +180,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
}
}
- public synchronized QueueEntry findEarliestAssignedAvailableEntry(final Subscription sub)
+ public synchronized QueueEntry findEarliestAssignedAvailableEntry(final QueueConsumer sub)
{
EntryFinder visitor = new EntryFinder(sub);
sub.getQueue().visit(visitor);
@@ -189,9 +190,9 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
private class EntryFinder implements QueueEntryVisitor
{
private QueueEntry _entry;
- private Subscription _sub;
+ private QueueConsumer _sub;
- public EntryFinder(final Subscription sub)
+ public EntryFinder(final QueueConsumer sub)
{
_sub = sub;
}
@@ -206,7 +207,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;
@@ -224,7 +225,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
}
- public void clearAssignments(final Subscription sub)
+ public void clearAssignments(final QueueConsumer sub)
{
}
@@ -240,19 +241,19 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
return groupVal;
}
- private class GroupStateChangeListener implements QueueEntry.StateChangeListener
+ private class GroupStateChangeListener implements StateChangeListener<MessageInstance<QueueConsumer>, QueueEntry.State>
{
private final Group _group;
public GroupStateChangeListener(final Group group,
- final QueueEntry entry)
+ final MessageInstance<QueueConsumer> entry)
{
_group = group;
}
- public void stateChanged(final QueueEntry entry,
- final QueueEntry.State oldState,
- final QueueEntry.State newState)
+ public void stateChanged(final MessageInstance<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/subscription/MessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java
index 8ce4ce3344..740a96bf2d 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/queue/MessageGroupManager.java
@@ -18,24 +18,22 @@
* under the License.
*
*/
-package org.apache.qpid.server.subscription;
-
-import org.apache.qpid.server.queue.QueueEntry;
+package org.apache.qpid.server.queue;
public interface MessageGroupManager
{
- public interface SubscriptionResetHelper
+ public interface ConsumerResetHelper
{
- public void resetSubPointersForGroups(Subscription subscription, boolean clearAssignments);
+ public void resetSubPointersForGroups(QueueConsumer consumer, boolean clearAssignments);
- boolean isEntryAheadOfSubscription(QueueEntry entry, Subscription sub);
+ boolean isEntryAheadOfConsumer(QueueEntry entry, QueueConsumer sub);
}
- Subscription getAssignedSubscription(QueueEntry entry);
+ QueueConsumer getAssignedConsumer(QueueEntry entry);
- boolean acceptMessage(Subscription sub, QueueEntry entry);
+ boolean acceptMessage(QueueConsumer sub, QueueEntry entry);
- QueueEntry findEarliestAssignedAvailableEntry(Subscription sub);
+ QueueEntry findEarliestAssignedAvailableEntry(QueueConsumer sub);
- void clearAssignments(Subscription sub);
+ void clearAssignments(QueueConsumer sub);
}
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..6918ae683c 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,8 +20,6 @@
*/
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;
@@ -38,16 +36,16 @@ public abstract class OutOfOrderQueue extends SimpleAMQQueue
}
@Override
- protected void checkSubscriptionsNotAheadOfDelivery(final QueueEntry entry)
+ protected void checkConsumersNotAheadOfDelivery(final QueueEntry 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 subIter = getConsumerList().iterator();
while(subIter.advance() && !entry.isAcquired())
{
- final Subscription subscription = subIter.getNode().getSubscription();
- if(!subscription.isClosed())
+ final QueueConsumer consumer = subIter.getNode().getConsumer();
+ if(!consumer.isClosed())
{
- QueueContext context = (QueueContext) subscription.getQueueContext();
+ QueueContext context = consumer.getQueueContext();
if(context != null)
{
QueueEntry released = context.getReleasedEntry();
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..05d84327d4 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
@@ -24,7 +24,7 @@ import org.apache.qpid.server.message.ServerMessage;
public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
{
- private final AMQQueue _queue;
+ private final AMQQueue<QueueConsumer> _queue;
private final PriorityQueueEntrySubList[] _priorityLists;
private final int _priorities;
private final int _priorityOffset;
@@ -46,7 +46,7 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
return _priorities;
}
- public AMQQueue getQueue()
+ public AMQQueue<QueueConsumer> getQueue()
{
return _queue;
}
@@ -166,7 +166,7 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
{
private int _listPriority;
- public PriorityQueueEntrySubList(AMQQueue queue, int listPriority)
+ public PriorityQueueEntrySubList(AMQQueue<QueueConsumer> queue, int listPriority)
{
super(queue);
_listPriority = listPriority;
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..ff7840255a
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java
@@ -0,0 +1,480 @@
+/*
+ *
+ * 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> 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 AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE);
+ private final Lock _stateChangeLock = new ReentrantLock();
+ private final long _createTime = System.currentTimeMillis();
+ private final MessageInstance.ConsumerAcquiredState _owningState = new MessageInstance.ConsumerAcquiredState(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 SimpleAMQQueue _queue;
+ private GenericActor _logActor;
+
+ 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 _queueContext;
+ private StateChangeListener<? extends Consumer, State> _stateListener = new StateChangeListener<Consumer, State>()
+ {
+ public void stateChanged(Consumer 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<Consumer, State> stateListener =
+ (StateChangeListener<Consumer, State>) 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 SimpleAMQQueue getQueue()
+ {
+ return _queue;
+ }
+
+ final void setQueue(SimpleAMQQueue 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 MessageInstance entry) throws AMQException
+ {
+ return getQueue().resend((QueueEntry)entry, this);
+ }
+
+ final SubFlushRunner getRunner()
+ {
+ return _runner;
+ }
+
+ public final long getId()
+ {
+ return _id;
+ }
+
+ public final StateChangeListener<? extends Consumer, State> getStateListener()
+ {
+ return _stateListener;
+ }
+
+ public final void setStateListener(StateChangeListener<? extends Consumer, State> listener)
+ {
+ _stateListener = listener;
+ }
+
+ final QueueContext getQueueContext()
+ {
+ return _queueContext;
+ }
+
+ final void setQueueContext(QueueContext queueContext)
+ {
+ _queueContext = queueContext;
+ }
+
+ protected boolean updateState(State from, State to)
+ {
+ return _state.compareAndSet(from, to);
+ }
+
+ 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(MessageInstance 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");
+ hasEntries = true;
+ }
+
+ 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 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 QueueEntry 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..82e9d58cf3 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
{
- private final SubscriptionNode _head = new SubscriptionNode();
+ private final ConsumerNode _head = new ConsumerNode();
- private final AtomicReference<SubscriptionNode> _tail = new AtomicReference<SubscriptionNode>(_head);
- private final AtomicReference<SubscriptionNode> _subNodeMarker = new AtomicReference<SubscriptionNode>(_head);
+ private final AtomicReference<ConsumerNode> _tail = new AtomicReference<ConsumerNode>(_head);
+ private final AtomicReference<ConsumerNode> _subNodeMarker = new AtomicReference<ConsumerNode>(_head);
private final AtomicInteger _size = new AtomicInteger();
- public static final class SubscriptionNode
+ public static final class ConsumerNode
{
private final AtomicBoolean _deleted = new AtomicBoolean();
- private final AtomicReference<SubscriptionNode> _next = new AtomicReference<SubscriptionNode>();
- private final Subscription _sub;
+ private final AtomicReference<ConsumerNode> _next = new AtomicReference<ConsumerNode>();
+ private final QueueConsumer _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 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 findNext()
{
- SubscriptionNode next = nextNode();
+ ConsumerNode next = nextNode();
while(next != null && next.isDeleted())
{
- final SubscriptionNode newNext = next.nextNode();
+ final ConsumerNode 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 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 node)
{
return _next.compareAndSet(null, node);
}
@@ -112,18 +112,18 @@ public class SubscriptionList
return _deleted.compareAndSet(false,true);
}
- public Subscription getSubscription()
+ public QueueConsumer getConsumer()
{
return _sub;
}
}
- private void insert(final SubscriptionNode node, final boolean count)
+ private void insert(final ConsumerNode node, final boolean count)
{
for (;;)
{
- SubscriptionNode tail = _tail.get();
- SubscriptionNode next = tail.nextNode();
+ ConsumerNode tail = _tail.get();
+ ConsumerNode 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 sub)
{
- SubscriptionNode node = new SubscriptionNode(sub);
+ ConsumerNode node = new ConsumerNode(sub);
insert(node, true);
}
- public boolean remove(final Subscription sub)
+ public boolean remove(final QueueConsumer sub)
{
- SubscriptionNode prevNode = _head;
- SubscriptionNode node = _head.nextNode();
+ ConsumerNode prevNode = _head;
+ ConsumerNode 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(), 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 node)
{
- SubscriptionNode markedNode = _subNodeMarker.get();
+ ConsumerNode 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 dummy = new ConsumerNode();
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 expected, final ConsumerNode 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 getMarkedNode()
{
return _subNodeMarker.get();
}
- public static class SubscriptionNodeIterator
+ public static class ConsumerNodeIterator
{
- private SubscriptionNode _lastNode;
+ private ConsumerNode _lastNode;
- SubscriptionNodeIterator(SubscriptionNode startNode)
+ ConsumerNodeIterator(ConsumerNode startNode)
{
_lastNode = startNode;
}
- public SubscriptionNode getNode()
+ public ConsumerNode getNode()
{
return _lastNode;
}
public boolean advance()
{
- SubscriptionNode nextNode = _lastNode.findNext();
+ ConsumerNode nextNode = _lastNode.findNext();
_lastNode = nextNode;
return _lastNode != null;
}
}
- public SubscriptionNodeIterator iterator()
+ public ConsumerNodeIterator iterator()
{
- return new SubscriptionNodeIterator(_head);
+ return new ConsumerNodeIterator(_head);
}
- public SubscriptionNode getHead()
+ public ConsumerNode 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..861bd3dea1 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,7 +23,7 @@ package org.apache.qpid.server.queue;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-final class QueueContext implements AMQQueue.Context
+final class QueueContext
{
private volatile QueueEntry _lastSeenEntry;
private volatile QueueEntry _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..6a42088c47 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,20 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.filter.Filterable;
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 extends MessageInstance<QueueConsumer>, Comparable<QueueEntry>
{
-
-
- 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();
+ AMQQueue<QueueConsumer> 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();
-
- void decrementDeliveryCount();
-
- 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..8b81a87903 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;
@@ -46,7 +50,7 @@ public abstract class QueueEntryImpl implements QueueEntry
private final QueueEntryList _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<MessageInstance<QueueConsumer>, State>> _stateChangeListeners;
private static final
AtomicReferenceFieldUpdater<QueueEntryImpl, Set>
@@ -134,7 +138,7 @@ public abstract class QueueEntryImpl implements QueueEntry
return _entryId;
}
- public AMQQueue getQueue()
+ public AMQQueue<QueueConsumer> 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 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,14 +232,9 @@ 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);
- }
}
if(!getQueue().isDeleted())
@@ -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,12 +315,10 @@ public abstract class QueueEntryImpl implements QueueEntry
if((state.getState() == State.ACQUIRED) &&_stateUpdater.compareAndSet(this, state, DEQUEUED_STATE))
{
- Subscription s = null;
- if (state instanceof SubscriptionAcquiredState)
+ Consumer s = null;
+ if (state instanceof ConsumerAcquiredState)
{
getQueue().decrementUnackedMsgCount(this);
- s = ((SubscriptionAcquiredState) state).getSubscription();
- s.onDequeue(this);
}
getQueue().dequeue(this,s);
@@ -336,7 +333,7 @@ public abstract class QueueEntryImpl implements QueueEntry
private void notifyStateChange(final State oldState, final State newState)
{
- for(StateChangeListener l : _stateChangeListeners)
+ for(StateChangeListener<MessageInstance<QueueConsumer>, State> l : _stateChangeListeners)
{
l.stateChanged(this, oldState, newState);
}
@@ -367,7 +364,7 @@ public abstract class QueueEntryImpl implements QueueEntry
dispose();
}
- public int routeToAlternate(final BaseQueue.PostEnqueueAction action, ServerTransaction txn)
+ public int routeToAlternate(final Action<MessageInstance<? extends Consumer>> action, ServerTransaction txn)
{
final AMQQueue currentQueue = getQueue();
Exchange alternateExchange = currentQueue.getAlternateExchange();
@@ -379,7 +376,10 @@ public abstract class QueueEntryImpl implements QueueEntry
txn = new LocalTransaction(getQueue().getVirtualHost().getMessageStore());
}
- int enqueues = alternateExchange.send(getMessage(), getInstanceProperties(), txn, action);
+ int enqueues = alternateExchange.send(getMessage(),
+ getInstanceProperties(),
+ txn,
+ action);
txn.dequeue(currentQueue, getMessage(), new ServerTransaction.Action()
{
@@ -412,21 +412,21 @@ public abstract class QueueEntryImpl implements QueueEntry
return getQueue().isDeleted();
}
- public void addStateChangeListener(StateChangeListener listener)
+ public void addStateChangeListener(StateChangeListener<MessageInstance<QueueConsumer>, State> listener)
{
- Set<StateChangeListener> listeners = _stateChangeListeners;
+ Set<StateChangeListener<MessageInstance<QueueConsumer>, State>> listeners = _stateChangeListeners;
if(listeners == null)
{
- _listenersUpdater.compareAndSet(this, null, new CopyOnWriteArraySet<StateChangeListener>());
+ _listenersUpdater.compareAndSet(this, null, new CopyOnWriteArraySet<StateChangeListener<MessageInstance<QueueConsumer>, State>>());
listeners = _stateChangeListeners;
}
listeners.add(listener);
}
- public boolean removeStateChangeListener(StateChangeListener listener)
+ public boolean removeStateChangeListener(StateChangeListener<MessageInstance<QueueConsumer>, State> listener)
{
- Set<StateChangeListener> listeners = _stateChangeListeners;
+ Set<StateChangeListener<MessageInstance<QueueConsumer>, State>> listeners = _stateChangeListeners;
if(listeners != null)
{
return listeners.remove(listener);
@@ -461,6 +461,12 @@ public abstract class QueueEntryImpl implements QueueEntry
return _deliveryCount;
}
+ @Override
+ public int getMaximumDeliveryCount()
+ {
+ return getQueue().getMaximumDeliveryCount();
+ }
+
public void incrementDeliveryCount()
{
_deliveryCountUpdater.incrementAndGet(this);
@@ -485,6 +491,23 @@ public abstract class QueueEntryImpl implements QueueEntry
'}';
}
+ @Override
+ public boolean resend() throws AMQException
+ {
+ QueueConsumer sub = getDeliveredConsumer();
+ if(sub != null)
+ {
+ return sub.resend(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/QueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
index 641aaa0a08..ad1f703f51 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
@@ -24,7 +24,7 @@ import org.apache.qpid.server.message.ServerMessage;
public interface QueueEntryList<Q extends QueueEntry>
{
- AMQQueue getQueue();
+ AMQQueue<QueueConsumer> getQueue();
Q add(ServerMessage message);
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..f4a9794fcd 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.MessageDestination;
+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.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
+public class SimpleAMQQueue implements AMQQueue<QueueConsumer>,
+ StateChangeListener<QueueConsumer, QueueConsumer.State>,
+ MessageGroupManager.ConsumerResetHelper
{
private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class);
@@ -98,9 +96,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private final QueueEntryList<QueueEntry> _entries;
- private final SubscriptionList _subscriptionList = new SubscriptionList();
+ private final QueueConsumerList _consumerList = new QueueConsumerList();
- private volatile Subscription _exclusiveSubscriber;
+ private volatile QueueConsumer _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,7 +157,7 @@ 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;
@@ -187,8 +179,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private int _maximumDeliveryCount;
private final MessageGroupManager _messageGroupManager;
- private final Collection<SubscriptionRegistrationListener> _subscriptionListeners =
- new ArrayList<SubscriptionRegistrationListener>();
+ private final Collection<ConsumerRegistrationListener> _consumerListeners =
+ new ArrayList<ConsumerRegistrationListener>();
private AMQQueue.NotificationListener _notificationListener;
private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length];
@@ -257,7 +249,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
else
{
- _messageGroupManager = new AssignedSubscriptionMessageGroupManager(String.valueOf(arguments.get(
+ _messageGroupManager = new AssignedConsumerMessageGroupManager(String.valueOf(arguments.get(
Queue.MESSAGE_GROUP_KEY)), DEFAULT_MAX_GROUPS);
}
}
@@ -388,11 +380,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 QueueConsumer addConsumer(final ConsumerTarget 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 +398,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 consumer = new QueueConsumer(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(_entries.getHead()));
if (!isDeleted())
{
- subscription.setQueue(this, exclusive);
+ consumer.setQueue(this, exclusive);
if(_nolocal)
{
- subscription.setNoLocal(_nolocal);
+ consumer.setNoLocal(_nolocal);
}
- synchronized (_subscriptionListeners)
+ synchronized (_consumerListeners)
{
- for(SubscriptionRegistrationListener listener : _subscriptionListeners)
+ for(ConsumerRegistrationListener listener : _consumerListeners)
{
- listener.subscriptionRegistered(this, subscription);
+ listener.consumerAdded(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 +460,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 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 listener : _consumerListeners)
{
- listener.subscriptionUnregistered(this, subscription);
+ listener.consumerRemoved(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 +511,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> getConsumers()
{
- List<Subscription> consumers = new ArrayList<Subscription>();
- SubscriptionList.SubscriptionNodeIterator iter = _subscriptionList.iterator();
+ List<QueueConsumer> consumers = new ArrayList<QueueConsumer>();
+ QueueConsumerList.ConsumerNodeIterator 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 listener)
{
- synchronized (_subscriptionListeners)
+ synchronized (_consumerListeners)
{
- _subscriptionListeners.add(listener);
+ _consumerListeners.add(listener);
}
}
- public void removeSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ public void removeConsumerRegistrationListener(final ConsumerRegistrationListener listener)
{
- synchronized (_subscriptionListeners)
+ synchronized (_consumerListeners)
{
- _subscriptionListeners.remove(listener);
+ _consumerListeners.remove(listener);
}
}
- public void resetSubPointersForGroups(Subscription subscription, boolean clearAssignments)
+ public void resetSubPointersForGroups(QueueConsumer consumer, boolean clearAssignments)
{
- QueueEntry entry = _messageGroupManager.findEarliestAssignedAvailableEntry(subscription);
+ QueueEntry entry = _messageGroupManager.findEarliestAssignedAvailableEntry(consumer);
if(clearAssignments)
{
- _messageGroupManager.clearAssignments(subscription);
+ _messageGroupManager.clearAssignments(consumer);
}
if(entry != null)
{
- SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
+ QueueConsumerList.ConsumerNodeIterator 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 sub = subscriberIter.getNode().getConsumer();
// we don't make browsers send the same stuff twice
if (sub.seesRequeues())
@@ -617,23 +625,9 @@ 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
- {
- enqueue(message, false, action);
- }
- public void enqueue(ServerMessage message, boolean transactional, PostEnqueueAction action) throws AMQException
+ public void enqueue(ServerMessage message, Action<MessageInstance<? extends Consumer>> action) throws AMQException
{
-
- if(transactional)
- {
- incrementTxnEnqueueStats(message);
- }
incrementQueueCount();
incrementQueueSize(message);
@@ -641,35 +635,35 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
QueueEntry entry;
- final Subscription exclusiveSub = _exclusiveSubscriber;
+ final QueueConsumer 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 node = _consumerList.getMarkedNode();
+ QueueConsumerList.ConsumerNode 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 +677,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 sub = nextNode.getConsumer();
+ deliverToConsumer(sub, entry);
}
nextNode = nextNode.findNext();
@@ -699,7 +693,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if (entry.isAvailable())
{
- checkSubscriptionsNotAheadOfDelivery(entry);
+ checkConsumersNotAheadOfDelivery(entry);
if (exclusiveSub != null)
{
@@ -715,12 +709,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 sub, final QueueEntry entry)
throws AMQException
{
@@ -729,14 +723,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 +746,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- private boolean assign(final Subscription sub, final QueueEntry entry)
+ private boolean assign(final QueueConsumer sub, final QueueEntry entry)
{
if(_messageGroupManager == null)
{
@@ -766,17 +760,17 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- private boolean mightAssign(final Subscription sub, final QueueEntry entry)
+ private boolean mightAssign(final QueueConsumer sub, final QueueEntry 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 QueueEntry entry)
{
// This method is only required for queues which mess with ordering
// Simple Queues don't :-)
@@ -810,19 +804,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 sub, final QueueEntry entry, boolean batch)
throws AMQException
{
setLastSeenEntry(sub, entry);
@@ -833,15 +815,15 @@ 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 sub, final QueueEntry entry) throws AMQException
{
return sub.hasInterest(entry) && (getNextAvailableEntry(sub) == entry);
}
- private void setLastSeenEntry(final Subscription sub, final QueueEntry entry)
+ private void setLastSeenEntry(final QueueConsumer sub, final QueueEntry entry)
{
- QueueContext subContext = (QueueContext) sub.getQueueContext();
+ QueueContext subContext = sub.getQueueContext();
if (subContext != null)
{
QueueEntry releasedEntry = subContext.getReleasedEntry();
@@ -854,10 +836,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- private void updateSubRequeueEntry(final Subscription sub, final QueueEntry entry)
+ private void updateSubRequeueEntry(final QueueConsumer sub, final QueueEntry entry)
{
- QueueContext subContext = (QueueContext) sub.getQueueContext();
+ QueueContext subContext = sub.getQueueContext();
if(subContext != null)
{
QueueEntry oldEntry;
@@ -874,11 +856,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public void requeue(QueueEntry entry)
{
- SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
+ QueueConsumerList.ConsumerNodeIterator 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 sub = subscriberIter.getNode().getConsumer();
// we don't make browsers send the same stuff twice
if (sub.seesRequeues())
@@ -891,20 +873,15 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void dequeue(QueueEntry entry, Subscription sub)
+ public void dequeue(QueueEntry entry, Consumer sub)
{
decrementQueueCount();
decrementQueueSize(entry);
- if (entry.acquiredBySubscription())
+ if (entry.acquiredByConsumer())
{
_deliveredMessages.decrementAndGet();
}
- if(sub != null && sub.isSessionTransactional())
- {
- incrementTxnDequeueStats(entry);
- }
-
checkCapacity();
}
@@ -928,17 +905,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 QueueEntry entry, final Consumer 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((QueueConsumer) consumer, entry, false);
return true;
}
else
@@ -948,7 +925,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
finally
{
- subscription.releaseSendLock();
+ consumer.releaseSendLock();
}
}
@@ -956,12 +933,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()
@@ -1039,16 +1011,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void stateChange(Subscription sub, Subscription.State oldState, Subscription.State newState)
+ public void stateChanged(QueueConsumer 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();
@@ -1072,12 +1044,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 exclusiveSubscriber)
{
_exclusiveSubscriber = exclusiveSubscriber;
}
@@ -1093,9 +1065,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _entries;
}
- protected SubscriptionList getSubscriptionList()
+ protected QueueConsumerList getConsumerList()
{
- return _subscriptionList;
+ return _consumerList;
}
@@ -1300,12 +1272,12 @@ 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);
}
@@ -1322,19 +1294,21 @@ 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();
}
}
@@ -1375,9 +1349,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 +1435,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void deliverAsync(Subscription sub)
+ public void deliverAsync(QueueConsumer sub)
{
if(_exclusiveSubscriber == null)
{
@@ -1469,28 +1443,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 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 sub, long iterations) throws AMQException
{
boolean atTail = false;
final boolean keepSendLockHeld = iterations <= SimpleAMQQueue.MAX_ASYNC_DELIVERIES;
@@ -1511,8 +1480,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
sub.getSendLock();
}
- atTail = attemptDelivery(sub, true);
- if (atTail && getNextAvailableEntry(sub) == null)
+ atTail = attemptDelivery((QueueConsumer)sub, true);
+ if (atTail && getNextAvailableEntry((QueueConsumer)sub) == null)
{
queueEmpty = true;
}
@@ -1546,21 +1515,21 @@ 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
@@ -1568,7 +1537,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
* @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 sub, boolean batch) throws AMQException
{
boolean atTail = false;
@@ -1587,7 +1556,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 +1567,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 +1580,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 consumerNodeIterator = _consumerList.iterator();
+ while (consumerNodeIterator.advance())
{
- SubscriptionList.SubscriptionNode subNode = subscriberIter.getNode();
- Subscription sub = subNode.getSubscription();
+ QueueConsumerList.ConsumerNode subNode = consumerNodeIterator.getNode();
+ QueueConsumer sub = subNode.getConsumer();
if(sub.acquires())
{
getNextAvailableEntry(sub);
@@ -1629,10 +1598,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- private QueueEntry getNextAvailableEntry(final Subscription sub)
+ private QueueEntry getNextAvailableEntry(final QueueConsumer sub)
throws AMQException
{
- QueueContext context = (QueueContext) sub.getQueueContext();
+ QueueContext context = sub.getQueueContext();
if(context != null)
{
QueueEntry lastSeen = context.getLastSeenEntry();
@@ -1670,9 +1639,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- public boolean isEntryAheadOfSubscription(QueueEntry entry, Subscription sub)
+ public boolean isEntryAheadOfConsumer(QueueEntry entry, QueueConsumer sub)
{
- QueueContext context = (QueueContext) sub.getQueueContext();
+ QueueContext context = sub.getQueueContext();
if(context != null)
{
QueueEntry releasedNode = context.getReleasedEntry();
@@ -1689,14 +1658,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
@@ -1720,7 +1689,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 +1700,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 +1713,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 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 sub = consumerNodeIterator.getNode().getConsumer();
sub.getSendLock();
try
@@ -1759,8 +1728,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 +1740,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 +1761,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;
@@ -1984,12 +1953,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _notificationChecks;
}
- private final class QueueEntryListener implements QueueEntry.StateChangeListener
+ private final class QueueEntryListener implements StateChangeListener<MessageInstance<QueueConsumer>, QueueEntry.State>
{
- private final Subscription _sub;
+ private final QueueConsumer _sub;
- public QueueEntryListener(final Subscription sub)
+ public QueueEntryListener(final QueueConsumer sub)
{
_sub = sub;
}
@@ -2005,7 +1974,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(MessageInstance entry, QueueEntry.State oldSate, QueueEntry.State newState)
{
entry.removeStateChangeListener(this);
deliverAsync(_sub);
@@ -2076,26 +2045,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 +2072,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return getName();
}
- public long getUnackedMessageCountHigh()
- {
- return _unackedMsgCountHigh.get();
- }
-
public long getUnackedMessageCount()
{
return _unackedMsgCount.get();
@@ -2146,17 +2090,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private void incrementUnackedMsgCount(QueueEntry 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 +2159,39 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return (String) _arguments.get(Queue.DESCRIPTION);
}
+ public final int send(final ServerMessage message,
+ final InstanceProperties instanceProperties,
+ final ServerTransaction txn,
+ final Action<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..101771c7cc 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
@@ -39,7 +39,7 @@ public class SimpleQueueEntryList implements QueueEntryList<SimpleQueueEntryImpl
(SimpleQueueEntryList.class, SimpleQueueEntryImpl.class, "_tail");
- private final AMQQueue _queue;
+ private final AMQQueue<QueueConsumer> _queue;
static final AtomicReferenceFieldUpdater<SimpleQueueEntryImpl, SimpleQueueEntryImpl>
_nextUpdater = SimpleQueueEntryImpl._nextUpdater;
@@ -49,7 +49,7 @@ public class SimpleQueueEntryList implements QueueEntryList<SimpleQueueEntryImpl
private final AtomicReference<SimpleQueueEntryImpl> _unscavengedHWM = new AtomicReference<SimpleQueueEntryImpl>();
- public SimpleQueueEntryList(AMQQueue queue)
+ public SimpleQueueEntryList(AMQQueue<QueueConsumer> queue)
{
_queue = queue;
_head = new SimpleQueueEntryImpl(this);
@@ -71,7 +71,7 @@ public class SimpleQueueEntryList implements QueueEntryList<SimpleQueueEntryImpl
}
- public AMQQueue getQueue()
+ public AMQQueue<QueueConsumer> getQueue()
{
return _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..cad1aa6d4f 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,7 +20,10 @@
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;
@@ -29,7 +32,7 @@ import java.util.UUID;
public class SortedQueue extends OutOfOrderQueue
{
//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;
@@ -48,7 +51,7 @@ public class SortedQueue extends OutOfOrderQueue
return _sortedPropertyName;
}
- public void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException
+ public void enqueue(ServerMessage message, Action<MessageInstance<? extends Consumer>> action) throws AMQException
{
synchronized (_sortedQueueLock)
{
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..336ee566eb 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
@@ -28,7 +28,7 @@ import org.apache.qpid.server.queue.SortedQueueEntryImpl.Colour;
* 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>
{
@@ -36,17 +36,17 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl
private SortedQueueEntryImpl _root;
private long _entryId = Long.MIN_VALUE;
private final Object _lock = new Object();
- private final AMQQueue _queue;
+ private final AMQQueue<QueueConsumer> _queue;
private final String _propertyName;
- public SortedQueueEntryList(final AMQQueue queue, final String propertyName)
+ public SortedQueueEntryList(final AMQQueue<QueueConsumer> queue, final String propertyName)
{
_queue = queue;
_head = new SortedQueueEntryImpl(this);
_propertyName = propertyName;
}
- public AMQQueue getQueue()
+ public AMQQueue<QueueConsumer> getQueue()
{
return _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 e490ac38c1..d80fa656e7 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
@@ -1065,7 +1065,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();
}
@@ -1076,7 +1076,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();
}
@@ -1199,7 +1199,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
{
@@ -1371,7 +1371,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
}
@Override
- public TransactionLogResource getQueue()
+ public TransactionLogResource getResource()
{
return this;
}
@@ -1401,10 +1401,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..de7369f5ed 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<? extends Consumer> 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<? extends Consumer> 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 d48b09d912..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,7 +105,7 @@ 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)
{
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 5859ce3c68..9a23e00f90 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
@@ -47,8 +47,13 @@ import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.VirtualHostMessages;
+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;
@@ -99,6 +104,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
private final DtxRegistry _dtxRegistry;
private final AMQQueueFactory _queueFactory;
+ private final SystemNodeRegistry _systemNodeRegistry = new SystemNodeRegistry();
private volatile State _state = State.INITIALISING;
@@ -107,6 +113,13 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
private final Map<String, LinkRegistry> _linkRegistry = new HashMap<String, LinkRegistry>();
private boolean _blocked;
+ 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,
@@ -149,6 +162,8 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
_exchangeRegistry = new DefaultExchangeRegistry(this, _queueRegistry);
+ registerSystemNodes();
+
initialiseStatistics();
initialiseStorage(hostConfig, virtualHost);
@@ -157,6 +172,16 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
getMessageStore().addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL);
}
+ 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;
@@ -441,6 +466,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);
@@ -524,6 +556,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)
{
@@ -927,4 +967,39 @@ 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;
+ }
+ }
}
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 2ebbedccd4..7034311d84 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
@@ -30,6 +30,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;
@@ -49,6 +52,7 @@ public interface VirtualHost extends DurableConfigurationStore.Source, Closeable
String getName();
AMQQueue getQueue(String name);
+ MessageSource getMessageSource(String name);
AMQQueue getQueue(UUID id);
@@ -76,6 +80,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/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..ea9d0ac693 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;
@@ -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<Consumer> 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<Consumer> 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<Consumer> 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<Consumer> 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<Consumer> 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<Consumer> 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<Consumer> 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/AMQPriorityQueueTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java
index a468fa072b..ced00dc578 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/AMQPriorityQueueTest.java
@@ -25,10 +25,14 @@ import junit.framework.AssertionFailedError;
import org.apache.qpid.AMQException;
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.when;
@@ -47,25 +51,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 +88,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/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..66c12717db 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,21 +24,28 @@ 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.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;
import java.util.concurrent.CopyOnWriteArrayList;
-public class MockAMQQueue implements AMQQueue
+public class MockAMQQueue implements AMQQueue<QueueConsumer>
{
private boolean _deleted = false;
private String _name;
@@ -202,32 +209,44 @@ public class MockAMQQueue implements AMQQueue
return _virtualhost;
}
- public String getName()
+ @Override
+ public QueueConsumer addConsumer(final ConsumerTarget target,
+ final FilterManager filters,
+ final Class<? extends ServerMessage> messageClass,
+ final String consumerName,
+ final EnumSet<Consumer.Option> options) throws AMQException
{
- return _name;
+ 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 registerSubscription(Subscription subscription, boolean exclusive) throws AMQException
+ public String getName()
{
-
+ return _name;
}
- public void unregisterSubscription(Subscription subscription) throws AMQException
+ @Override
+ public int send(final ServerMessage message,
+ final InstanceProperties instanceProperties,
+ final ServerTransaction txn,
+ final Action<MessageInstance<? extends Consumer>> 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 +261,7 @@ public class MockAMQQueue implements AMQQueue
return 0;
}
- public boolean hasExclusiveSubscriber()
+ public boolean hasExclusiveConsumer()
{
return false;
}
@@ -293,41 +312,29 @@ 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, Action<MessageInstance<? extends Consumer>> 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, Subscription sub)
+ public void dequeue(QueueEntry entry, Consumer sub)
{
}
- public boolean resend(QueueEntry entry, Subscription subscription) throws AMQException
+ public boolean resend(QueueEntry entry, Consumer consumer) throws AMQException
{
return false;
}
- public void addQueueDeleteTask(Task task)
+ public void addQueueDeleteTask(Action<AMQQueue> task)
{
}
- public void removeQueueDeleteTask(final Task task)
+ public void removeQueueDeleteTask(final Action<AMQQueue> task)
{
}
@@ -427,12 +434,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)
{
}
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/MockQueueEntry.java
index d3c866f747..89b366567d 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/MockQueueEntry.java
@@ -24,9 +24,13 @@ 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
{
@@ -38,22 +42,28 @@ public class MockQueueEntry implements QueueEntry
return false;
}
- public boolean acquire(Subscription sub)
+ public boolean acquire(QueueConsumer sub)
{
return false;
}
- public boolean acquiredBySubscription()
+ @Override
+ public int getMaximumDeliveryCount()
+ {
+ return 0;
+ }
+
+ public boolean acquiredByConsumer()
{
return false;
}
- public boolean isAcquiredBy(Subscription subscription)
+ public boolean isAcquiredBy(QueueConsumer consumer)
{
return false;
}
- public void addStateChangeListener(StateChangeListener listener)
+ public void addStateChangeListener(StateChangeListener<MessageInstance<QueueConsumer>, State> listener)
{
}
@@ -63,7 +73,7 @@ public class MockQueueEntry implements QueueEntry
}
- public int routeToAlternate(final BaseQueue.PostEnqueueAction action, final ServerTransaction txn)
+ public int routeToAlternate(final Action<MessageInstance<? extends Consumer>> action, final ServerTransaction txn)
{
return 0;
}
@@ -78,7 +88,7 @@ public class MockQueueEntry implements QueueEntry
return false;
}
- public Subscription getDeliveredSubscription()
+ public QueueConsumer getDeliveredConsumer()
{
return null;
}
@@ -93,7 +103,7 @@ public class MockQueueEntry implements QueueEntry
return _message;
}
- public AMQQueue getQueue()
+ public AMQQueue<QueueConsumer> getQueue()
{
return null;
}
@@ -116,7 +126,7 @@ public class MockQueueEntry implements QueueEntry
}
- public boolean isRejectedBy(long subscriptionId)
+ public boolean isRejectedBy(QueueConsumer consumer)
{
return false;
@@ -136,8 +146,14 @@ public class MockQueueEntry implements QueueEntry
}
+ @Override
+ public boolean resend() throws AMQException
+ {
+ return false;
+ }
+
- public boolean removeStateChangeListener(StateChangeListener listener)
+ public boolean removeStateChangeListener(StateChangeListener<MessageInstance<QueueConsumer>, State> listener)
{
return false;
@@ -217,4 +233,10 @@ public class MockQueueEntry implements QueueEntry
{
return InstanceProperties.EMPTY;
}
+
+ @Override
+ public TransactionLogResource getOwningResource()
+ {
+ return getQueue();
+ }
}
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..95139d8740 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,11 +21,11 @@ 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.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 java.lang.reflect.Field;
@@ -113,11 +113,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 +148,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));
}
/**
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/SimpleAMQQueueTest.java
index b0e5a510b8..5abc97cee9 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/SimpleAMQQueueTest.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,15 @@ 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.ConsumerTarget;
+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;
@@ -65,7 +69,8 @@ public class SimpleAMQQueueTest extends QpidTestCase
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
@@ -157,20 +162,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 +184,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 +237,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 +258,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 +271,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 +288,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 +308,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 +320,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 +337,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 +357,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 +371,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 +414,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 +455,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 +475,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)
{
@@ -462,23 +500,45 @@ public class SimpleAMQQueueTest extends QpidTestCase
_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",
+
+ ServerMessage message = createMessage(new Long(25));
+ _consumer = _queue.addConsumer(_consumerTarget, null, message.getClass(), "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
+
+ _queue.enqueue(message, null);
+ _consumer.close();
+ assertTrue("Queue was not deleted when consumer 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)
+ {
+ QueueEntry entry = (QueueEntry) object;
+ entry.setRedelivered();
+ try
+ {
+ _consumer.resend(entry);
+ }
+ catch (AMQException e)
+ {
+ fail("Exception thrown: " + e.getMessage());
+ }
+ }
+ });
+
+
}
@@ -489,7 +549,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 +565,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 +586,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,7 +607,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 non-existent 0th QueueEntry & check returned list was empty
@@ -605,19 +665,19 @@ 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
{
@@ -626,10 +686,10 @@ public class SimpleAMQQueueTest extends QpidTestCase
false, false, _virtualHost, factory, null)
{
@Override
- public void deliverAsync(Subscription sub)
+ public void deliverAsync(QueueConsumer sub)
{
// do nothing, i.e prevent deliveries by the SubFlushRunner
- // when registering the new subscriptions
+ // when registering the new consumers
}
};
@@ -645,25 +705,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 +743,9 @@ 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());
}
/**
@@ -850,7 +913,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
false, "testOwner", false, false, _virtualHost, null)
{
@Override
- public void deliverAsync(Subscription sub)
+ public void deliverAsync(QueueConsumer sub)
{
// do nothing
}
@@ -865,15 +928,15 @@ public class SimpleAMQQueueTest extends QpidTestCase
// latch to wait for message receipt
final CountDownLatch latch = new CountDownLatch(messageNumber -1);
- // create a subscription
- MockSubscription subscription = new MockSubscription()
+ // create a consumer
+ MockConsumer consumer = new MockConsumer()
{
/**
* Send a message and decrement latch
* @param entry
* @param batch
*/
- public void send(QueueEntry entry, boolean batch) throws AMQException
+ public void send(MessageInstance entry, boolean batch) throws AMQException
{
super.send(entry, batch);
latch.countDown();
@@ -883,7 +946,12 @@ public class SimpleAMQQueueTest extends QpidTestCase
try
{
// subscribe
- testQueue.registerSubscription(subscription, false);
+ 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)
@@ -907,12 +975,12 @@ public class SimpleAMQQueueTest extends QpidTestCase
{
Thread.currentThread().interrupt();
}
- List<QueueEntry> expected = createEntriesList(entries.get(0), entries.get(2), entries.get(3));
- verifyReceivedMessages(expected, subscription.getMessages());
+ List<MessageInstance> expected = Arrays.asList((MessageInstance)entries.get(0), entries.get(2), entries.get(3));
+ verifyReceivedMessages(expected, consumer.getMessages());
}
/**
- * Tests that entry in dequeued state are not enqueued and not delivered to subscription
+ * Tests that entry in dequeued state are not enqueued and not delivered to consumer
*/
public void testEnqueueDequeuedEntry()
{
@@ -948,7 +1016,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
}
@Override
- public boolean acquire(Subscription sub)
+ public boolean acquire(QueueConsumer sub)
{
if(message.getMessageNumber() % 2 == 0)
{
@@ -964,24 +1032,29 @@ public class SimpleAMQQueueTest extends QpidTestCase
};
}
}, null);
- // create a subscription
- MockSubscription subscription = new MockSubscription();
+ // create a consumer
+ MockConsumer consumer = new MockConsumer();
- // register subscription
+ // register consumer
try
{
- queue.registerSubscription(subscription, false);
+ queue.addConsumer(consumer,
+ null,
+ createMessage(-1l).getClass(),
+ "test",
+ EnumSet.of(Consumer.Option.ACQUIRES,
+ Consumer.Option.SEES_REQUEUES));
}
catch (AMQException e)
{
- fail("Failure to register subscription:" + e.getMessage());
+ fail("Failure to register consumer:" + e.getMessage());
}
// put test messages into a queue
putGivenNumberOfMessages(queue, 4);
// assert received messages
- List<QueueEntry> messages = subscription.getMessages();
+ 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());
@@ -994,55 +1067,64 @@ public class SimpleAMQQueueTest extends QpidTestCase
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);
+ //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.registerSubscription(subscription1, false);
+ 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 subscription doesn't increase the count
- final MockSubscription subscription2 = new MockSubscription();
- subscription2.setActive(false);
+ //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.registerSubscription(subscription2, false);
+ 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 subscription going suspended->active increases the count
- queue.stateChange(subscription2, Subscription.State.SUSPENDED, Subscription.State.ACTIVE);
+ //verify a consumer going suspended->active increases the count
+ consumer2.setState(ConsumerTarget.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);
+ //verify a consumer going active->suspended decreases the count
+ consumer2.setState(ConsumerTarget.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);
+ //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 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 a consumer going active->active doesn't change the count
+ consumer1.setState(ConsumerTarget.State.ACTIVE);
+ assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
- //verify behaviour in face of unexpected state changes:
+ consumer1.setState(ConsumerTarget.State.SUSPENDED);
+ assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount());
- //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 consumer going suspended->suspended doesn't change the count
+ consumer1.setState(ConsumerTarget.State.SUSPENDED);
+ assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount());
- //verify a subscription going active->active doesn't change the count
- queue.stateChange(subscription2, Subscription.State.ACTIVE, Subscription.State.ACTIVE);
+ consumer1.setState(ConsumerTarget.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 consumer going active->closed decreases the count
+ consumer1.setState(ConsumerTarget.State.CLOSED);
+ assertEquals("Unexpected active consumer count", 0, 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 +1134,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 +1146,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);
@@ -1132,7 +1214,7 @@ public class SimpleAMQQueueTest extends QpidTestCase
// Put message on queue
try
{
- queue.enqueue(message);
+ queue.enqueue(message,null);
}
catch (AMQException e)
{
@@ -1167,23 +1249,23 @@ 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)
+ private 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));
@@ -1195,9 +1277,9 @@ public class SimpleAMQQueueTest extends QpidTestCase
return _queue;
}
- public MockSubscription getSubscription()
+ public MockConsumer getConsumer()
{
- return _subscription;
+ return _consumerTarget;
}
public Map<String,Object> getArguments()
@@ -1213,20 +1295,36 @@ 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;
}
+ 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);
+ }
+ }
+
class TestSimpleQueueEntryListFactory implements QueueEntryListFactory
{
QueueEntryList _list;
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 121c380736..7a4f92f0ca 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
@@ -154,6 +154,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..11b9bbe1b4 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,6 +20,7 @@
*/
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;
@@ -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);
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..80e794e0ff 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,6 +20,7 @@
*/
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;
@@ -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);
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
index 1ca7ff1b65..832b89c81a 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
@@ -27,6 +27,8 @@ import org.apache.qpid.AMQException;
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.MessageSource;
import org.apache.qpid.server.plugin.ExchangeType;
import org.apache.qpid.server.protocol.LinkRegistry;
import org.apache.qpid.server.queue.AMQQueue;
@@ -127,6 +129,12 @@ public class MockVirtualHost implements VirtualHost
}
@Override
+ public MessageSource getMessageSource(final String name)
+ {
+ return null;
+ }
+
+ @Override
public AMQQueue getQueue(UUID id)
{
return null;
@@ -174,6 +182,12 @@ public class MockVirtualHost implements VirtualHost
}
@Override
+ public MessageDestination getMessageDestination(final String name)
+ {
+ return null;
+ }
+
+ @Override
public Exchange getExchange(String name)
{
return null;
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..6ad9de22cb
--- /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,580 @@
+/*
+ *
+ * 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();
+
+ getConsumer().getSendLock();
+ try
+ {
+ while(!closed && state != State.CLOSED)
+ {
+ closed = updateState(state, State.CLOSED);
+ if(!closed)
+ {
+ state = getState();
+ }
+ }
+ _creditManager.removeListener(this);
+ }
+ finally
+ {
+ getConsumer().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/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 93d886687c..53022c333e 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,8 +821,8 @@ 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);
}
@@ -955,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 dcca696529..9a90b74656 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;
@@ -385,7 +406,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)
{
@@ -393,12 +414,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);
- }
}
}
@@ -407,7 +423,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)
{
@@ -814,24 +830,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)
@@ -1249,9 +1265,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
{
@@ -1265,9 +1281,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);
}
@@ -1276,9 +1292,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);
@@ -1287,9 +1303,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);
}
@@ -1461,7 +1477,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)
{
@@ -1478,7 +1494,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)
{
@@ -1496,7 +1512,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-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 e139887284..aa465d373f 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,7 @@ 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.FilterManagerFactory;
import org.apache.qpid.server.flow.FlowCreditManager;
import org.apache.qpid.server.flow.Pre0_10CreditManager;
import org.apache.qpid.server.logging.LogActor;
@@ -66,25 +56,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 +115,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 +148,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 +259,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 +268,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 +353,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,62 +490,89 @@ 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) 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.
// We add before we register as the Async Delivery process may AutoClose the subscriber
// 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);
+ Consumer sub =
+ source.addConsumer(target,
+ FilterManagerFactory.createManager(FieldTable.convertToMap(filters)),
+ 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 +587,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 +646,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 +656,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 +679,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 +710,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 +721,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 +741,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 +749,8 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
unacked.setRedelivered();
// Ensure message is released for redelivery
- if (!unacked.isQueueDeleted())
- {
-
- // 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.release();
- unacked.delete();
- }
}
else
{
@@ -786,10 +763,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 +775,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 +789,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 +808,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 +825,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 +853,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 +881,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 +931,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 +947,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 +1032,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 +1053,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 +1070,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 +1128,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);
}
@@ -1234,78 +1189,96 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
}
- 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;
}
@@ -1314,7 +1287,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
{
try
{
- for(QueueEntry entry : _ackedMessages)
+ for(MessageInstance entry : _ackedMessages)
{
entry.delete();
}
@@ -1337,10 +1310,10 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F
{
try
{
- for(QueueEntry entry : _ackedMessages)
- {
- entry.release();
- }
+ for(MessageInstance entry : _ackedMessages)
+ {
+ entry.release();
+ }
}
finally
{
@@ -1505,7 +1478,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)
{
@@ -1514,36 +1487,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()));
+ }
}
}
@@ -1604,6 +1583,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..47700f812f
--- /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,552 @@
+/*
+ *
+ * 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.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());
+ }
+
+ 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, AMQProtocolSession protocolSession,
+ AMQShortString consumerTag, FieldTable filters,
+ boolean noLocal, 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();
+
+ getConsumer().getSendLock();
+ try
+ {
+ while(!closed && state != State.CLOSED)
+ {
+ closed = updateState(state, State.CLOSED);
+ if(!closed)
+ {
+ state = getState();
+ }
+ }
+ _creditManager.removeListener(this);
+ return closed;
+ }
+ finally
+ {
+ getConsumer().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/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..526bc9b9fe 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,11 @@ 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());
if (!body.getNowait())
{
MethodRegistry methodRegistry = protocolConnection.getMethodRegistry();
@@ -156,14 +160,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..d4bd486a99 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);
@@ -128,7 +132,7 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB
{
@Override
- public void deliverToClient(final Subscription sub, final ServerMessage message, final
+ public void deliverToClient(final Consumer sub, final ServerMessage message, final
InstanceProperties props, final long deliveryTag)
throws AMQException
{
@@ -145,25 +149,32 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB
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.createNoAckTarget(channel,
+ AMQShortString.EMPTY_STRING, null,
+ singleMessageCredit, getDeliveryMethod, getRecordMethod);
}
- queue.registerSubscription(sub,false);
- queue.flushSubscription(sub);
- queue.unregisterSubscription(sub);
+ Consumer sub = queue.addConsumer(target, null, AMQMessage.class, "", options);
+ sub.flush();
+ sub.close();
return(!singleMessageCredit.hasCredit());
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 d4d8c9aaef..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.requeue(deliveryTag);
- }
+ // 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/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..281f7345ff 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
@@ -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);
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..e895f81c44 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
@@ -29,7 +29,7 @@ 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.consumer.Consumer;
import org.apache.qpid.server.util.BrokerTestHelper;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -130,8 +130,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 +143,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);
}
}
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/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_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..a96d951de6 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;
@@ -286,7 +285,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/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..9e0327fe76 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;
@@ -64,11 +65,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 +82,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 +111,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 +173,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 +211,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 +311,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 +322,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 +344,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 +360,46 @@ 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);
}
+
+ _consumer.setNoLocal(noLocal);
+
+
try
{
-
- queue.registerSubscription(_subscription, false);
+ _consumer = _queue.addConsumer(_target,
+ messageFilter == null ? null : new SimpleFilterManager(messageFilter),
+ Message_1_0.class, getEndpoint().getName(), options);
}
catch (AMQException e)
{
@@ -394,12 +422,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 +453,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 +470,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 +518,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS
}
if(_resumeAcceptedTransfers.isEmpty())
{
- _subscription.flowStateChanged();
+ _target.flowStateChanged();
}
}
@@ -531,7 +558,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 +620,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 +630,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 +651,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 +671,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 +705,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 +719,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/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/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/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/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/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