summaryrefslogtreecommitdiff
path: root/java/broker
diff options
context:
space:
mode:
authorKim van der Riet <kpvdr@apache.org>2012-05-04 15:39:19 +0000
committerKim van der Riet <kpvdr@apache.org>2012-05-04 15:39:19 +0000
commit633c33f224f3196f3f9bd80bd2e418d8143fea06 (patch)
tree1391da89470593209466df68c0b40b89c14963b1 /java/broker
parentc73f9286ebff93a6c8dbc29cf05e258c4b55c976 (diff)
downloadqpid-python-633c33f224f3196f3f9bd80bd2e418d8143fea06.tar.gz
QPID-3858: Updated branch - merged from trunk r.1333987
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1334037 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/broker')
-rw-r--r--java/broker/bin/create-example-ssl-stores.bat36
-rwxr-xr-xjava/broker/bin/create-example-ssl-stores.sh38
-rw-r--r--java/broker/build.xml2
-rw-r--r--java/broker/etc/config.xml3
-rw-r--r--java/broker/etc/virtualhosts.xml12
-rwxr-xr-xjava/broker/src/main/java/broker.bnd2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java22
-rw-r--r--java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java74
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java92
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Broker.java147
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Main.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java94
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java13
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java18
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java30
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java53
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeType.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java42
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java42
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java216
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java29
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java16
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/ConfigStore_logmessages.properties3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubject.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java4
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java11
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java522
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Binding.java75
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java38
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java229
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Consumer.java73
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java91
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/IllegalStateTransitionException.java43
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/LifetimePolicy.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Publisher.java25
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Queue.java146
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/State.java30
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java25
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java54
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java2
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java64
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java394
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java449
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java98
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Destination.java28
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java108
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java59
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Link_1_0.java26
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java172
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java100
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingDestination.java35
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java51
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLink_1_0.java305
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingDestination.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java44
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java648
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java446
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java634
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/TxnCoordinatorLink_1_0.java195
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java13
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java38
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java41
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java29
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java50
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java17
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java22
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java223
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java25
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SortedQueue.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java60
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java1
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java18
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java63
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java183
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java (renamed from java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java)46
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java29
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/Event.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/EventListener.java25
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java55
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java185
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java37
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java110
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java146
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java73
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/State.java38
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java151
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/StoreFuture.java40
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java4
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/Transaction.java81
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java13
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java (renamed from java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java)1610
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java40
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java14
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java35
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java24
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java194
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java446
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/AlreadyKnownDtxException.java32
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java35
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java247
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java349
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxException.java44
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxNotSelectedException.java30
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java333
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/IncorrectDtxStateException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/JoinAndResumeDtxException.java32
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/NotAssociatedDtxException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/RollbackOnlyDtxException.java32
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/SuspendAndFailDtxException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/TimeoutDtxException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/UnknownDtxBranchException.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/util/MapJsonSerializer.java69
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java29
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java21
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java259
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java650
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java3
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java52
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java20
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java3
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java57
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java13
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java58
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java4
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java4
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java4
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java5
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java18
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java39
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java5
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java19
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java13
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java5
-rwxr-xr-xjava/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java6
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java117
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java33
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java59
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java20
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java19
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java16
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java5
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java30
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslServerTestCase.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java377
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/EventManagerTest.java72
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java16
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java181
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java4
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java157
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java195
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java98
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java57
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java37
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java4
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java67
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java54
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java7
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/util/MapJsonSerializerTest.java53
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java26
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java84
209 files changed, 12425 insertions, 2979 deletions
diff --git a/java/broker/bin/create-example-ssl-stores.bat b/java/broker/bin/create-example-ssl-stores.bat
deleted file mode 100644
index 5419c098d5..0000000000
--- a/java/broker/bin/create-example-ssl-stores.bat
+++ /dev/null
@@ -1,36 +0,0 @@
-@REM
-@REM Licensed to the Apache Software Foundation (ASF) under one
-@REM or more contributor license agreements. See the NOTICE file
-@REM distributed with this work for additional information
-@REM regarding copyright ownership. The ASF licenses this file
-@REM to you under the Apache License, Version 2.0 (the
-@REM "License"); you may not use this file except in compliance
-@REM with the License. You may obtain a copy of the License at
-@REM
-@REM http://www.apache.org/licenses/LICENSE-2.0
-@REM
-@REM Unless required by applicable law or agreed to in writing,
-@REM software distributed under the License is distributed on an
-@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-@REM KIND, either express or implied. See the License for the
-@REM specific language governing permissions and limitations
-@REM under the License.
-@REM
-
-@REM Create example keystore for broker and trust store for client/management console.
-@REM
-@REM Use generated qpid.keystore as the brokers keystore
-@REM Use generated qpid.truststore as client/consoles truststore
-@REM All passwords have value: password
-
-@REM Create Broker Keystore:
-keytool -genkey -alias qpidBroker -keyalg RSA -validity 365 -keystore qpid.keystore -storepass password -keypass password -dname "CN=hostname, OU=OrgUnit, O=Org, L=City, C=US"
-
-@REM Export Self Signed Cert:
-keytool -export -alias qpidBroker -keystore qpid.keystore -file qpidBroker.cer -storepass password
-
-@REM Import Broker Cert Into MC TrustStore:
-keytool -import -alias qpidBrokerCert -file qpidBroker.cer -keystore qpid.truststore -storepass password -noprompt
-
-@REM Delete the cert
-del qpidBroker.cer \ No newline at end of file
diff --git a/java/broker/bin/create-example-ssl-stores.sh b/java/broker/bin/create-example-ssl-stores.sh
deleted file mode 100755
index bfcb3dfecf..0000000000
--- a/java/broker/bin/create-example-ssl-stores.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Create example keystore for broker and trust store for client/management console.
-#
-# Use generated qpid.keystore as the brokers keystore
-# Use generated qpid.truststore as client/consoles truststore
-# All passwords have value: password
-
-#Create Broker Keystore:
-keytool -genkey -alias qpidBroker -keyalg RSA -validity 365 -keystore qpid.keystore \
--storepass password -keypass password -dname "CN=hostname, OU=OrgUnit, O=Org, L=City, C=US"
-
-#Export Self Signed Cert:
-keytool -export -alias qpidBroker -keystore qpid.keystore -file qpidBroker.cer -storepass password
-
-#Import Broker Cert Into MC TrustStore:
-keytool -import -alias qpidBrokerCert -file qpidBroker.cer -keystore qpid.truststore -storepass password -noprompt
-
-#Delete the cert
-rm qpidBroker.cer
diff --git a/java/broker/build.xml b/java/broker/build.xml
index bb809583ee..9e8bf12f18 100644
--- a/java/broker/build.xml
+++ b/java/broker/build.xml
@@ -19,7 +19,7 @@
-
-->
<project name="AMQ Broker" default="build">
- <property name="module.depends" value="management/common common"/>
+ <property name="module.depends" value="management/common common amqp-1-0-common"/>
<property name="module.test.depends" value="common/test" />
<property name="module.main" value="org.apache.qpid.server.Main"/>
<property name="module.genpom" value="true"/>
diff --git a/java/broker/etc/config.xml b/java/broker/etc/config.xml
index 6839f8cf9f..e1aacd43b5 100644
--- a/java/broker/etc/config.xml
+++ b/java/broker/etc/config.xml
@@ -53,8 +53,7 @@
</jmxport>
<ssl>
<enabled>false</enabled>
- <!-- Update below path to your keystore location, or run the bin/create-example-ssl-stores(.sh|.bat)
- script from within the etc/ folder to generate an example store with self-signed cert -->
+ <!-- Update below path to your keystore location. -->
<keyStorePath>${conf}/qpid.keystore</keyStorePath>
<keyStorePassword>password</keyStorePassword>
</ssl>
diff --git a/java/broker/etc/virtualhosts.xml b/java/broker/etc/virtualhosts.xml
index 4dcdcda6d2..1f7f91de9a 100644
--- a/java/broker/etc/virtualhosts.xml
+++ b/java/broker/etc/virtualhosts.xml
@@ -25,8 +25,8 @@
<name>localhost</name>
<localhost>
<store>
- <class>org.apache.qpid.server.store.MemoryMessageStore</class>
- <!--<class>org.apache.qpid.server.store.DerbyMessageStore</class>
+ <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
+ <!--<factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
<environment-path>${QPID_WORK}/derbystore</environment-path>-->
</store>
@@ -86,8 +86,8 @@
<name>development</name>
<development>
<store>
- <class>org.apache.qpid.server.store.MemoryMessageStore</class>
- <!--<class>org.apache.qpid.server.store.DerbyMessageStore</class>
+ <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
+ <!--<factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
<environment-path>${QPID_WORK}/derbystore</environment-path>-->
</store>
@@ -125,8 +125,8 @@
<name>test</name>
<test>
<store>
- <class>org.apache.qpid.server.store.MemoryMessageStore</class>
- <!--<class>org.apache.qpid.server.store.DerbyMessageStore</class>
+ <factoryclass>org.apache.qpid.server.store.MemoryMessageStoreFactory</factoryclass>
+ <!--<factoryclass>org.apache.qpid.server.store.derby.DerbyMessageStoreFactory</factoryclass>
<environment-path>${QPID_WORK}/derbystore</environment-path>-->
</store>
diff --git a/java/broker/src/main/java/broker.bnd b/java/broker/src/main/java/broker.bnd
index 25b0495a63..fa433848a6 100755
--- a/java/broker/src/main/java/broker.bnd
+++ b/java/broker/src/main/java/broker.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.15.0
+ver: 0.17.0
Bundle-SymbolicName: qpid-broker
Bundle-Version: ${ver}
diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
index 1a098d0446..034a4ae53c 100644
--- a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
@@ -37,6 +37,7 @@ import org.apache.qpid.server.exchange.topic.TopicNormalizer;
import org.apache.qpid.server.exchange.topic.TopicParser;
import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.virtualhost.HouseKeepingTask;
@@ -83,7 +84,8 @@ public class ManagementExchange implements Exchange, QMFService.Listener
private class ManagementQueue implements BaseQueue
{
- private final String NAME_AS_STRING = "##__mgmt_pseudo_queue__##" + UUID.randomUUID().toString();
+ private final UUID QUEUE_ID = UUIDGenerator.generateUUID();
+ private final String NAME_AS_STRING = "##__mgmt_pseudo_queue__##" + QUEUE_ID.toString();
private final AMQShortString NAME_AS_SHORT_STRING = new AMQShortString(NAME_AS_STRING);
public void enqueue(ServerMessage message) throws AMQException
@@ -129,9 +131,10 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return NAME_AS_SHORT_STRING;
}
- public String getResourceName()
+ @Override
+ public UUID getId()
{
- return NAME_AS_STRING;
+ return QUEUE_ID;
}
}
@@ -155,14 +158,14 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return ManagementExchange.class;
}
- public ManagementExchange newInstance(VirtualHost host,
+ public ManagementExchange newInstance(UUID id, VirtualHost host,
AMQShortString name,
boolean durable,
int ticket,
boolean autoDelete) throws AMQException
{
ManagementExchange exch = new ManagementExchange();
- exch.initialise(host, name, durable, ticket, autoDelete);
+ exch.initialise(id, host, name, durable, ticket, autoDelete);
return exch;
}
@@ -183,7 +186,7 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return QPID_MANAGEMENT_TYPE;
}
- public void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
+ public void initialise(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
throws AMQException
{
if(!QPID_MANAGEMENT.equals(name))
@@ -191,7 +194,7 @@ public class ManagementExchange implements Exchange, QMFService.Listener
throw new AMQException("Can't create more than one Management exchange");
}
_virtualHost = host;
- _id = host.getConfigStore().createId();
+ _id = id;
_virtualHost.scheduleHouseKeepingTask(_virtualHost.getBroker().getManagementPublishInterval(), new UpdateTask(_virtualHost));
getConfigStore().addConfiguredObject(this);
getQMFService().addListener(this);
@@ -410,6 +413,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return queues;
}
+ public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue)
+ {
+ return false; //TODO
+ }
+
public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
{
return false; //To change body of implemented methods use File | Settings | File Templates.
diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java
index 4367a04da9..900b722886 100644
--- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java
+++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java
@@ -658,6 +658,11 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return _obj.getStagingThreshold();
}
+ public Boolean getMgmtPublish()
+ {
+ return true;
+ }
+
public Integer getMgmtPubInterval()
{
return _obj.getManagementPublishInterval();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
index 265aa7714e..0f32b98aa8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
@@ -33,11 +33,11 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.ManagementActor;
import org.apache.qpid.server.management.AMQManagedObject;
import org.apache.qpid.server.management.ManagedObject;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.AMQQueueMBean;
import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostImpl;
@@ -49,6 +49,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
/**
* This MBean implements the broker management interface and exposes the
@@ -60,8 +61,6 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
private final QueueRegistry _queueRegistry;
private final ExchangeRegistry _exchangeRegistry;
private final ExchangeFactory _exchangeFactory;
- private final Exchange _defaultExchange;
- private final DurableConfigurationStore _durableConfig;
private final VirtualHostImpl.VirtualHostMBean _virtualHostMBean;
@@ -75,8 +74,6 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
_queueRegistry = virtualHost.getQueueRegistry();
_exchangeRegistry = virtualHost.getExchangeRegistry();
- _defaultExchange = _exchangeRegistry.getDefaultExchange();
- _durableConfig = virtualHost.getDurableConfigurationStore();
_exchangeFactory = virtualHost.getExchangeFactory();
}
@@ -176,12 +173,12 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
Exchange exchange = _exchangeRegistry.getExchange(new AMQShortString(exchangeName));
if (exchange == null)
{
- exchange = _exchangeFactory.createExchange(new AMQShortString(exchangeName), new AMQShortString(type),
- durable, false, 0);
+ exchange = _exchangeFactory.createExchange(new AMQShortString(exchangeName),
+ new AMQShortString(type), durable, false, 0);
_exchangeRegistry.registerExchange(exchange);
if (durable)
{
- _durableConfig.createExchange(exchange);
+ getVirtualHost().getMessageStore().createExchange(exchange);
}
}
else
@@ -249,45 +246,42 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
public void createNewQueue(String queueName, String owner, boolean durable, Map<String,Object> arguments) throws JMException
{
final AMQShortString queueNameAsAMQShortString = new AMQShortString(queueName);
- AMQQueue queue = _queueRegistry.getQueue(queueNameAsAMQShortString);
- if (queue != null)
+ synchronized (_queueRegistry)
{
- throw new JMException("The queue \"" + queueName + "\" already exists.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- AMQShortString ownerShortString = null;
- if (owner != null)
+ AMQQueue queue = _queueRegistry.getQueue(queueNameAsAMQShortString);
+ if (queue != null)
{
- ownerShortString = new AMQShortString(owner);
+ throw new JMException("The queue \"" + queueName + "\" already exists.");
}
- FieldTable args = null;
- if(arguments != null)
+ CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
+ try
{
- args = FieldTable.convertToFieldTable(arguments);
- }
- final VirtualHost virtualHost = getVirtualHost();
+ FieldTable args = null;
+ if(arguments != null)
+ {
+ args = FieldTable.convertToFieldTable(arguments);
+ }
+ final VirtualHost virtualHost = getVirtualHost();
+
+ queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), queueName, durable, owner,
+ false, false, getVirtualHost(), arguments);
+ if (queue.isDurable() && !queue.isAutoDelete())
+ {
+ getVirtualHost().getMessageStore().createQueue(queue, args);
+ }
- queue = AMQQueueFactory.createAMQQueueImpl(queueNameAsAMQShortString, durable, ownerShortString,
- false, false, getVirtualHost(), args);
- if (queue.isDurable() && !queue.isAutoDelete())
+ virtualHost.getBindingFactory().addBinding(queueName, queue, _exchangeRegistry.getDefaultExchange(), null);
+ }
+ catch (AMQException ex)
{
- _durableConfig.createQueue(queue, args);
+ JMException jme = new JMException(ex.toString());
+ throw new MBeanException(jme, "Error in creating queue " + queueName);
+ }
+ finally
+ {
+ CurrentActor.remove();
}
-
- virtualHost.getBindingFactory().addBinding(queueName, queue, _defaultExchange, null);
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error in creating queue " + queueName);
- }
- finally
- {
- CurrentActor.remove();
}
}
@@ -317,7 +311,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
queue.delete();
if (queue.isDurable())
{
- _durableConfig.removeQueue(queue);
+ getVirtualHost().getMessageStore().removeQueue(queue);
}
}
catch (AMQException ex)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
index e5e755bd23..8198cec821 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -82,11 +83,13 @@ import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.registry.ApplicationRegistry;
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.subscription.SubscriptionFactoryImpl;
+import org.apache.qpid.server.subscription.SubscriptionImpl;
import org.apache.qpid.server.txn.AsyncAutoCommitTransaction;
import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
@@ -273,7 +276,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
{
throw new AMQSecurityException("Permission denied: " + e.getName());
}
- _currentMessage = new IncomingMessage(info);
+ _currentMessage = new IncomingMessage(info, getProtocolSession().getReference());
_currentMessage.setExchange(e);
}
@@ -295,26 +298,9 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
_currentMessage.setExpiration();
+ _currentMessage.headersReceived(getProtocolSession().getLastReceivedTime());
- MessageMetaData mmd = _currentMessage.headersReceived(getProtocolSession().getLastReceivedTime());
- final StoredMessage<MessageMetaData> handle = _messageStore.addMessage(mmd);
- _currentMessage.setStoredMessage(handle);
-
- routeCurrentMessage();
-
-
- _transaction.addPostTransactionAction(new ServerTransaction.Action()
- {
-
- public void postCommit()
- {
- }
-
- public void onRollback()
- {
- handle.remove();
- }
- });
+ _currentMessage.route();
deliverCurrentMessageIfComplete();
}
@@ -346,17 +332,41 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
{
_actor.message(ExchangeMessages.DISCARDMSG(_currentMessage.getExchange().asString(), _currentMessage.getRoutingKey()));
}
-
}
else
{
+ final StoredMessage<MessageMetaData> handle = _messageStore.addMessage(_currentMessage.getMessageMetaData());
+ _currentMessage.setStoredMessage(handle);
+ int bodyCount = _currentMessage.getBodyCount();
+ if(bodyCount > 0)
+ {
+ long bodyLengthReceived = 0;
+ for(int i = 0 ; i < bodyCount ; i++)
+ {
+ ContentChunk contentChunk = _currentMessage.getContentChunk(i);
+ handle.addContent((int)bodyLengthReceived, ByteBuffer.wrap(contentChunk.getData()));
+ bodyLengthReceived += contentChunk.getSize();
+ }
+ }
+
+ _transaction.addPostTransactionAction(new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ }
+
+ public void onRollback()
+ {
+ handle.remove();
+ }
+ });
+
_transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues), getProtocolSession().getLastReceivedTime());
incrementOutstandingTxnsIfNecessary();
- updateTransactionalActivity();
+ updateTransactionalActivity();
+ _currentMessage.getStoredMessage().flushToStore();
}
}
- _currentMessage.getStoredMessage().flushToStore();
-
}
finally
{
@@ -383,9 +393,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
try
{
-
- // returns true iff the message was delivered (i.e. if all data was
- // received
final ContentChunk contentChunk =
_session.getMethodRegistry().getProtocolVersionMethodConverter().convertToContentChunk(contentBody);
@@ -409,11 +416,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
}
}
- protected void routeCurrentMessage() throws AMQException
- {
- _currentMessage.route();
- }
-
public long getNextDeliveryTag()
{
return ++_deliveryTag;
@@ -1123,11 +1125,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
}
- public Object getID()
- {
- return _channelId;
- }
-
public AMQConnectionModel getConnectionModel()
{
return _session;
@@ -1377,7 +1374,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
{
if(_blockingQueues.remove(queue))
{
- if(_blocking.compareAndSet(true,false))
+ if(_blocking.compareAndSet(true,false) && !isClosing())
{
_actor.message(_logSubject, ChannelMessages.FLOW_REMOVED());
@@ -1386,6 +1383,16 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
}
}
+ public boolean onSameConnection(InboundMessage inbound)
+ {
+ if(inbound instanceof IncomingMessage)
+ {
+ IncomingMessage incoming = (IncomingMessage) inbound;
+ return getProtocolSession().getReference() == incoming.getConnectionReference();
+ }
+ return false;
+ }
+
private void flow(boolean flow)
{
MethodRegistry methodRegistry = _session.getMethodRegistry();
@@ -1551,7 +1558,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
}
}
- public void recordFuture(final MessageStore.StoreFuture future, final ServerTransaction.Action action)
+ public void recordFuture(final StoreFuture future, final ServerTransaction.Action action)
{
_unfinishedCommandsQueue.add(new AsyncCommand(future, action));
}
@@ -1585,10 +1592,10 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
private static class AsyncCommand
{
- private final MessageStore.StoreFuture _future;
+ private final StoreFuture _future;
private ServerTransaction.Action _action;
- public AsyncCommand(final MessageStore.StoreFuture future, final ServerTransaction.Action action)
+ public AsyncCommand(final StoreFuture future, final ServerTransaction.Action action)
{
_future = future;
_action = action;
@@ -1615,9 +1622,8 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
}
}
- @Override
public int compareTo(AMQSessionModel session)
{
- return getId().toString().compareTo(session.getID().toString());
+ return getId().compareTo(session.getId());
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/java/broker/src/main/java/org/apache/qpid/server/Broker.java
index 072f8dc132..5004d320c2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/Broker.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/Broker.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server;
+import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.QpidLog4JConfigurator;
@@ -52,15 +53,24 @@ import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.EnumSet;
+import java.util.Formatter;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.FileHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
public class Broker
{
+ private static final Logger LOGGER = Logger.getLogger(Broker.class);
+
private static final int IPV4_ADDRESS_LENGTH = 4;
private static final char IPV4_LITERAL_SEPARATOR = '.';
+ private volatile Thread _shutdownHookThread;
protected static class InitException extends RuntimeException
{
@@ -74,7 +84,14 @@ public class Broker
public void shutdown()
{
- ApplicationRegistry.remove();
+ try
+ {
+ removeShutdownHook();
+ }
+ finally
+ {
+ ApplicationRegistry.remove();
+ }
}
public void startup() throws Exception
@@ -88,6 +105,7 @@ public class Broker
{
CurrentActor.set(new BrokerActor(new SystemOutMessageLogger()));
startupImpl(options);
+ addShutdownHook();
}
finally
{
@@ -147,6 +165,12 @@ public class Broker
parsePortList(sslPorts, serverConfig.getSSLPorts());
}
+ Set<Integer> exclude_1_0 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v1_0));
+ if(exclude_1_0.isEmpty())
+ {
+ parsePortList(exclude_1_0, serverConfig.getPortExclude10());
+ }
+
Set<Integer> exclude_0_10 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_10));
if(exclude_0_10.isEmpty())
{
@@ -177,14 +201,14 @@ public class Broker
bindAddr = serverConfig.getBind();
}
- InetAddress bindAddress = null;
+ InetAddress bindAddress;
if (bindAddr.equals(WILDCARD_ADDRESS))
{
- bindAddress = new InetSocketAddress(0).getAddress();
+ bindAddress = null;
}
else
{
- bindAddress = InetAddress.getByAddress(parseIP(bindAddr));
+ bindAddress = InetAddress.getByName(bindAddr);
}
final AmqpProtocolVersion defaultSupportedProtocolReply = serverConfig.getDefaultSupportedProtocolReply();
@@ -193,18 +217,22 @@ public class Broker
{
for(int port : ports)
{
+ final InetSocketAddress inetSocketAddress = new InetSocketAddress(bindAddress, port);
+
final Set<AmqpProtocolVersion> supported =
- getSupportedVersions(port, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8, serverConfig);
+ getSupportedVersions(port, exclude_1_0, exclude_0_10, exclude_0_9_1, exclude_0_9,
+ exclude_0_8, serverConfig);
final NetworkTransportConfiguration settings =
- new ServerNetworkTransportConfiguration(serverConfig, port, bindAddress.getHostName(), Transport.TCP);
+ new ServerNetworkTransportConfiguration(serverConfig, inetSocketAddress, Transport.TCP);
final IncomingNetworkTransport transport = Transport.getIncomingTransportInstance();
final MultiVersionProtocolEngineFactory protocolEngineFactory =
new MultiVersionProtocolEngineFactory(supported, defaultSupportedProtocolReply);
transport.accept(settings, protocolEngineFactory, null);
- ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port),
+
+ ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress,
new QpidAcceptor(transport,"TCP"));
CurrentActor.get().message(BrokerMessages.LISTENING("TCP", port));
}
@@ -219,17 +247,21 @@ public class Broker
for(int sslPort : sslPorts)
{
+ final InetSocketAddress inetSocketAddress = new InetSocketAddress(bindAddress, sslPort);
+
final Set<AmqpProtocolVersion> supported =
- getSupportedVersions(sslPort, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8, serverConfig);
+ getSupportedVersions(sslPort, exclude_1_0, exclude_0_10, exclude_0_9_1,
+ exclude_0_9, exclude_0_8, serverConfig);
final NetworkTransportConfiguration settings =
- new ServerNetworkTransportConfiguration(serverConfig, sslPort, bindAddress.getHostName(), Transport.TCP);
+ new ServerNetworkTransportConfiguration(serverConfig, inetSocketAddress, Transport.TCP);
final IncomingNetworkTransport transport = Transport.getIncomingTransportInstance();
final MultiVersionProtocolEngineFactory protocolEngineFactory =
new MultiVersionProtocolEngineFactory(supported, defaultSupportedProtocolReply);
transport.accept(settings, protocolEngineFactory, sslContext);
- ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, sslPort),
+
+ ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress,
new QpidAcceptor(transport,"TCP"));
CurrentActor.get().message(BrokerMessages.LISTENING("TCP/SSL", sslPort));
}
@@ -244,13 +276,20 @@ public class Broker
}
}
- private static Set<AmqpProtocolVersion> getSupportedVersions(final int port, final Set<Integer> exclude_0_10,
- final Set<Integer> exclude_0_9_1, final Set<Integer> exclude_0_9,
- final Set<Integer> exclude_0_8,
- final ServerConfiguration serverConfig)
+ private static Set<AmqpProtocolVersion> getSupportedVersions(final int port,
+ final Set<Integer> exclude_1_0,
+ final Set<Integer> exclude_0_10,
+ final Set<Integer> exclude_0_9_1,
+ final Set<Integer> exclude_0_9,
+ final Set<Integer> exclude_0_8,
+ final ServerConfiguration serverConfig)
{
final EnumSet<AmqpProtocolVersion> supported = EnumSet.allOf(AmqpProtocolVersion.class);
+ if(exclude_1_0.contains(port) || !serverConfig.isAmqp10enabled())
+ {
+ supported.remove(AmqpProtocolVersion.v1_0_0);
+ }
if(exclude_0_10.contains(port) || !serverConfig.isAmqp010enabled())
{
supported.remove(AmqpProtocolVersion.v0_10);
@@ -349,34 +388,6 @@ public class Broker
}
}
- private byte[] parseIP(String address) throws Exception
- {
- char[] literalBuffer = address.toCharArray();
- int byteCount = 0;
- int currByte = 0;
- byte[] ip = new byte[IPV4_ADDRESS_LENGTH];
- for (int i = 0; i < literalBuffer.length; i++)
- {
- char currChar = literalBuffer[i];
- if ((currChar >= '0') && (currChar <= '9'))
- {
- currByte = (currByte * 10) + (Character.digit(currChar, 10) & 0xFF);
- }
-
- if (currChar == IPV4_LITERAL_SEPARATOR || (i + 1 == literalBuffer.length))
- {
- ip[byteCount++] = (byte) currByte;
- currByte = 0;
- }
- }
-
- if (byteCount != 4)
- {
- throw new Exception("Invalid IP address: " + address);
- }
- return ip;
- }
-
private void configureLogging(File logConfigFile, long logWatchTime) throws InitException, IOException
{
if (logConfigFile.exists() && logConfigFile.canRead())
@@ -441,4 +452,56 @@ public class Broker
blm.register();
}
+
+ private void addShutdownHook()
+ {
+ Thread shutdownHookThread = new Thread(new ShutdownService());
+ shutdownHookThread.setName("QpidBrokerShutdownHook");
+
+ Runtime.getRuntime().addShutdownHook(shutdownHookThread);
+ _shutdownHookThread = shutdownHookThread;
+
+ LOGGER.debug("Added shutdown hook");
+ }
+
+ private void removeShutdownHook()
+ {
+ Thread shutdownThread = _shutdownHookThread;
+
+ //if there is a shutdown thread and we aren't it, we should remove it
+ if(shutdownThread != null && !(Thread.currentThread() == shutdownThread))
+ {
+ LOGGER.debug("Removing shutdown hook");
+
+ _shutdownHookThread = null;
+
+ boolean removed = false;
+ try
+ {
+ removed = Runtime.getRuntime().removeShutdownHook(shutdownThread);
+ }
+ catch(IllegalStateException ise)
+ {
+ //ignore, means the JVM is already shutting down
+ }
+
+ if(LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Removed shutdown hook: " + removed);
+ }
+ }
+ else
+ {
+ LOGGER.debug("Skipping shutdown hook removal as there either isnt one, or we are it.");
+ }
+ }
+
+ private class ShutdownService implements Runnable
+ {
+ public void run()
+ {
+ LOGGER.debug("Shutdown hook running");
+ Broker.this.shutdown();
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java b/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
index 1f96a24701..d871c724fd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
@@ -47,7 +47,6 @@ public class BrokerOptions
private Integer _logWatchFrequency = 0;
-
public void addPort(final int port)
{
_ports.add(port);
@@ -107,7 +106,6 @@ public class BrokerOptions
{
_jmxPortConnectorServer = jmxPortConnectorServer;
}
-
public String getQpidHome()
{
return System.getProperty(QPID_HOME);
@@ -163,5 +161,4 @@ public class BrokerOptions
{
_bundleContext = bundleContext;
}
-
} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/Main.java b/java/broker/src/main/java/org/apache/qpid/server/Main.java
index 5fcd8a7b52..70fa414e3c 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/Main.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/Main.java
@@ -59,6 +59,12 @@ public class Main
.withDescription("SSL port. Overrides any value in the config file")
.withLongOpt("sslport").create("s");
+
+ private static final Option OPTION_EXCLUDE_1_0 =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP1-0 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-1-0").create();
+
private static final Option OPTION_EXCLUDE_0_10 =
OptionBuilder.withArgName("port").hasArg()
.withDescription("when listening on the specified port do not accept AMQP0-10 connections. The specified port must be one specified on the command line")
@@ -116,6 +122,7 @@ public class Main
OPTIONS.addOption(OPTION_LOG_WATCH);
OPTIONS.addOption(OPTION_PORT);
OPTIONS.addOption(OPTION_SSLPORT);
+ OPTIONS.addOption(OPTION_EXCLUDE_1_0);
OPTIONS.addOption(OPTION_EXCLUDE_0_10);
OPTIONS.addOption(OPTION_EXCLUDE_0_9_1);
OPTIONS.addOption(OPTION_EXCLUDE_0_9);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java b/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java
index 22d97d36dd..fe6e32173f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java
@@ -28,7 +28,8 @@ public enum ProtocolExclusion
v0_8("exclude-0-8","--exclude-0-8"),
v0_9("exclude-0-9", "--exclude-0-9"),
v0_9_1("exclude-0-9-1", "--exclude-0-9-1"),
- v0_10("exclude-0-10", "--exclude-0-10");
+ v0_10("exclude-0-10", "--exclude-0-10"),
+ v1_0("exclude-1-0", "--exclude-1-0");
private static final Map<String, ProtocolExclusion> MAP = new HashMap<String,ProtocolExclusion>();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java
index 8e44da095a..2efd4cee26 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java
@@ -117,7 +117,7 @@ public class Binding
public String toString()
{
- return "Binding{bindingKey="+_bindingKey+", exchange="+_exchange+", queue="+_queue+"}";
+ return "Binding{bindingKey="+_bindingKey+", exchange="+_exchange+", queue="+_queue+", id= " + _id + " }";
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java
index fe66a6d341..abf252c733 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java
@@ -24,7 +24,6 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.AMQInternalException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.configuration.BindingConfig;
import org.apache.qpid.server.configuration.BindingConfigType;
import org.apache.qpid.server.configuration.ConfigStore;
@@ -33,58 +32,35 @@ import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.BindingMessages;
import org.apache.qpid.server.logging.subjects.BindingLogSubject;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collections;
import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class BindingFactory
{
private final VirtualHost _virtualHost;
- private final DurableConfigurationStore.Source _configSource;
- private final Exchange _defaultExchange;
private final ConcurrentHashMap<BindingImpl, BindingImpl> _bindings = new ConcurrentHashMap<BindingImpl, BindingImpl>();
-
public BindingFactory(final VirtualHost vhost)
{
- this(vhost, vhost.getExchangeRegistry().getDefaultExchange());
+ _virtualHost = vhost;
}
- public BindingFactory(final DurableConfigurationStore.Source configSource, final Exchange defaultExchange)
- {
- _configSource = configSource;
- _defaultExchange = defaultExchange;
- if (configSource instanceof VirtualHost)
- {
- _virtualHost = (VirtualHost) configSource;
- }
- else
- {
- _virtualHost = null;
- }
- }
-
- public VirtualHost getVirtualHost()
- {
- return _virtualHost;
- }
-
-
-
private final class BindingImpl extends Binding implements AMQQueue.Task, Exchange.Task, BindingConfig
{
private final BindingLogSubject _logSubject;
//TODO : persist creation time
private long _createTime = System.currentTimeMillis();
- private BindingImpl(String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments)
+ private BindingImpl(UUID id, String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments)
{
- super(queue.getVirtualHost().getConfigStore().createId(), bindingKey, queue, exchange, arguments);
+ super(id, bindingKey, queue, exchange, arguments);
_logSubject = new BindingLogSubject(bindingKey,exchange,queue);
}
@@ -141,48 +117,59 @@ public class BindingFactory
public boolean addBinding(String bindingKey, AMQQueue queue, Exchange exchange, Map<String, Object> arguments) throws AMQSecurityException, AMQInternalException
{
- return makeBinding(bindingKey, queue, exchange, arguments, false, false);
+ return makeBinding(null, bindingKey, queue, exchange, arguments, false, false);
}
- public boolean replaceBinding(final String bindingKey,
+ public boolean replaceBinding(final UUID id, final String bindingKey,
final AMQQueue queue,
final Exchange exchange,
final Map<String, Object> arguments) throws AMQSecurityException, AMQInternalException
{
- return makeBinding(bindingKey, queue, exchange, arguments, false, true);
+ return makeBinding(id, bindingKey, queue, exchange, arguments, false, true);
}
- private boolean makeBinding(String bindingKey, AMQQueue queue, Exchange exchange, Map<String, Object> arguments, boolean restore, boolean force) throws AMQSecurityException, AMQInternalException
+ private boolean makeBinding(UUID id, String bindingKey, AMQQueue queue, Exchange exchange, Map<String, Object> arguments, boolean restore, boolean force) throws AMQSecurityException, AMQInternalException
{
assert queue != null;
+ final Exchange defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange();
+
if (bindingKey == null)
{
bindingKey = "";
}
if (exchange == null)
{
- exchange = _defaultExchange;
+ exchange = defaultExchange;
}
if (arguments == null)
{
arguments = Collections.emptyMap();
}
+ if (exchange == null)
+ {
+ throw new IllegalArgumentException("exchange cannot be null");
+ }
+
// The default exchange bindings must reflect the existence of queues, allow
// all operations on it to succeed. It is up to the broker to prevent illegal
// attempts at binding to this exchange, not the ACLs.
- if(exchange != _defaultExchange)
+ if(exchange != defaultExchange)
{
//Perform ACLs
- if (!getVirtualHost().getSecurityManager().authoriseBind(exchange, queue, new AMQShortString(bindingKey)))
+ if (!_virtualHost.getSecurityManager().authoriseBind(exchange, queue, new AMQShortString(bindingKey)))
{
throw new AMQSecurityException("Permission denied: binding " + bindingKey);
}
}
-
- BindingImpl b = new BindingImpl(bindingKey,queue,exchange,arguments);
- BindingImpl existingMapping = _bindings.putIfAbsent(b,b);
+
+ if (id == null)
+ {
+ id = UUIDGenerator.generateUUID();
+ }
+ BindingImpl b = new BindingImpl(id, bindingKey, queue, exchange, arguments);
+ BindingImpl existingMapping = _bindings.putIfAbsent(b, b);
if (existingMapping == null || force)
{
if (existingMapping != null)
@@ -192,7 +179,7 @@ public class BindingFactory
if (b.isDurable() && !restore)
{
- _configSource.getDurableConfigurationStore().bindQueue(exchange,new AMQShortString(bindingKey),queue,FieldTable.convertToFieldTable(arguments));
+ _virtualHost.getMessageStore().bindQueue(b);
}
queue.addQueueDeleteTask(b);
@@ -212,12 +199,12 @@ public class BindingFactory
private ConfigStore getConfigStore()
{
- return getVirtualHost().getConfigStore();
+ return _virtualHost.getConfigStore();
}
- public void restoreBinding(final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> argumentMap) throws AMQSecurityException, AMQInternalException
+ public void restoreBinding(final UUID id, final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> argumentMap) throws AMQSecurityException, AMQInternalException
{
- makeBinding(bindingKey,queue,exchange,argumentMap,true, false);
+ makeBinding(id, bindingKey,queue,exchange,argumentMap,true, false);
}
public void removeBinding(final Binding b) throws AMQSecurityException, AMQInternalException
@@ -229,13 +216,15 @@ public class BindingFactory
public Binding removeBinding(String bindingKey, AMQQueue queue, Exchange exchange, Map<String, Object> arguments) throws AMQSecurityException, AMQInternalException
{
assert queue != null;
+ final Exchange defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange();
+
if (bindingKey == null)
{
bindingKey = "";
}
if (exchange == null)
{
- exchange = _defaultExchange;
+ exchange = defaultExchange;
}
if (arguments == null)
{
@@ -245,16 +234,16 @@ public class BindingFactory
// The default exchange bindings must reflect the existence of queues, allow
// all operations on it to succeed. It is up to the broker to prevent illegal
// attempts at binding to this exchange, not the ACLs.
- if(exchange != _defaultExchange)
+ if(exchange != defaultExchange)
{
// Check access
- if (!getVirtualHost().getSecurityManager().authoriseUnbind(exchange, new AMQShortString(bindingKey), queue))
+ if (!_virtualHost.getSecurityManager().authoriseUnbind(exchange, new AMQShortString(bindingKey), queue))
{
throw new AMQSecurityException("Permission denied: unbinding " + bindingKey);
}
}
- BindingImpl b = _bindings.remove(new BindingImpl(bindingKey,queue,exchange,arguments));
+ BindingImpl b = _bindings.remove(new BindingImpl(null, bindingKey,queue,exchange,arguments));
if (b != null)
{
@@ -265,10 +254,7 @@ public class BindingFactory
if (b.isDurable())
{
- _configSource.getDurableConfigurationStore().unbindQueue(exchange,
- new AMQShortString(bindingKey),
- queue,
- FieldTable.convertToFieldTable(arguments));
+ _virtualHost.getMessageStore().unbindQueue(b);
}
b.logDestruction();
getConfigStore().removeConfiguredObject(b);
@@ -280,20 +266,22 @@ public class BindingFactory
public Binding getBinding(String bindingKey, AMQQueue queue, Exchange exchange, Map<String, Object> arguments)
{
assert queue != null;
+ final Exchange defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange();
+
if(bindingKey == null)
{
bindingKey = "";
}
if(exchange == null)
{
- exchange = _defaultExchange;
+ exchange = defaultExchange;
}
if(arguments == null)
{
arguments = Collections.emptyMap();
}
- BindingImpl b = new BindingImpl(bindingKey,queue,exchange,arguments);
+ BindingImpl b = new BindingImpl(null, bindingKey,queue,exchange,arguments);
return _bindings.get(b);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
index 259902a938..46027d02c6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
@@ -88,6 +88,7 @@ public class ServerConfiguration extends ConfigurationPlugin
public static final String MGMT_JMXPORT_CONNECTORSERVER = "management.jmxport.connectorServer";
public static final String STATUS_UPDATES = "status-updates";
public static final String ADVANCED_LOCALE = "advanced.locale";
+ public static final String CONNECTOR_AMQP10ENABLED = "connector.amqp10enabled";
public static final String CONNECTOR_AMQP010ENABLED = "connector.amqp010enabled";
public static final String CONNECTOR_AMQP091ENABLED = "connector.amqp091enabled";
public static final String CONNECTOR_AMQP09ENABLED = "connector.amqp09enabled";
@@ -667,6 +668,11 @@ public class ServerConfiguration extends ConfigurationPlugin
return getListValue("connector.port", Collections.<Integer>singletonList(DEFAULT_PORT));
}
+ public List getPortExclude10()
+ {
+ return getListValue("connector.non10port");
+ }
+
public List getPortExclude010()
{
return getListValue("connector.non010port");
@@ -737,7 +743,7 @@ public class ServerConfiguration extends ConfigurationPlugin
public String getConnectorKeyManagerFactoryAlgorithm()
{
final String systemFallback = KeyManagerFactory.getDefaultAlgorithm();
- // deprecated, pre-0.15 brokers supported this name.
+ // deprecated, pre-0.17 brokers supported this name.
final String fallback = getStringValue("connector.ssl.certType", systemFallback);
return getStringValue("connector.ssl.keyManagerFactoryAlgorithm", fallback);
}
@@ -843,6 +849,11 @@ public class ServerConfiguration extends ConfigurationPlugin
return getConfig().getString("deadLetterQueueSuffix", AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX);
}
+ public boolean isAmqp10enabled()
+ {
+ return getConfig().getBoolean(CONNECTOR_AMQP10ENABLED, true);
+ }
+
public boolean isAmqp010enabled()
{
return getConfig().getBoolean(CONNECTOR_AMQP010ENABLED, true);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
index 81dfcb4465..f6fe47b996 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
@@ -19,22 +19,21 @@
*/
package org.apache.qpid.server.configuration;
+import java.net.InetSocketAddress;
import org.apache.qpid.transport.NetworkTransportConfiguration;
public class ServerNetworkTransportConfiguration implements NetworkTransportConfiguration
{
private final ServerConfiguration _serverConfig;
- private final int _port;
- private final String _host;
private final String _transport;
+ private InetSocketAddress _address;
public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig,
- final int port, final String host,
+ final InetSocketAddress address,
final String transport)
{
_serverConfig = serverConfig;
- _port = port;
- _host = host;
+ _address = address;
_transport = transport;
}
@@ -55,12 +54,12 @@ public class ServerNetworkTransportConfiguration implements NetworkTransportConf
public Integer getPort()
{
- return _port;
+ return _address.getPort();
}
public String getHost()
{
- return _host;
+ return _address.getHostName();
}
public String getTransport()
@@ -72,4 +71,9 @@ public class ServerNetworkTransportConfiguration implements NetworkTransportConf
{
return _serverConfig.getConnectorProcessors();
}
+
+ public InetSocketAddress getAddress()
+ {
+ return _address;
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java
index 9256724c56..b96ddc56c6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java
@@ -29,6 +29,4 @@ public interface VirtualHostConfig extends ConfiguredObject<VirtualHostConfigTyp
String getFederationTag();
- void setBroker(BrokerConfig brokerConfig);
-
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
index 5fd261a081..5f472b6ddd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
@@ -32,6 +32,7 @@ import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.MemoryMessageStore;
+import org.apache.qpid.server.store.MemoryMessageStoreFactory;
import java.util.ArrayList;
import java.util.Arrays;
@@ -42,9 +43,9 @@ import java.util.Map;
public class VirtualHostConfiguration extends ConfigurationPlugin
{
- private String _name;
- private Map<String, QueueConfiguration> _queues = new HashMap<String, QueueConfiguration>();
- private Map<String, ExchangeConfiguration> _exchanges = new HashMap<String, ExchangeConfiguration>();
+ private final String _name;
+ private final Map<String, QueueConfiguration> _queues = new HashMap<String, QueueConfiguration>();
+ private final Map<String, ExchangeConfiguration> _exchanges = new HashMap<String, ExchangeConfiguration>();
public VirtualHostConfiguration(String name, Configuration config) throws ConfigurationException
{
@@ -92,11 +93,6 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
return getLongValue("housekeeping.checkPeriod", ApplicationRegistry.getInstance().getConfiguration().getHousekeepingCheckPeriod());
}
- public String getAuthenticationDatabase()
- {
- return getStringValue("security.authentication.name");
- }
-
public List getCustomExchanges()
{
return getListValue("custom-exchanges.class-name");
@@ -107,14 +103,14 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
return getConfig().subset("store");
}
- public String getMessageStoreClass()
+ public String getMessageStoreFactoryClass()
{
- return getStringValue("store.class", MemoryMessageStore.class.getName());
+ return getStringValue("store.factoryclass", MemoryMessageStoreFactory.class.getName());
}
- public void setMessageStoreClass(String storeClass)
+ public void setMessageStoreFactoryClass(String storeFactoryClass)
{
- getConfig().setProperty("store.class", storeClass);
+ getConfig().setProperty("store.factoryclass", storeFactoryClass);
}
public List getExchanges()
@@ -253,16 +249,6 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
return queueConfig;
}
- public long getMemoryUsageMaximum()
- {
- return getLongValue("queues.maximumMemoryUsage");
- }
-
- public long getMemoryUsageMinimum()
- {
- return getLongValue("queues.minimumMemoryUsage");
- }
-
public int getMaximumMessageAge()
{
return getIntValue("queues.maximumMessageAge");
diff --git a/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
index 9159489299..4a58314f51 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
@@ -46,11 +46,19 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable
/** Close all of the currently open connections. */
public void close()
{
- _logger.debug("Closing connection registry :" + _registry.size() + " connections.");
+ close(IConnectionRegistry.BROKER_SHUTDOWN_REPLY_TEXT);
+ }
+
+ public void close(final String replyText)
+ {
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Closing connection registry :" + _registry.size() + " connections.");
+ }
while (!_registry.isEmpty())
{
AMQConnectionModel connection = _registry.get(0);
- closeConnection(connection, AMQConstant.CONNECTION_FORCED, "Broker is shutting down");
+ closeConnection(connection, AMQConstant.CONNECTION_FORCED, replyText);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java
index 89582e5748..954c448b72 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java
@@ -28,12 +28,17 @@ import java.util.List;
public interface IConnectionRegistry
{
+ public static final String BROKER_SHUTDOWN_REPLY_TEXT = "Broker is shutting down";
+ public static final String VHOST_PASSIVATE_REPLY_TEXT = "Virtual host is being passivated";
+
public void initialise();
public void close() throws AMQException;
-
+
+ public void close(String replyText) throws AMQException;
+
public void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message);
-
+
public List<AMQConnectionModel> getConnections();
public void registerConnection(AMQConnectionModel connnection);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index cae07046fa..9493f400f2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -20,8 +20,6 @@
*/
package org.apache.qpid.server.exchange;
-import org.apache.log4j.Logger;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.binding.Binding;
@@ -116,7 +114,7 @@ public abstract class AbstractExchange implements Exchange, Managable
*/
protected abstract AbstractExchangeMBean createMBean() throws JMException;
- public void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
+ public void initialise(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
throws AMQException
{
_virtualHost = host;
@@ -125,10 +123,18 @@ public abstract class AbstractExchange implements Exchange, Managable
_autoDelete = autoDelete;
_ticket = ticket;
- // TODO - fix
- _id = getConfigStore().createId();
+ _id = id;
getConfigStore().addConfiguredObject(this);
+ createAndRegisterMBean();
+ _logSubject = new ExchangeLogSubject(this, this.getVirtualHost());
+
+ // Log Exchange creation
+ CurrentActor.get().message(ExchangeMessages.CREATED(String.valueOf(getTypeShortString()), String.valueOf(name), durable));
+ }
+
+ private void createAndRegisterMBean()
+ {
try
{
_exchangeMbean = createMBean();
@@ -136,12 +142,8 @@ public abstract class AbstractExchange implements Exchange, Managable
}
catch (JMException e)
{
- getLogger().error(e);
+ throw new RuntimeException("Failed to register mbean",e);
}
- _logSubject = new ExchangeLogSubject(this, this.getVirtualHost());
-
- // Log Exchange creation
- CurrentActor.get().message(ExchangeMessages.CREATED(String.valueOf(getTypeShortString()), String.valueOf(name), durable));
}
public ConfigStore getConfigStore()
@@ -149,8 +151,6 @@ public abstract class AbstractExchange implements Exchange, Managable
return getVirtualHost().getConfigStore();
}
- public abstract Logger getLogger();
-
public boolean isDurable()
{
return _durable;
@@ -324,8 +324,7 @@ public abstract class AbstractExchange implements Exchange, Managable
public Map<String, Object> getArguments()
{
- // TODO - Fix
- return Collections.EMPTY_MAP;
+ return Collections.emptyMap();
}
public UUID getId()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java
index 153419de1b..5058f91995 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java
@@ -25,9 +25,11 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.AMQUnknownExchangeType;
+import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.qmf.ManagementExchange;
import org.apache.qpid.server.configuration.VirtualHostConfiguration;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -35,6 +37,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import java.util.UUID;
public class DefaultExchangeFactory implements ExchangeFactory
{
@@ -76,17 +79,29 @@ public class DefaultExchangeFactory implements ExchangeFactory
return publicTypes;
}
-
-
public Exchange createExchange(String exchange, String type, boolean durable, boolean autoDelete)
- throws AMQException
+ throws AMQException
{
return createExchange(new AMQShortString(exchange), new AMQShortString(type), durable, autoDelete, 0);
}
- public Exchange createExchange(AMQShortString exchange, AMQShortString type, boolean durable, boolean autoDelete,
- int ticket)
+ public Exchange createExchange(UUID id, String exchange, String type, boolean durable, boolean autoDelete)
+ throws AMQException
+ {
+ return createExchange(id, new AMQShortString(exchange), new AMQShortString(type), durable, autoDelete, 0);
+ }
+
+ public Exchange createExchange(AMQShortString exchange, AMQShortString type, boolean durable,
+ boolean autoDelete, int ticket)
+ throws AMQException
+ {
+ UUID id = UUIDGenerator.generateExchangeUUID(exchange.asString(), _host.getName());
+ return createExchange(id, exchange, type, durable, autoDelete, ticket);
+ }
+
+ public Exchange createExchange(UUID id, AMQShortString exchange, AMQShortString type, boolean durable,
+ boolean autoDelete, int ticket)
throws AMQException
{
// Check access
@@ -102,7 +117,7 @@ public class DefaultExchangeFactory implements ExchangeFactory
throw new AMQUnknownExchangeType("Unknown exchange type: " + type,null);
}
- Exchange e = exchType.newInstance(_host, exchange, durable, ticket, autoDelete);
+ Exchange e = exchType.newInstance(id, _host, exchange, durable, ticket, autoDelete);
return e;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
index a5fa9f014e..bf4184bf0b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
@@ -21,7 +21,6 @@
package org.apache.qpid.server.exchange;
import org.apache.log4j.Logger;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.exchange.ExchangeDefaults;
@@ -31,12 +30,13 @@ import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collection;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class DefaultExchangeRegistry implements ExchangeRegistry
{
- private static final Logger _log = Logger.getLogger(DefaultExchangeRegistry.class);
+ private static final Logger LOGGER = Logger.getLogger(DefaultExchangeRegistry.class);
/**
* Maps from exchange name to exchange instance
@@ -59,11 +59,9 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
new ExchangeInitialiser().initialise(_host.getExchangeFactory(), this, getDurableConfigurationStore());
}
-
-
public DurableConfigurationStore getDurableConfigurationStore()
{
- return _host.getDurableConfigurationStore();
+ return _host.getMessageStore();
}
public void registerExchange(Exchange exchange) throws AMQException
@@ -153,4 +151,49 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
}
}
+ @Override
+ public void clearAndUnregisterMbeans()
+ {
+ for (final AMQShortString exchangeName : getExchangeNames())
+ {
+ final Exchange exchange = getExchange(exchangeName);
+
+ if (exchange instanceof AbstractExchange)
+ {
+ AbstractExchange abstractExchange = (AbstractExchange) exchange;
+ try
+ {
+ abstractExchange.getManagedObject().unregister();
+ }
+ catch (AMQException e)
+ {
+ LOGGER.warn("Failed to unregister mbean", e);
+ }
+ }
+ }
+ _exchangeMap.clear();
+ _exchangeMapStr.clear();
+ }
+
+ @Override
+ public synchronized Exchange getExchange(UUID exchangeId)
+ {
+ if (exchangeId == null)
+ {
+ return getDefaultExchange();
+ }
+ else
+ {
+ Collection<Exchange> exchanges = _exchangeMap.values();
+ for (Exchange exchange : exchanges)
+ {
+ if (exchange.getId().equals(exchangeId))
+ {
+ return exchange;
+ }
+ }
+ return null;
+ }
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
index 8c0a5001db..af9322764a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
@@ -36,6 +36,7 @@ import javax.management.JMException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -103,14 +104,14 @@ public class DirectExchange extends AbstractExchange
return DirectExchange.class;
}
- public DirectExchange newInstance(VirtualHost host,
+ public DirectExchange newInstance(UUID id, VirtualHost host,
AMQShortString name,
boolean durable,
int ticket,
boolean autoDelete) throws AMQException
{
DirectExchange exch = new DirectExchange();
- exch.initialise(host,name,durable,ticket,autoDelete);
+ exch.initialise(id, host,name,durable,ticket,autoDelete);
return exch;
}
@@ -131,12 +132,6 @@ public class DirectExchange extends AbstractExchange
return new DirectExchangeMBean(this);
}
- public Logger getLogger()
- {
- return _logger;
- }
-
-
public List<? extends BaseQueue> doRoute(InboundMessage payload)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
index c3ae15f09c..289cb1a923 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
@@ -35,6 +35,8 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
import javax.management.JMException;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.UUID;
public interface Exchange extends ExchangeReferrer, ExchangeConfig
{
@@ -49,7 +51,7 @@ public interface Exchange extends ExchangeReferrer, ExchangeConfig
AMQShortString getTypeShortString();
- void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
+ void initialise(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
throws AMQException, JMException;
boolean isDurable();
@@ -111,6 +113,8 @@ public interface Exchange extends ExchangeReferrer, ExchangeConfig
boolean isBound(String bindingKey, AMQQueue queue);
+ public boolean isBound(String bindingKey, Map<String,Object> arguments, AMQQueue queue);
+
boolean isBound(String bindingKey);
void addCloseTask(Task task);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java
index 577da79028..aae4ae89bb 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java
@@ -25,6 +25,7 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import java.util.Collection;
+import java.util.UUID;
public interface ExchangeFactory
@@ -40,4 +41,10 @@ public interface ExchangeFactory
Collection<ExchangeType<? extends Exchange>> getPublicCreatableTypes();
Exchange createExchange(String exchange, String type, boolean durable, boolean autoDelete) throws AMQException;
+
+ Exchange createExchange(UUID id, String exchange, String type, boolean durable, boolean autoDelete) throws AMQException;
+
+ Exchange createExchange(UUID id, AMQShortString exchange, AMQShortString type, boolean durable,
+ boolean autoDelete, int ticket)
+ throws AMQException;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java
index 4dfcce7bbe..ba4f57a8e0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.exchange;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
@@ -27,7 +28,8 @@ import org.apache.qpid.server.store.DurableConfigurationStore;
public class ExchangeInitialiser
{
- public void initialise(ExchangeFactory factory, ExchangeRegistry registry, DurableConfigurationStore store) throws AMQException{
+ public void initialise(ExchangeFactory factory, ExchangeRegistry registry, DurableConfigurationStore store) throws AMQException
+ {
for (ExchangeType<? extends Exchange> type : factory.getRegisteredTypes())
{
define (registry, factory, type.getDefaultExchangeName(), type.getName(), store);
@@ -44,7 +46,6 @@ public class ExchangeInitialiser
{
Exchange exchange = f.createExchange(name, type, true, false, 0);
r.registerExchange(exchange);
-
if(exchange.isDurable())
{
store.createExchange(exchange);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
index 18eb37e037..795ae2e140 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
@@ -24,6 +24,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import java.util.Collection;
+import java.util.UUID;
public interface ExchangeRegistry
@@ -51,5 +52,9 @@ public interface ExchangeRegistry
Exchange getExchange(String exchangeName);
- void unregisterExchange(String exchange, boolean ifUnused) throws ExchangeInUseException, AMQException;;
+ void unregisterExchange(String exchange, boolean ifUnused) throws ExchangeInUseException, AMQException;
+
+ void clearAndUnregisterMbeans();
+
+ Exchange getExchange(UUID exchangeId);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeType.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeType.java
index ce339c4e29..a01e41f039 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeType.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeType.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.exchange;
+import java.util.UUID;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -29,7 +31,7 @@ public interface ExchangeType<T extends Exchange>
{
public AMQShortString getName();
public Class<T> getExchangeClass();
- public T newInstance(VirtualHost host, AMQShortString name,
+ public T newInstance(UUID id, VirtualHost host, AMQShortString name,
boolean durable, int ticket, boolean autoDelete) throws AMQException;
public AMQShortString getDefaultExchangeName();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
index 76f86ea1b4..5ebcfd095f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
@@ -34,6 +34,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
import javax.management.JMException;
import java.util.ArrayList;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class FanoutExchange extends AbstractExchange
@@ -52,11 +53,6 @@ public class FanoutExchange extends AbstractExchange
return new FanoutExchangeMBean(this);
}
- public Logger getLogger()
- {
- return _logger;
- }
-
public static final ExchangeType<FanoutExchange> TYPE = new ExchangeType<FanoutExchange>()
{
@@ -70,14 +66,14 @@ public class FanoutExchange extends AbstractExchange
return FanoutExchange.class;
}
- public FanoutExchange newInstance(VirtualHost host,
+ public FanoutExchange newInstance(UUID id, VirtualHost host,
AMQShortString name,
boolean durable,
int ticket,
boolean autoDelete) throws AMQException
{
FanoutExchange exch = new FanoutExchange();
- exch.initialise(host, name, durable, ticket, autoDelete);
+ exch.initialise(id, host, name, durable, ticket, autoDelete);
return exch;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
index 0886ae2ae0..b6f5f973f4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
@@ -39,7 +39,7 @@ class HeadersBinding
{
private static final Logger _logger = Logger.getLogger(HeadersBinding.class);
- private final FieldTable _mappings;
+ private final Map<String,Object> _mappings;
private final Binding _binding;
private final Set<String> required = new HashSet<String>();
private final Map<String,Object> matches = new HashMap<String,Object>();
@@ -58,7 +58,7 @@ class HeadersBinding
_binding = binding;
if(_binding !=null)
{
- _mappings = FieldTable.convertToFieldTable(_binding.getArguments());
+ _mappings = _binding.getArguments();
initMappings();
}
else
@@ -69,37 +69,23 @@ class HeadersBinding
private void initMappings()
{
- _mappings.processOverElements(new FieldTable.FieldTableElementProcessor()
+ for(Map.Entry<String, Object> entry : _mappings.entrySet())
{
-
- public boolean processElement(String propertyName, AMQTypedValue value)
+ String propertyName = entry.getKey();
+ Object value = entry.getValue();
+ if (isSpecial(propertyName))
{
- if (isSpecial(propertyName))
- {
- processSpecial(propertyName, value.getValue());
- }
- else if (value.getValue() == null || value.getValue().equals(""))
- {
- required.add(propertyName);
- }
- else
- {
- matches.put(propertyName,value.getValue());
- }
-
- return true;
+ processSpecial(propertyName, value);
}
-
- public Object getResult()
+ else if (value == null || value.equals(""))
{
- return null;
+ required.add(propertyName);
}
- });
- }
-
- protected FieldTable getMappings()
- {
- return _mappings;
+ else
+ {
+ matches.put(propertyName,value);
+ }
+ }
}
public Binding getBinding()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
index de12da74b4..16ba3c0431 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
@@ -37,6 +37,7 @@ import javax.management.JMException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -93,12 +94,12 @@ public class HeadersExchange extends AbstractExchange
return HeadersExchange.class;
}
- public HeadersExchange newInstance(VirtualHost host, AMQShortString name, boolean durable, int ticket,
+ public HeadersExchange newInstance(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket,
boolean autoDelete) throws AMQException
{
HeadersExchange exch = new HeadersExchange();
- exch.initialise(host, name, durable, ticket, autoDelete);
+ exch.initialise(id, host, name, durable, ticket, autoDelete);
return exch;
}
@@ -146,6 +147,33 @@ public class HeadersExchange extends AbstractExchange
return new ArrayList<BaseQueue>(queues);
}
+
+ public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue)
+ {
+ CopyOnWriteArraySet<Binding> bindings;
+ if(bindingKey == null)
+ {
+ bindings = new CopyOnWriteArraySet<Binding>(getBindings());
+ }
+ else
+ {
+ bindings = _bindingsByKey.get(bindingKey);
+ }
+
+ if(bindings != null)
+ {
+ for(Binding binding : bindings)
+ {
+ if(queue == null || binding.getQueue().equals(queue))
+ {
+ return arguments == null ? binding.getArguments() == null : binding.getArguments().equals(arguments);
+ }
+ }
+ }
+
+ return false;
+ }
+
public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
{
//fixme isBound here should take the arguements in to consideration.
@@ -204,11 +232,6 @@ public class HeadersExchange extends AbstractExchange
return new HeadersExchangeMBean(this);
}
- public Logger getLogger()
- {
- return _logger;
- }
-
protected void onBind(final Binding binding)
{
String bindingKey = binding.getBindingKey();
@@ -251,10 +274,11 @@ public class HeadersExchange extends AbstractExchange
{
bindings.remove(binding);
}
-
+
+ boolean removedBinding = _bindingHeaderMatchers.remove(new HeadersBinding(binding));
if(_logger.isDebugEnabled())
{
- _logger.debug("Removing Binding: " + _bindingHeaderMatchers.remove(new HeadersBinding(binding)));
+ _logger.debug("Removing Binding: " + removedBinding);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
index 6d7242a78d..7ea7a41826 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
@@ -20,13 +20,24 @@
*/
package org.apache.qpid.server.exchange;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.UUID;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.management.JMException;
import org.apache.log4j.Logger;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQInvalidArgumentException;
import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.filter.SelectorParsingException;
+import org.apache.qpid.filter.selector.ParseException;
import org.apache.qpid.filter.selector.TokenMgrError;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
@@ -36,23 +47,14 @@ import org.apache.qpid.server.exchange.topic.TopicMatcherResult;
import org.apache.qpid.server.exchange.topic.TopicNormalizer;
import org.apache.qpid.server.exchange.topic.TopicParser;
import org.apache.qpid.server.filter.JMSSelectorFilter;
-import org.apache.qpid.filter.selector.ParseException;
+import org.apache.qpid.server.filter.MessageFilter;
import org.apache.qpid.server.message.InboundMessage;
+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.Filterable;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import javax.management.JMException;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.WeakHashMap;
-import java.util.concurrent.ConcurrentHashMap;
-
public class TopicExchange extends AbstractExchange
{
@@ -69,14 +71,14 @@ public class TopicExchange extends AbstractExchange
return TopicExchange.class;
}
- public TopicExchange newInstance(VirtualHost host,
+ public TopicExchange newInstance(UUID id, VirtualHost host,
AMQShortString name,
boolean durable,
int ticket,
boolean autoDelete) throws AMQException
{
TopicExchange exch = new TopicExchange();
- exch.initialise(host, name, durable, ticket, autoDelete);
+ exch.initialise(id, host, name, durable, ticket, autoDelete);
return exch;
}
@@ -122,24 +124,26 @@ public class TopicExchange extends AbstractExchange
FieldTable oldArgs = _bindings.get(binding);
TopicExchangeResult result = _topicExchangeResults.get(routingKey);
- if(argumentsContainSelector(args))
+ if(argumentsContainFilter(args))
{
- if(argumentsContainSelector(oldArgs))
+ if(argumentsContainFilter(oldArgs))
{
- result.replaceQueueFilter(queue,createSelectorFilter(oldArgs), createSelectorFilter(args));
+ result.replaceQueueFilter(queue,
+ createMessageFilter(oldArgs, queue),
+ createMessageFilter(args, queue));
}
else
{
- result.addFilteredQueue(queue,createSelectorFilter(args));
+ result.addFilteredQueue(queue, createMessageFilter(args, queue));
result.removeUnfilteredQueue(queue);
}
}
else
{
- if(argumentsContainSelector(oldArgs))
+ if(argumentsContainFilter(oldArgs))
{
result.addUnfilteredQueue(queue);
- result.removeFilteredQueue(queue, createSelectorFilter(oldArgs));
+ result.removeFilteredQueue(queue, createMessageFilter(oldArgs, queue));
}
else
{
@@ -158,9 +162,9 @@ public class TopicExchange extends AbstractExchange
if(result == null)
{
result = new TopicExchangeResult();
- if(argumentsContainSelector(args))
+ if(argumentsContainFilter(args))
{
- result.addFilteredQueue(queue, createSelectorFilter(args));
+ result.addFilteredQueue(queue, createMessageFilter(args, queue));
}
else
{
@@ -171,9 +175,9 @@ public class TopicExchange extends AbstractExchange
}
else
{
- if(argumentsContainSelector(args))
+ if(argumentsContainFilter(args))
{
- result.addFilteredQueue(queue, createSelectorFilter(args));
+ result.addFilteredQueue(queue, createMessageFilter(args, queue));
}
else
{
@@ -187,9 +191,28 @@ public class TopicExchange extends AbstractExchange
}
- private JMSSelectorFilter createSelectorFilter(final FieldTable args) throws AMQInvalidArgumentException
+ private MessageFilter createMessageFilter(final FieldTable args, AMQQueue queue) throws AMQInvalidArgumentException
{
+ if(argumentsContainNoLocal(args))
+ {
+ MessageFilter filter = new NoLocalFilter(queue);
+
+ if(argumentsContainJMSSelector(args))
+ {
+ filter = new CompoundFilter(filter, createJMSSelectorFilter(args));
+ }
+ return filter;
+ }
+ else
+ {
+ return createJMSSelectorFilter(args);
+ }
+
+ }
+
+ private MessageFilter createJMSSelectorFilter(FieldTable args) throws AMQInvalidArgumentException
+ {
final String selectorString = args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue());
WeakReference<JMSSelectorFilter> selectorRef = _selectorCache.get(selectorString);
JMSSelectorFilter selector = null;
@@ -217,11 +240,25 @@ public class TopicExchange extends AbstractExchange
return selector;
}
- private static boolean argumentsContainSelector(final FieldTable args)
+ private static boolean argumentsContainFilter(final FieldTable args)
{
- return args != null && args.containsKey(AMQPFilterTypes.JMS_SELECTOR.getValue()) && args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue()).trim().length() != 0;
+ return argumentsContainNoLocal(args) || argumentsContainJMSSelector(args);
}
+ private static boolean argumentsContainNoLocal(final FieldTable args)
+ {
+ return args != null
+ && args.containsKey(AMQPFilterTypes.NO_LOCAL.getValue())
+ && Boolean.TRUE.equals(args.get(AMQPFilterTypes.NO_LOCAL.getValue()));
+ }
+
+ private static boolean argumentsContainJMSSelector(final FieldTable args)
+ {
+ return args != null && (args.containsKey(AMQPFilterTypes.JMS_SELECTOR.getValue())
+ && args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue()).trim().length() != 0);
+ }
+
+
public ArrayList<BaseQueue> doRoute(InboundMessage payload)
{
@@ -275,6 +312,28 @@ public class TopicExchange extends AbstractExchange
}
}
+ public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue)
+ {
+ Binding binding = new Binding(null, bindingKey, queue, this, arguments);
+ if (arguments == null)
+ {
+ return _bindings.containsKey(binding);
+ }
+ else
+ {
+ FieldTable o = _bindings.get(binding);
+ if (o != null)
+ {
+ return arguments.equals(FieldTable.convertToMap(o));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ }
+
public boolean isBound(AMQShortString routingKey, AMQQueue queue)
{
return isBound(routingKey, null, queue);
@@ -321,11 +380,11 @@ public class TopicExchange extends AbstractExchange
result.removeBinding(binding);
- if(argumentsContainSelector(bindingArgs))
+ if(argumentsContainFilter(bindingArgs))
{
try
{
- result.removeFilteredQueue(binding.getQueue(), createSelectorFilter(bindingArgs));
+ result.removeFilteredQueue(binding.getQueue(), createMessageFilter(bindingArgs, binding.getQueue()));
}
catch (AMQInvalidArgumentException e)
{
@@ -349,11 +408,6 @@ public class TopicExchange extends AbstractExchange
return new TopicExchangeMBean(this);
}
- public Logger getLogger()
- {
- return _logger;
- }
-
private Collection<AMQQueue> getMatchedQueues(InboundMessage message, AMQShortString routingKey)
{
@@ -402,4 +456,96 @@ public class TopicExchange extends AbstractExchange
deregisterQueue(binding);
}
+ private static final class NoLocalFilter implements MessageFilter
+ {
+ private final AMQQueue _queue;
+
+ public NoLocalFilter(AMQQueue queue)
+ {
+ _queue = queue;
+ }
+
+ public boolean matches(Filterable message)
+ {
+ InboundMessage inbound = (InboundMessage) message;
+ final AMQSessionModel exclusiveOwningSession = _queue.getExclusiveOwningSession();
+ return exclusiveOwningSession == null || !exclusiveOwningSession.onSameConnection(inbound);
+
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ NoLocalFilter that = (NoLocalFilter) o;
+
+ return _queue == null ? that._queue == null : _queue.equals(that._queue);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _queue != null ? _queue.hashCode() : 0;
+ }
+ }
+
+ private static final class CompoundFilter implements MessageFilter
+ {
+ private MessageFilter _noLocalFilter;
+ private MessageFilter _jmsSelectorFilter;
+
+ public CompoundFilter(MessageFilter filter, MessageFilter jmsSelectorFilter)
+ {
+ _noLocalFilter = filter;
+ _jmsSelectorFilter = jmsSelectorFilter;
+ }
+
+ public boolean matches(Filterable message)
+ {
+ return _noLocalFilter.matches(message) && _jmsSelectorFilter.matches(message);
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ CompoundFilter that = (CompoundFilter) o;
+
+ if (_jmsSelectorFilter != null ? !_jmsSelectorFilter.equals(that._jmsSelectorFilter) : that._jmsSelectorFilter != null)
+ {
+ return false;
+ }
+ if (_noLocalFilter != null ? !_noLocalFilter.equals(that._noLocalFilter) : that._noLocalFilter != null)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = _noLocalFilter != null ? _noLocalFilter.hashCode() : 0;
+ result = 31 * result + (_jmsSelectorFilter != null ? _jmsSelectorFilter.hashCode() : 0);
+ return result;
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java
index b58802e1ff..c7046f8e53 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java
@@ -132,7 +132,7 @@ public class Bridge implements BridgeConfig
{
try
{
- brokerLink.getVirtualHost().getDurableConfigurationStore().createBridge(this);
+ brokerLink.getVirtualHost().getMessageStore().createBridge(this);
}
catch (AMQStoreException e)
{
@@ -220,7 +220,7 @@ public class Bridge implements BridgeConfig
{
try
{
- brokerLink.getVirtualHost().getDurableConfigurationStore().createBridge(this);
+ brokerLink.getVirtualHost().getMessageStore().createBridge(this);
}
catch (AMQStoreException e)
{
@@ -767,13 +767,13 @@ public class Bridge implements BridgeConfig
try
{
- _queue = AMQQueueFactory.createAMQQueueImpl(_tmpQueueName,
+ _queue = AMQQueueFactory.createAMQQueueImpl(null,
+ _tmpQueueName,
isDurable(),
_link.getFederationTag(),
false,
false,
- getVirtualHost(),
- options);
+ getVirtualHost(), options);
}
catch (AMQException e)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java b/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java
index 032df8bb0d..4bcc0d6136 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java
@@ -250,7 +250,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener
{
try
{
- _virtualHost.getDurableConfigurationStore().createBrokerLink(this);
+ _virtualHost.getMessageStore().createBrokerLink(this);
}
catch (AMQStoreException e)
{
@@ -295,7 +295,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener
{
try
{
- _virtualHost.getDurableConfigurationStore().createBrokerLink(this);
+ _virtualHost.getMessageStore().createBrokerLink(this);
}
catch (AMQStoreException e)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java b/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java
index 18a0e4c8bf..6c158de8b5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java
@@ -39,6 +39,12 @@ public class SimpleFilterManager implements FilterManager
_filters = new ConcurrentLinkedQueue<MessageFilter>();
}
+ public SimpleFilterManager(JMSSelectorFilter messageFilter)
+ {
+ this();
+ add(messageFilter);
+ }
+
public void add(MessageFilter filter)
{
_filters.add(filter);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java
index 79fcfb6d76..eab28ac9d4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java
@@ -32,6 +32,7 @@ import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.state.AMQState;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.virtualhost.State;
import org.apache.qpid.server.virtualhost.VirtualHost;
public class ConnectionOpenMethodHandler implements StateAwareMethodListener<ConnectionOpenBody>
@@ -82,6 +83,10 @@ public class ConnectionOpenMethodHandler implements StateAwareMethodListener<Con
{
throw body.getConnectionException(AMQConstant.ACCESS_REFUSED, "Permission denied: '" + virtualHost.getName() + "'");
}
+ else if (virtualHost.getState() != State.ACTIVE)
+ {
+ throw body.getConnectionException(AMQConstant.CONNECTION_FORCED, "Virtual host '" + virtualHost.getName() + "' is not active");
+ }
session.setVirtualHost(virtualHost);
@@ -89,10 +94,10 @@ public class ConnectionOpenMethodHandler implements StateAwareMethodListener<Con
if (session.getContextKey() == null)
{
session.setContextKey(generateClientID());
- }
+ }
MethodRegistry methodRegistry = session.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createConnectionOpenOkBody(body.getVirtualHost());
+ AMQMethodBody responseBody = methodRegistry.createConnectionOpenOkBody(body.getVirtualHost());
stateManager.changeState(AMQState.CONNECTION_OPEN);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
index 81e2e5557a..8756409f64 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
@@ -26,6 +26,7 @@ import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQUnknownExchangeType;
import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ExchangeDeclareBody;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.protocol.AMQConstant;
@@ -65,26 +66,39 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange
throw body.getChannelNotFoundException(channelId);
}
+ final AMQShortString exchangeName = body.getExchange();
if (_logger.isDebugEnabled())
{
- _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + body.getExchange());
+ _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + exchangeName);
}
synchronized(exchangeRegistry)
{
- Exchange exchange = exchangeRegistry.getExchange(body.getExchange());
+ Exchange exchange = exchangeRegistry.getExchange(exchangeName);
if (exchange == null)
{
if(body.getPassive() && ((body.getType() == null) || body.getType().length() ==0))
{
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + body.getExchange());
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName);
+ }
+ else if(exchangeName.startsWith("amq."))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Attempt to declare exchange: " + exchangeName +
+ " which begins with reserved prefix 'amq.'.");
+ }
+ else if(exchangeName.startsWith("qpid."))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Attempt to declare exchange: " + exchangeName +
+ " which begins with reserved prefix 'qpid.'.");
}
else
{
try
{
- exchange = exchangeFactory.createExchange(body.getExchange() == null ? null : body.getExchange().intern(),
+ exchange = exchangeFactory.createExchange(exchangeName == null ? null : exchangeName.intern(),
body.getType() == null ? null : body.getType().intern(),
body.getDurable(),
body.getPassive(), body.getTicket());
@@ -92,19 +106,20 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange
if (exchange.isDurable())
{
- virtualHost.getDurableConfigurationStore().createExchange(exchange);
+ virtualHost.getMessageStore().createExchange(exchange);
}
}
catch(AMQUnknownExchangeType e)
{
- throw body.getConnectionException(AMQConstant.COMMAND_INVALID, "Unknown exchange: " + body.getExchange(),e);
+ throw body.getConnectionException(AMQConstant.COMMAND_INVALID, "Unknown exchange: " + exchangeName,e);
}
}
}
else if (!exchange.getTypeShortString().equals(body.getType()) && !((body.getType() == null || body.getType().length() ==0) && body.getPassive()))
{
- throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + body.getExchange() + " of type " + exchange.getTypeShortString() + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null);
+ throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " +
+ exchangeName + " of type " + exchange.getTypeShortString() + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null);
}
}
if(!body.getNowait())
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java
index bb979d5441..49ca934966 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java
@@ -134,7 +134,7 @@ public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody>
Map<String, Object> oldArgs = oldBinding.getArguments();
if((oldArgs == null && !arguments.isEmpty()) || (oldArgs != null && !oldArgs.equals(arguments)))
{
- virtualHost.getBindingFactory().replaceBinding(bindingKey, queue, exch, arguments);
+ virtualHost.getBindingFactory().replaceBinding(oldBinding.getId(), bindingKey, queue, exch, arguments);
}
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
index f57f7eb9e6..396829df91 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
@@ -24,6 +24,7 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.framing.QueueDeclareBody;
import org.apache.qpid.framing.QueueDeclareOkBody;
@@ -31,6 +32,7 @@ import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
@@ -43,6 +45,7 @@ import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collections;
+import java.util.Map;
import java.util.UUID;
public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclareBody>
@@ -65,7 +68,7 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
VirtualHost virtualHost = protocolConnection.getVirtualHost();
ExchangeRegistry exchangeRegistry = virtualHost.getExchangeRegistry();
QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
- DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+ DurableConfigurationStore store = virtualHost.getMessageStore();
final AMQShortString queueName;
@@ -219,10 +222,11 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
throws AMQException
{
final QueueRegistry registry = virtualHost.getQueueRegistry();
- AMQShortString owner = body.getExclusive() ? session.getContextKey() : null;
+ String owner = body.getExclusive() ? AMQShortString.toString(session.getContextKey()) : null;
- final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, body.getDurable(), owner, body.getAutoDelete(),
- body.getExclusive(),virtualHost, body.getArguments());
+ Map<String, Object> arguments = FieldTable.convertToMap(body.getArguments());
+ final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), AMQShortString.toString(queueName), body.getDurable(), owner, body.getAutoDelete(),
+ body.getExclusive(),virtualHost, arguments);
if (body.getExclusive() && !body.getDurable())
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java
index cc37259d54..762f090b83 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java
@@ -62,7 +62,7 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB
AMQProtocolSession protocolConnection = stateManager.getProtocolSession();
VirtualHost virtualHost = protocolConnection.getVirtualHost();
QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
- DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+ DurableConfigurationStore store = virtualHost.getMessageStore();
AMQChannel channel = protocolConnection.getChannel(channelId);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java
index feacf35d41..97134515a0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java
@@ -20,11 +20,13 @@
*/
package org.apache.qpid.server.logging.actors;
-import org.apache.qpid.server.logging.LogActor;
-
import java.util.EmptyStackException;
import java.util.Stack;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.LogMessage;
+import org.apache.qpid.server.logging.LogSubject;
+
/**
* The CurrentActor is a ThreadLocal wrapper that allows threads in the broker
* to retrieve an actor to perform logging. This approach is used so for two
@@ -126,4 +128,14 @@ public class CurrentActor
{
_defaultActor = defaultActor;
}
+
+ public static void message(LogSubject subject, LogMessage message)
+ {
+ get().message(subject, message);
+ }
+
+ public static void message(LogMessage message)
+ {
+ get().message(message);
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ConfigStore_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ConfigStore_logmessages.properties
index 3bc5074777..541f8b8c68 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ConfigStore_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ConfigStore_logmessages.properties
@@ -18,8 +18,7 @@
#
# Default File used for all non-defined locales.
-# 0 - name
-CREATED = CFG-1001 : Created : {0}
+CREATED = CFG-1001 : Created
# 0 - path
STORE_LOCATION = CFG-1002 : Store location : {0}
CLOSE = CFG-1003 : Closed
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties
index a2cedeb22a..081f2bbca3 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties
@@ -18,11 +18,11 @@
#
# Default File used for all non-defined locales.
#
-# 0 - name
-CREATED = MST-1001 : Created : {0}
+CREATED = MST-1001 : Created
# 0 - path
STORE_LOCATION = MST-1002 : Store location : {0}
CLOSED = MST-1003 : Closed
RECOVERY_START = MST-1004 : Recovery Start
RECOVERED = MST-1005 : Recovered {0,number} messages
-RECOVERY_COMPLETE = MST-1006 : Recovery Complete \ No newline at end of file
+RECOVERY_COMPLETE = MST-1006 : Recovery Complete
+PASSIVATE = MST-1007 : Store Passivated
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties
index fadc2e2098..b9e87159a6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/TransactionLog_logmessages.properties
@@ -19,8 +19,7 @@
# Default File used for all non-defined locales.
#
#
-# 0 - name
-CREATED = TXN-1001 : Created : {0}
+CREATED = TXN-1001 : Created
# 0 - path
STORE_LOCATION = TXN-1002 : Store location : {0}
CLOSED = TXN-1003 : Closed
@@ -31,3 +30,9 @@ RECOVERY_START = TXN-1004 : Recovery Start[ : {0}]
RECOVERED = TXN-1005 : Recovered {0,number} messages for queue {1}
# 0 - queue name
RECOVERY_COMPLETE = TXN-1006 : Recovery Complete[ : {0}]
+# 0 - xid
+# 1 - queue name
+XA_INCOMPLETE_QUEUE = TXN-1007 : XA transaction recover for xid {0} incomplete as it references a queue {1} which was not durably retained
+# 0 - xid format
+# 1 - message id
+XA_INCOMPLETE_MESSAGE = TXN-1008 : XA transaction recover for xid {0} incomplete as it references a message {1} which was not durably retained
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java
index 8f0b9182a9..6f18cbcc6b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java
@@ -40,7 +40,8 @@ public class BindingLogSubject extends AbstractLogSubject
public BindingLogSubject(String routingKey, Exchange exchange,
AMQQueue queue)
{
- setLogStringWithFormat(BINDING_FORMAT, queue.getVirtualHost().getName(),
+ setLogStringWithFormat(BINDING_FORMAT,
+ queue.getVirtualHost().getName(),
exchange.getTypeShortString(),
exchange.getNameShortString(),
queue.getNameShortString(),
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubject.java
index 969288be00..08963bd8f1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubject.java
@@ -20,7 +20,6 @@
*/
package org.apache.qpid.server.logging.subjects;
-import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.STORE_FORMAT;
@@ -28,10 +27,9 @@ import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.STORE_FOR
public class MessageStoreLogSubject extends AbstractLogSubject
{
- /** Create an ExchangeLogSubject that Logs in the following format. */
- public MessageStoreLogSubject(VirtualHost vhost, MessageStore store)
+ /** Create an MessageStoreLogSubject that Logs in the following format. */
+ public MessageStoreLogSubject(VirtualHost vhost, String messageStoreName)
{
- setLogStringWithFormat(STORE_FORMAT, vhost.getName(),
- store.getClass().getSimpleName());
+ setLogStringWithFormat(STORE_FORMAT, vhost.getName(), messageStoreName);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java b/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java
index e7c07b6dd4..6cfc827046 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java
@@ -1,3 +1,23 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
package org.apache.qpid.server.management;
import org.apache.qpid.management.common.mbeans.ManagedConnection;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
index b6623bbd09..04a5b27991 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
@@ -157,9 +157,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
if (!ksf.exists())
{
- throw new FileNotFoundException("Cannot find JMX management SSL keystore file " + ksf + "\n"
- + "Check broker configuration, or see create-example-ssl-stores script"
- + "in the bin/ directory if you need to generate an example store.");
+ throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf);
}
if (!ksf.canRead())
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
index 805094a061..88b0f60346 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
@@ -50,6 +50,7 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes
public static final MessageMetaDataType.Factory<MessageMetaData_0_10> FACTORY = new MetaDataFactory();
private volatile ByteBuffer _encoded;
+ private Object _connectionReference;
public MessageMetaData_0_10(MessageTransfer xfr)
@@ -219,6 +220,16 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes
return _header;
}
+ public void setConnectionReference(Object connectionReference)
+ {
+ _connectionReference = connectionReference;
+ }
+
+ public Object getConnectionReference()
+ {
+ return _connectionReference;
+ }
+
private static class MetaDataFactory implements MessageMetaDataType.Factory<MessageMetaData_0_10>
{
public MessageMetaData_0_10 createMetaData(ByteBuffer buf)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java
new file mode 100755
index 0000000000..7d030fe711
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java
@@ -0,0 +1,522 @@
+/*
+*
+* 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 java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.qpid.amqp_1_0.codec.ValueHandler;
+import org.apache.qpid.amqp_1_0.messaging.SectionDecoder;
+import org.apache.qpid.amqp_1_0.type.AmqpErrorException;
+import org.apache.qpid.amqp_1_0.type.Section;
+import org.apache.qpid.amqp_1_0.type.Symbol;
+import org.apache.qpid.amqp_1_0.type.codec.AMQPDescribedTypeRegistry;
+import org.apache.qpid.amqp_1_0.type.messaging.AmqpSequence;
+import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue;
+import org.apache.qpid.amqp_1_0.type.messaging.ApplicationProperties;
+import org.apache.qpid.amqp_1_0.type.messaging.Data;
+import org.apache.qpid.amqp_1_0.type.messaging.DeliveryAnnotations;
+import org.apache.qpid.amqp_1_0.type.messaging.Footer;
+import org.apache.qpid.amqp_1_0.type.messaging.Header;
+import org.apache.qpid.amqp_1_0.type.messaging.MessageAnnotations;
+import org.apache.qpid.amqp_1_0.type.messaging.Properties;
+import org.apache.qpid.server.store.MessageMetaDataType;
+import org.apache.qpid.server.store.StorableMessageMetaData;
+
+public class MessageMetaData_1_0 implements StorableMessageMetaData
+{
+ // TODO move to somewhere more useful
+ public static final Symbol JMS_TYPE = Symbol.valueOf("x-opt-jms-type");
+
+
+ private Header _header;
+ private Properties _properties;
+ private Map _deliveryAnnotations;
+ private Map _messageAnnotations;
+ private Map _appProperties;
+ private Map _footer;
+
+ private List<ByteBuffer> _encodedSections = new ArrayList<ByteBuffer>(3);
+
+ private volatile ByteBuffer _encoded;
+ private MessageHeader_1_0 _messageHeader;
+
+
+
+ public MessageMetaData_1_0(ByteBuffer[] fragments, SectionDecoder decoder)
+ {
+ this(fragments, decoder, new ArrayList<ByteBuffer>(3));
+ }
+
+ public MessageMetaData_1_0(ByteBuffer[] fragments, SectionDecoder decoder, List<ByteBuffer> immuatableSections)
+ {
+ this(constructSections(fragments, decoder,immuatableSections), immuatableSections);
+ }
+
+ private MessageMetaData_1_0(List<Section> sections, List<ByteBuffer> encodedSections)
+ {
+ _encodedSections = encodedSections;
+
+ Iterator<Section> sectIter = sections.iterator();
+
+ Section section = sectIter.hasNext() ? sectIter.next() : null;
+ if(section instanceof Header)
+ {
+ _header = (Header) section;
+ section = sectIter.hasNext() ? sectIter.next() : null;
+ }
+
+ if(section instanceof DeliveryAnnotations)
+ {
+ _deliveryAnnotations = ((DeliveryAnnotations) section).getValue();
+ section = sectIter.hasNext() ? sectIter.next() : null;
+ }
+
+ if(section instanceof MessageAnnotations)
+ {
+ _messageAnnotations = ((MessageAnnotations) section).getValue();
+ section = sectIter.hasNext() ? sectIter.next() : null;
+ }
+
+ if(section instanceof Properties)
+ {
+ _properties = (Properties) section;
+ section = sectIter.hasNext() ? sectIter.next() : null;
+ }
+
+ if(section instanceof ApplicationProperties)
+ {
+ _appProperties = ((ApplicationProperties) section).getValue();
+ section = sectIter.hasNext() ? sectIter.next() : null;
+ }
+
+ if(section instanceof Footer)
+ {
+ _footer = ((Footer) section).getValue();
+ section = sectIter.hasNext() ? sectIter.next() : null;
+ }
+
+ _messageHeader = new MessageHeader_1_0();
+
+ }
+
+ private static List<Section> constructSections(final ByteBuffer[] fragments, final SectionDecoder decoder, List<ByteBuffer> encodedSections)
+ {
+ List<Section> sections = new ArrayList<Section>(3);
+
+ ByteBuffer src;
+ if(fragments.length == 1)
+ {
+ src = fragments[0].duplicate();
+ }
+ else
+ {
+ int size = 0;
+ for(ByteBuffer buf : fragments)
+ {
+ size += buf.remaining();
+ }
+ src = ByteBuffer.allocate(size);
+ for(ByteBuffer buf : fragments)
+ {
+ src.put(buf.duplicate());
+ }
+ src.flip();
+
+ }
+
+ try
+ {
+ int startBarePos = -1;
+ int lastPos = src.position();
+ Section s = decoder.readSection(src);
+
+
+
+ if(s instanceof Header)
+ {
+ sections.add(s);
+ lastPos = src.position();
+ s = src.hasRemaining() ? decoder.readSection(src) : null;
+ }
+
+ if(s instanceof DeliveryAnnotations)
+ {
+ sections.add(s);
+ lastPos = src.position();
+ s = src.hasRemaining() ? decoder.readSection(src) : null;
+ }
+
+ if(s instanceof MessageAnnotations)
+ {
+ sections.add(s);
+ lastPos = src.position();
+ s = src.hasRemaining() ? decoder.readSection(src) : null;
+ }
+
+ if(s instanceof Properties)
+ {
+ sections.add(s);
+ if(startBarePos == -1)
+ {
+ startBarePos = lastPos;
+ }
+ s = src.hasRemaining() ? decoder.readSection(src) : null;
+ }
+
+ if(s instanceof ApplicationProperties)
+ {
+ sections.add(s);
+ if(startBarePos == -1)
+ {
+ startBarePos = lastPos;
+ }
+ s = src.hasRemaining() ? decoder.readSection(src) : null;
+ }
+
+ if(s instanceof AmqpValue)
+ {
+ if(startBarePos == -1)
+ {
+ startBarePos = lastPos;
+ }
+ s = src.hasRemaining() ? decoder.readSection(src) : null;
+ }
+ else if(s instanceof Data)
+ {
+ if(startBarePos == -1)
+ {
+ startBarePos = lastPos;
+ }
+ do
+ {
+ s = src.hasRemaining() ? decoder.readSection(src) : null;
+ } while(s instanceof Data);
+ }
+ else if(s instanceof AmqpSequence)
+ {
+ if(startBarePos == -1)
+ {
+ startBarePos = lastPos;
+ }
+ do
+ {
+ s = src.hasRemaining() ? decoder.readSection(src) : null;
+ }
+ while(s instanceof AmqpSequence);
+ }
+
+ if(s instanceof Footer)
+ {
+ sections.add(s);
+ }
+
+
+ int pos = 0;
+ for(ByteBuffer buf : fragments)
+ {
+/*
+ if(pos < startBarePos)
+ {
+ if(pos + buf.remaining() > startBarePos)
+ {
+ ByteBuffer dup = buf.duplicate();
+ dup.position(dup.position()+startBarePos-pos);
+ dup.slice();
+ encodedSections.add(dup);
+ }
+ }
+ else
+*/
+ {
+ encodedSections.add(buf.duplicate());
+ }
+ pos += buf.remaining();
+ }
+
+ return sections;
+ }
+ catch (AmqpErrorException e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+
+ public MessageMetaDataType getType()
+ {
+ return MessageMetaDataType.META_DATA_1_0;
+ }
+
+
+ public int getStorableSize()
+ {
+ int size = 0;
+
+ for(ByteBuffer bin : _encodedSections)
+ {
+ size += bin.limit();
+ }
+
+ return size;
+ }
+
+ private ByteBuffer encodeAsBuffer()
+ {
+ ByteBuffer buf = ByteBuffer.allocate(getStorableSize());
+
+ for(ByteBuffer bin : _encodedSections)
+ {
+ buf.put(bin.duplicate());
+ }
+
+ return buf;
+ }
+
+ public int writeToBuffer(int offsetInMetaData, ByteBuffer dest)
+ {
+ ByteBuffer buf = _encoded;
+
+ if(buf == null)
+ {
+ buf = encodeAsBuffer();
+ _encoded = buf;
+ }
+
+ buf = buf.duplicate();
+
+ buf.position(offsetInMetaData);
+
+ if(dest.remaining() < buf.limit())
+ {
+ buf.limit(dest.remaining());
+ }
+ dest.put(buf);
+ return buf.limit();
+ }
+
+ public int getContentSize()
+ {
+ ByteBuffer buf = _encoded;
+
+ if(buf == null)
+ {
+ buf = encodeAsBuffer();
+ _encoded = buf;
+ }
+ return buf.remaining();
+ }
+
+ public boolean isPersistent()
+ {
+ return _header != null && Boolean.TRUE.equals(_header.getDurable());
+ }
+
+ public MessageHeader_1_0 getMessageHeader()
+ {
+ return _messageHeader;
+ }
+
+ public static final MessageMetaDataType.Factory<MessageMetaData_1_0> FACTORY = new MetaDataFactory();
+
+
+ private static class MetaDataFactory implements MessageMetaDataType.Factory<MessageMetaData_1_0>
+ {
+ private final AMQPDescribedTypeRegistry _typeRegistry = AMQPDescribedTypeRegistry.newInstance();
+
+ public MessageMetaData_1_0 createMetaData(ByteBuffer buf)
+ {
+ ValueHandler valueHandler = new ValueHandler(_typeRegistry);
+
+ ArrayList<Section> sections = new ArrayList<Section>(3);
+ ArrayList<ByteBuffer> encodedSections = new ArrayList<ByteBuffer>(3);
+
+ while(buf.hasRemaining())
+ {
+ try
+ {
+ ByteBuffer encodedBuf = buf.duplicate();
+ sections.add((Section) valueHandler.parse(buf));
+ encodedBuf.limit(buf.position());
+ encodedSections.add(encodedBuf);
+
+ }
+ catch (AmqpErrorException e)
+ {
+ //TODO
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ return new MessageMetaData_1_0(sections,encodedSections);
+
+ }
+ }
+
+ public class MessageHeader_1_0 implements AMQMessageHeader
+ {
+
+ public String getCorrelationId()
+ {
+ if(_properties == null || _properties.getCorrelationId() == null)
+ {
+ return null;
+ }
+ else
+ {
+ return _properties.getMessageId().toString();
+ }
+ }
+
+ public long getExpiration()
+ {
+ return 0; //TODO
+ }
+
+ public String getMessageId()
+ {
+ if(_properties == null || _properties.getCorrelationId() == null)
+ {
+ return null;
+ }
+ else
+ {
+ return _properties.getCorrelationId().toString();
+ }
+ }
+
+ public String getMimeType()
+ {
+
+ if(_properties == null || _properties.getContentType() == null)
+ {
+ return null;
+ }
+ else
+ {
+ return _properties.getContentType().toString();
+ }
+ }
+
+ public String getEncoding()
+ {
+ return null; //TODO
+ }
+
+ public byte getPriority()
+ {
+ if(_header == null || _header.getPriority() == null)
+ {
+ return 4; //javax.jms.Message.DEFAULT_PRIORITY;
+ }
+ else
+ {
+ return _header.getPriority().byteValue();
+ }
+ }
+
+ public long getTimestamp()
+ {
+ if(_properties == null || _properties.getCreationTime() == null)
+ {
+ return 0L;
+ }
+ else
+ {
+ return _properties.getCreationTime().getTime();
+ }
+
+ }
+
+ public String getType()
+ {
+
+ if(_messageAnnotations == null || _messageAnnotations.get(JMS_TYPE) == null)
+ {
+ return null;
+ }
+ else
+ {
+ return _messageAnnotations.get(JMS_TYPE).toString();
+ }
+ }
+
+ public String getReplyTo()
+ {
+ if(_properties == null || _properties.getReplyTo() == null)
+ {
+ return null;
+ }
+ else
+ {
+ return _properties.getReplyTo().toString();
+ }
+ }
+
+ public String getReplyToExchange()
+ {
+ return null; //TODO
+ }
+
+ public String getReplyToRoutingKey()
+ {
+ return null; //TODO
+ }
+
+ public Object getHeader(final String name)
+ {
+ return _appProperties == null ? null : _appProperties.get(name);
+ }
+
+ public boolean containsHeaders(final Set<String> names)
+ {
+ if(_appProperties == null)
+ {
+ return false;
+ }
+
+ for(String key : names)
+ {
+ if(!_appProperties.containsKey(key))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean containsHeader(final String name)
+ {
+ return _appProperties != null && _appProperties.containsKey(name);
+ }
+
+ public String getSubject()
+ {
+ return _properties == null ? null : _properties.getSubject();
+ }
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Binding.java b/java/broker/src/main/java/org/apache/qpid/server/model/Binding.java
new file mode 100644
index 0000000000..fdb009386c
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Binding.java
@@ -0,0 +1,75 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+public interface Binding extends ConfiguredObject
+{
+
+ public String MATCHED_BYTES = "matchedBytes";
+ public String MATCHED_MESSAGES = "matchedMessages";
+ public String STATE_CHANGED = "stateChanged";
+
+ public static final Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableCollection(
+ Arrays.asList(
+ MATCHED_BYTES,
+ MATCHED_MESSAGES,
+ STATE_CHANGED));
+
+
+ public String ARGUMENTS = "arguments";
+ public String CREATED = "created";
+ public String DURABLE = "durable";
+ public String ID = "id";
+ public String LIFETIME_POLICY = "lifetimePolicy";
+ public String NAME = "name";
+ public String STATE = "state";
+ public String TIME_TO_LIVE = "timeToLive";
+ public String UPDATED = "updated";
+ public String QUEUE = "queue";
+ public String EXCHANGE = "exchange";
+
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableCollection(
+ Arrays.asList(ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ EXCHANGE,
+ QUEUE,
+ ARGUMENTS)
+ );
+
+
+
+ Map<String,Object> getArguments();
+
+ void delete();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
new file mode 100644
index 0000000000..6477633a9b
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
@@ -0,0 +1,38 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+public interface ConfigurationChangeListener
+{
+ /**
+ * Inform the listener that the passed object has changed state
+ *
+ * @param object the object whose state has changed
+ * @param oldState the state prior to the change
+ * @param newState the state after the change
+ */
+ void stateChanged(ConfiguredObject object, State oldState, State newState);
+
+ void childAdded(ConfiguredObject object, ConfiguredObject child);
+
+ void childRemoved(ConfiguredObject object, ConfiguredObject child);
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
new file mode 100644
index 0000000000..fb47a54d0a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
@@ -0,0 +1,229 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.UUID;
+
+public interface ConfiguredObject
+{
+
+ /**
+ * Get the universally unique identifier for the object
+ *
+ * @return the objects id
+ */
+ UUID getId();
+
+ /**
+ * Get the name of the object
+ *
+ * @return the name of the object
+ */
+ String getName();
+
+
+ /**
+ * Attempt to change the name of the object
+ *
+ * Request a change to the name of the object. The caller must pass in the name it believes the object currently
+ * has. If the current name differes from this expected value, then no name change will occur
+ *
+ * @param currentName the name the caller believes the object to have
+ * @param desiredName the name the caller would like the object to have
+ * @return the new name for the object
+ * @throws IllegalStateException if the name of the object may not be changed in in the current state
+ * @throws AccessControlException if the current context does not have permission to change the name
+ * @throws IllegalArgumentException if the provided name is not legal
+ * @throws NullPointerException if the desired name is null
+ */
+ String setName(String currentName, String desiredName) throws IllegalStateException,
+ AccessControlException;
+
+
+ /**
+ * Get the desired state of the object.
+ *
+ * This is the state set at the object itself, however the object
+ * may not be able attain this state if one of its ancestors is in a different state (in particular a descendant
+ * object may not be ACTIVE if all of its ancestors are not also ACTIVE).
+ *
+ * @return the desired state of the object
+ */
+ State getDesiredState();
+
+ /**
+ * Change the desired state of the object
+ *
+ * Request a change to the current state. The caller must pass in the state it believe the object to be in, if
+ * this differs from the current desired state when the object evalues the request, then no state change will occur.
+ *
+ * @param currentState the state the caller believes the object to be in
+ * @param desiredState the state the caller wishes the object to attain
+ * @return the new current state
+ * @throws IllegalStateTransitionException the requested state tranisition is invalid
+ * @throws AccessControlException the current context does not have sufficeint permissions to change the state
+ */
+ State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException,
+ AccessControlException;
+
+ /**
+ * Get the actual state of the object.
+ *
+ * This state is derived fromt the desired state of the object itself and
+ * the actual state of its parents. If an object "desires" to be ACTIVE, but one of its parents is STOPPED, then
+ * the actual state of the object will be STOPPED
+ *
+ * @return the actual state of the object
+ */
+ State getActualState();
+
+
+ /**
+ * Add a listener which will be informed of all changes to this configuration object
+ *
+ * @param listener the listener to add
+ */
+ void addChangeListener(ConfigurationChangeListener listener);
+
+ /**
+ * Remove a change listener
+ *
+ *
+ * @param listener the listener to remove
+ * @return true iff a listener was removed
+ */
+ boolean removeChangeListener(ConfigurationChangeListener listener);
+
+ /**
+ * Get the parent of the given type for this object
+ *
+ * @param clazz the class of parent being asked for
+ * @return the objects parent
+ */
+ <T extends ConfiguredObject> T getParent(Class<T> clazz);
+
+
+ /**
+ * Returns whether the the object configuration is durably stored
+ *
+ * @return the durablity
+ */
+ boolean isDurable();
+
+ /**
+ * Sets the durability of the object
+ *
+ * @param durable true iff the caller wishes the object to store its configuration durably
+ *
+ * @throws IllegalStateException if the durability cannot be changed in the current state
+ * @throws AccessControlException if the current context does not have sufficient permission to change the durability
+ * @throws IllegalArgumentException if the object does not support the requested durability
+ */
+ void setDurable(boolean durable) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+ /**
+ * Return the lifetime policy for the object
+ *
+ * @return the lifetime policy
+ */
+ LifetimePolicy getLifetimePolicy();
+
+ /**
+ * Set the lifetime policy of the object
+ *
+ * @param expected The lifetime policy the caller believes the object currently has
+ * @param desired The lifetime policy the caller desires the object to have
+ * @return the new lifetime policy
+ * @throws IllegalStateException if the lifetime policy cannot be changed in the current state
+ * @throws AccessControlException if the caller does not have permission to change the lifetime policy
+ * @throws IllegalArgumentException if the object does not support the requested lifetime policy
+ */
+ LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+ /**
+ * Get the time the object will live once the lifetime policy conditions are no longer fulfilled
+ *
+ * @return the time to live
+ */
+ long getTimeToLive();
+
+ /**
+ * Set the ttl value
+ *
+ * @param expected the ttl the caller believes the object currently has
+ * @param desired the ttl value the caller
+ * @return the new ttl value
+ * @throws IllegalStateException if the ttl cannot be set in the current state
+ * @throws AccessControlException if the caller does not have permission to change the ttl
+ * @throws IllegalArgumentException if the object does not support the requested ttl value
+ */
+ long setTimeToLive(long expected, long desired) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+ /**
+ * Get the names of attributes that are set on this object
+ *
+ * Not that the returned collection is correct at the time the method is called, but will not reflect future
+ * additions or removals when they occur
+ *
+ * @return the collection of attribute names
+ */
+ Collection<String> getAttributeNames();
+
+
+ /**
+ * Return the value for the given attribute
+ *
+ * @param name the name of the attribute
+ * @return the value of the attribute at the object (or null if the attribute is not set
+ */
+ Object getAttribute(String name);
+
+ /**
+ * Set the value of an attribute
+ *
+ * @param name the name of the attribute to be set
+ * @param expected the value the caller believes the attribute currently has (or null if it is expected to be unset)
+ * @param desired the desired value for the attribute (or null to unset the attribute)
+ * @return the new value for the given attribute
+ * @throws IllegalStateException if the attribute cannot be set while the object is in its current state
+ * @throws AccessControlException if the caller does not have permission to alter the value of the attribute
+ * @throws IllegalArgumentException if the provided value is not valid for the given argument
+ */
+ Object setAttribute(String name, Object expected, Object desired) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+
+ /**
+ * Return the Statistics holder for the ConfiguredObject
+ *
+ * @return the Statistics holder for the ConfiguredObject (or null if none exists)
+ */
+ Statistics getStatistics();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Consumer.java b/java/broker/src/main/java/org/apache/qpid/server/model/Consumer.java
new file mode 100644
index 0000000000..958177e713
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Consumer.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.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface Consumer extends ConfiguredObject
+{
+ public String DISTRIBUTION_MODE = "distributionMode";
+ public String EXCLUSIVE = "exclusive";
+ public String NO_LOCAL = "noLocal";
+ public String SELECTOR = "selector";
+ public String SETTLEMENT_MODE = "settlementMode";
+ public String CREATED = "created";
+ public String DURABLE = "durable";
+ public String ID = "id";
+ public String LIFETIME_POLICY = "lifetimePolicy";
+ public String NAME = "name";
+ public String STATE = "state";
+ public String TIME_TO_LIVE = "timeToLive";
+ public String UPDATED = "updated";
+
+ public Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableCollection(
+ Arrays.asList(ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ DISTRIBUTION_MODE,
+ SETTLEMENT_MODE,
+ EXCLUSIVE,
+ NO_LOCAL,
+ SELECTOR));
+
+ public String BYTES_OUT = "bytesOut";
+ public String MESSAGES_OUT = "messagesOut";
+ public String STATE_CHANGED = "stateChanged";
+ public String UNACKNOWLEDGED_BYTES = "unacknowledgedBytes";
+ public String UNACKNOWLEDGED_MESSAGES = "unacknowledgedMessages";
+
+ public Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableCollection(
+ Arrays.asList(BYTES_OUT,
+ MESSAGES_OUT,
+ STATE_CHANGED,
+ UNACKNOWLEDGED_BYTES,
+ UNACKNOWLEDGED_MESSAGES)
+ );
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java
new file mode 100644
index 0000000000..e872273d05
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java
@@ -0,0 +1,91 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+public interface Exchange extends ConfiguredObject
+{
+ String BINDING_COUNT = "bindingCount";
+ String BYTES_DROPPED = "bytesDropped";
+ String BYTES_IN = "bytesIn";
+ String MESSAGES_DROPPED = "messagesDropped";
+ String MESSAGES_IN = "messagesIn";
+ String PRODUCER_COUNT = "producerCount";
+ String STATE_CHANGED = "stateChanged";
+
+ public static final Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableList(
+ Arrays.asList(BINDING_COUNT,
+ BYTES_DROPPED,
+ BYTES_IN,
+ MESSAGES_DROPPED,
+ MESSAGES_IN,
+ PRODUCER_COUNT,
+ STATE_CHANGED));
+
+ String CREATED = "created";
+ String DURABLE = "durable";
+ String ID = "id";
+ String LIFETIME_POLICY = "lifetimePolicy";
+ String NAME = "name";
+ String STATE = "state";
+ String TIME_TO_LIVE = "timeToLive";
+ String UPDATED = "updated";
+ String ALTERNATE_EXCHANGE = "alternateExchange";
+ String TYPE = "type";
+
+ // Attributes
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(
+ ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ ALTERNATE_EXCHANGE,
+ TYPE
+ ));
+
+ String getExchangeType();
+
+ //children
+ Collection<Binding> getBindings();
+ Collection<Publisher> getPublishers();
+
+ //operations
+ Binding createBinding(String bindingKey,
+ Queue queue,
+ Map<String,Object> bindingArguments,
+ Map<String, Object> attributes);
+
+
+ // Statistics
+
+ void delete();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/IllegalStateTransitionException.java b/java/broker/src/main/java/org/apache/qpid/server/model/IllegalStateTransitionException.java
new file mode 100644
index 0000000000..9cab5e2103
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/IllegalStateTransitionException.java
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+public class IllegalStateTransitionException extends RuntimeException
+{
+ public IllegalStateTransitionException()
+ {
+ }
+
+ public IllegalStateTransitionException(final String message)
+ {
+ super(message);
+ }
+
+ public IllegalStateTransitionException(final String message, final Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public IllegalStateTransitionException(final Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/LifetimePolicy.java b/java/broker/src/main/java/org/apache/qpid/server/model/LifetimePolicy.java
new file mode 100644
index 0000000000..c9006f4e71
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/LifetimePolicy.java
@@ -0,0 +1,27 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+public enum LifetimePolicy
+{
+ PERMANENT,
+ AUTO_DELETE
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Publisher.java b/java/broker/src/main/java/org/apache/qpid/server/model/Publisher.java
new file mode 100644
index 0000000000..cdb85d8023
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Publisher.java
@@ -0,0 +1,25 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+public interface Publisher extends ConfiguredObject
+{
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java b/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java
new file mode 100644
index 0000000000..7c4f0de22b
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java
@@ -0,0 +1,146 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
+
+
+public interface Queue extends ConfiguredObject
+{
+ public static final String BINDING_COUNT = "bindingCount";
+ public static final String CONSUMER_COUNT = "consumerCount";
+ public static final String CONSUMER_COUNT_WITH_CREDIT = "consumerCountWithCredit";
+ public static final String DISCARDS_TTL_BYTES = "discardsTtlBytes";
+ public static final String DISCARDS_TTL_MESSAGES = "discardsTtlMessages";
+ public static final String PERSISTENT_DEQUEUED_BYTES = "persistentDequeuedBytes";
+ public static final String PERSISTENT_DEQUEUED_MESSAGES = "persistentDequeuedMessages";
+ public static final String PERSISTENT_ENQUEUED_BYTES = "persistentEnqueuedBytes";
+ public static final String PERSISTENT_ENQUEUED_MESSAGES = "persistentEnqueuedMessages";
+ public static final String QUEUE_DEPTH_BYTES = "queueDepthBytes";
+ public static final String QUEUE_DEPTH_MESSAGES = "queueDepthMessages";
+ public static final String STATE_CHANGED = "stateChanged";
+ public static final String TOTAL_DEQUEUED_BYTES = "totalDequeuedBytes";
+ public static final String TOTAL_DEQUEUED_MESSAGES = "totalDequeuedMessages";
+ public static final String TOTAL_ENQUEUED_BYTES = "totalEnqueuedBytes";
+ public static final String TOTAL_ENQUEUED_MESSAGES = "totalEnqueuedMessages";
+ public static final String UNACKNOWLEDGED_BYTES = "unacknowledgedBytes";
+ public static final String UNACKNOWLEDGED_MESSAGES = "unacknowledgedMessages";
+
+ public static final Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableList(
+ Arrays.asList(BINDING_COUNT,
+ CONSUMER_COUNT,
+ CONSUMER_COUNT_WITH_CREDIT,
+ DISCARDS_TTL_BYTES,
+ DISCARDS_TTL_MESSAGES,
+ PERSISTENT_DEQUEUED_BYTES,
+ PERSISTENT_DEQUEUED_MESSAGES,
+ PERSISTENT_ENQUEUED_BYTES,
+ PERSISTENT_ENQUEUED_MESSAGES,
+ QUEUE_DEPTH_BYTES,
+ QUEUE_DEPTH_MESSAGES,
+ STATE_CHANGED,
+ TOTAL_DEQUEUED_BYTES,
+ TOTAL_DEQUEUED_MESSAGES,
+ TOTAL_ENQUEUED_BYTES,
+ TOTAL_ENQUEUED_MESSAGES,
+ UNACKNOWLEDGED_BYTES,
+ UNACKNOWLEDGED_MESSAGES));
+
+
+
+ public static final String ID = "id";
+ public static final String NAME = "name";
+ public static final String STATE = "state";
+ public static final String DURABLE = "durable";
+ public static final String LIFETIME_POLICY = "lifetimePolicy";
+ public static final String TIME_TO_LIVE = "timeToLive";
+ public static final String CREATED = "created";
+ public static final String UPDATED = "updated";
+
+ public static final String ALERT_REPEAT_GAP = "alertRepeatGap";
+ public static final String ALERT_THRESHOLD_MESSAGE_AGE = "alertThresholdMessageAge";
+ public static final String ALERT_THRESHOLD_MESSAGE_SIZE = "alertThresholdMessageSize";
+ public static final String ALERT_THRESHOLD_QUEUE_DEPTH_BYTES = "alertThresholdQueueDepthBytes";
+ public static final String ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES = "alertThresholdQueueDepthMessages";
+ public static final String ALTERNATE_EXCHANGE = "alternateExchange";
+ public static final String EXCLUSIVE = "exclusive";
+ public static final String MESSAGE_GROUP_KEY = "messageGroupKey";
+ public static final String MESSAGE_GROUP_DEFAULT_GROUP = "messageGroupDefaultGroup";
+ public static final String MESSAGE_GROUP_SHARED_GROUPS = "messageGroupSharedGroups";
+ public static final String LVQ_KEY = "lvqKey";
+ public static final String MAXIMUM_DELIVERY_ATTEMPTS = "maximumDeliveryAttempts";
+ public static final String NO_LOCAL = "noLocal";
+ public static final String OWNER = "owner";
+ public static final String QUEUE_FLOW_CONTROL_SIZE_BYTES = "queueFlowControlSizeBytes";
+ public static final String QUEUE_FLOW_RESUME_SIZE_BYTES = "queueFlowResumeSizeBytes";
+ public static final String QUEUE_FLOW_STOPPED = "queueFlowStopped";
+ public static final String SORT_KEY = "sortKey";
+ public static final String TYPE = "type";
+
+
+
+
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ TYPE,
+ ALTERNATE_EXCHANGE,
+ EXCLUSIVE,
+ OWNER,
+ NO_LOCAL,
+ LVQ_KEY,
+ SORT_KEY,
+ MESSAGE_GROUP_KEY,
+ MESSAGE_GROUP_DEFAULT_GROUP,
+ MESSAGE_GROUP_SHARED_GROUPS,
+ MAXIMUM_DELIVERY_ATTEMPTS,
+ QUEUE_FLOW_CONTROL_SIZE_BYTES,
+ QUEUE_FLOW_RESUME_SIZE_BYTES,
+ QUEUE_FLOW_STOPPED,
+ ALERT_THRESHOLD_MESSAGE_AGE,
+ ALERT_THRESHOLD_MESSAGE_SIZE,
+ ALERT_THRESHOLD_QUEUE_DEPTH_BYTES,
+ ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES,
+ ALERT_REPEAT_GAP
+ ));
+
+ //children
+ Collection<Binding> getBindings();
+ Collection<Consumer> getConsumers();
+
+
+ //operations
+
+ void visit(QueueEntryVisitor visitor);
+
+ void delete();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/State.java b/java/broker/src/main/java/org/apache/qpid/server/model/State.java
new file mode 100644
index 0000000000..a73b2c9d3e
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/State.java
@@ -0,0 +1,30 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+public enum State
+{
+ INITIALISING,
+ QUIESCED,
+ STOPPED,
+ ACTIVE,
+ DELETED
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java b/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java
new file mode 100644
index 0000000000..2cb81eae82
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java
@@ -0,0 +1,25 @@
+package org.apache.qpid.server.model;
+
+import java.util.Collection;
+
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.
+ */
+public interface Statistics
+{
+ Collection<String> getStatisticNames();
+ public Object getStatistic(String name);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java b/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java
new file mode 100644
index 0000000000..d8493c6df4
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.UUID;
+
+import org.apache.qpid.exchange.ExchangeDefaults;
+
+
+public class UUIDGenerator
+{
+
+ public static UUID generateUUID()
+ {
+ return UUID.randomUUID();
+ }
+
+ public static UUID generateUUID(String objectName, String virtualHostName)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(virtualHostName).append(objectName);
+ return UUID.nameUUIDFromBytes(sb.toString().getBytes());
+ }
+
+ public static UUID generateExchangeUUID(String echangeName, String virtualHostName)
+ {
+ if(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(echangeName) || echangeName.startsWith("amq.") || echangeName.startsWith("qpid."))
+ {
+ return generateUUID(echangeName, virtualHostName);
+ }
+ else
+ {
+ return generateUUID();
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
index f6980be525..b750b29952 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
@@ -58,6 +58,7 @@ import org.apache.qpid.server.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.subscription.SubscriptionImpl;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
import org.apache.qpid.transport.Sender;
@@ -1315,7 +1316,8 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException
{
- closeChannel((Integer)session.getID());
+ int channelId = ((AMQChannel)session).getChannelId();
+ closeChannel(channelId);
MethodRegistry methodRegistry = getMethodRegistry();
ChannelCloseBody responseBody =
@@ -1324,7 +1326,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
new AMQShortString(message),
0,0);
- writeFrame(responseBody.generateFrame((Integer)session.getID()));
+ writeFrame(responseBody.generateFrame(channelId));
}
public void close(AMQConstant cause, String message) throws AMQException
@@ -1454,7 +1456,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
throws AMQException
{
registerMessageDelivered(entry.getMessage().getSize());
- _protocolOutputConverter.writeDeliver(entry, _channelId, deliveryTag, sub.getConsumerTag());
+ _protocolOutputConverter.writeDeliver(entry, _channelId, deliveryTag, ((SubscriptionImpl)sub).getConsumerTag());
entry.incrementDeliveryCount();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
index a80eb46cfa..fa171815ca 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
@@ -20,10 +20,12 @@
*/
package org.apache.qpid.server.protocol;
+import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListSet;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.SimpleAMQQueue;
@@ -34,7 +36,8 @@ import org.apache.qpid.server.queue.SimpleAMQQueue;
*/
public interface AMQSessionModel extends Comparable<AMQSessionModel>
{
- public Object getID();
+ /** Unique session ID across entire broker*/
+ public UUID getId();
public AMQConnectionModel getConnectionModel();
@@ -64,4 +67,7 @@ public interface AMQSessionModel extends Comparable<AMQSessionModel>
void block(AMQQueue queue);
void unblock(AMQQueue queue);
+
+
+ boolean onSameConnection(InboundMessage inbound);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java
index e925d7a1ec..0a71fe257a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java
@@ -20,4 +20,4 @@
*/
package org.apache.qpid.server.protocol;
-public enum AmqpProtocolVersion { v0_8, v0_9, v0_9_1, v0_10 } \ No newline at end of file
+public enum AmqpProtocolVersion { v0_8, v0_9, v0_9_1, v0_10, v1_0_0 }
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
index 3b26f05f84..652ffee004 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
@@ -175,6 +175,28 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
(byte) 10
};
+ private static final byte[] AMQP_1_0_0_HEADER =
+ new byte[] { (byte) 'A',
+ (byte) 'M',
+ (byte) 'Q',
+ (byte) 'P',
+ (byte) 0,
+ (byte) 1,
+ (byte) 0,
+ (byte) 0
+ };
+
+ private static final byte[] AMQP_SASL_1_0_0_HEADER =
+ new byte[] { (byte) 'A',
+ (byte) 'M',
+ (byte) 'Q',
+ (byte) 'P',
+ (byte) 3,
+ (byte) 1,
+ (byte) 0,
+ (byte) 0
+ };
+
public void setNetworkConnection(NetworkConnection networkConnection)
{
setNetworkConnection(networkConnection, networkConnection.getSender());
@@ -289,8 +311,48 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
}
};
+ private DelegateCreator creator_1_0_0 = new DelegateCreator()
+ {
+
+ public AmqpProtocolVersion getVersion()
+ {
+ return AmqpProtocolVersion.v1_0_0;
+ }
+
+
+ public byte[] getHeaderIdentifier()
+ {
+ return AMQP_1_0_0_HEADER;
+ }
+
+ public ServerProtocolEngine getProtocolEngine()
+ {
+ return new ProtocolEngine_1_0_0(_appRegistry,_id);
+ }
+ };
+
+ private DelegateCreator creator_1_0_0_SASL = new DelegateCreator()
+ {
+
+ public AmqpProtocolVersion getVersion()
+ {
+ return AmqpProtocolVersion.v1_0_0;
+ }
+
+
+ public byte[] getHeaderIdentifier()
+ {
+ return AMQP_SASL_1_0_0_HEADER;
+ }
+
+ public ServerProtocolEngine getProtocolEngine()
+ {
+ return new ProtocolEngine_1_0_0_SASL(_network, _appRegistry, _id);
+ }
+ };
+
private final DelegateCreator[] _creators =
- new DelegateCreator[] { creator_0_8, creator_0_9, creator_0_9_1, creator_0_10 };
+ new DelegateCreator[] { creator_0_8, creator_0_9, creator_0_9_1, creator_0_10, creator_1_0_0_SASL, creator_1_0_0 };
private class ClosedDelegateProtocolEngine implements ServerProtocolEngine
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java
new file mode 100755
index 0000000000..f31ad5052b
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java
@@ -0,0 +1,394 @@
+/*
+ *
+ * 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;
+
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.security.auth.callback.CallbackHandler;
+import org.apache.qpid.amqp_1_0.codec.FrameWriter;
+import org.apache.qpid.amqp_1_0.framing.AMQFrame;
+import org.apache.qpid.amqp_1_0.framing.FrameHandler;
+import org.apache.qpid.amqp_1_0.framing.OversizeFrameException;
+import org.apache.qpid.amqp_1_0.transport.CallbackHandlerSource;
+import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint;
+import org.apache.qpid.amqp_1_0.transport.Container;
+import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler;
+import org.apache.qpid.amqp_1_0.type.Binary;
+import org.apache.qpid.amqp_1_0.type.FrameBody;
+import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.configuration.ConfigStore;
+import org.apache.qpid.server.configuration.ConnectionConfigType;
+import org.apache.qpid.server.protocol.v1_0.Connection_1_0;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.network.NetworkConnection;
+
+public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHandler
+{
+ static final AtomicLong _connectionIdSource = new AtomicLong(0L);
+
+ //private NetworkConnection _networkDriver;
+ private long _readBytes;
+ private long _writtenBytes;
+ private final UUID _id;
+ private final IApplicationRegistry _appRegistry;
+ private long _createTime = System.currentTimeMillis();
+ private ConnectionEndpoint _conn;
+ private final long _connectionId;
+
+ private static final ByteBuffer HEADER =
+ ByteBuffer.wrap(new byte[]
+ {
+ (byte)'A',
+ (byte)'M',
+ (byte)'Q',
+ (byte)'P',
+ (byte) 0,
+ (byte) 1,
+ (byte) 0,
+ (byte) 0
+ });
+
+ private FrameWriter _frameWriter;
+ private FrameHandler _frameHandler;
+ private Object _sendLock = new Object();
+ private byte _major;
+ private byte _minor;
+ private byte _revision;
+ private NetworkConnection _network;
+ private Sender<ByteBuffer> _sender;
+
+
+ static enum State {
+ A,
+ M,
+ Q,
+ P,
+ PROTOCOL,
+ MAJOR,
+ MINOR,
+ REVISION,
+ FRAME
+ }
+
+ private State _state = State.A;
+
+
+
+ public ProtocolEngine_1_0_0(final IApplicationRegistry appRegistry, long id)
+ {
+ _id = appRegistry.getConfigStore().createId();
+ _appRegistry = appRegistry;
+ _connectionId = id;
+ }
+
+
+ public SocketAddress getRemoteAddress()
+ {
+ return _network.getRemoteAddress();
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return _network.getLocalAddress();
+ }
+
+ public long getReadBytes()
+ {
+ return _readBytes;
+ }
+
+ public long getWrittenBytes()
+ {
+ return _writtenBytes;
+ }
+
+ public void writerIdle()
+ {
+ //Todo
+ }
+
+ public void readerIdle()
+ {
+ //Todo
+ }
+
+ public void setNetworkConnection(final NetworkConnection network, final Sender<ByteBuffer> sender)
+ {
+ _network = network;
+ _sender = sender;
+
+ Container container = new Container(_appRegistry.getBrokerId().toString());
+
+ _conn = new ConnectionEndpoint(container,asCallbackHandlerSource(_appRegistry.getAuthenticationManager()));
+ _conn.setConnectionEventListener(new Connection_1_0(_appRegistry));
+ _conn.setFrameOutputHandler(this);
+ _conn.setRemoteAddress(_network.getRemoteAddress());
+
+ _frameWriter = new FrameWriter(_conn.getDescribedTypeRegistry());
+ _frameHandler = new FrameHandler(_conn);
+
+ _sender.send(HEADER.duplicate());
+ _sender.flush();
+ }
+
+ private CallbackHandlerSource asCallbackHandlerSource(final AuthenticationManager authenticationManager)
+ {
+ return new CallbackHandlerSource()
+ {
+ @Override
+ public CallbackHandler getHandler(String mechanism)
+ {
+ return authenticationManager.getHandler(mechanism);
+ }
+ };
+ }
+
+ public String getAddress()
+ {
+ return getRemoteAddress().toString();
+ }
+
+
+ public ConfigStore getConfigStore()
+ {
+ return _appRegistry.getConfigStore();
+ }
+
+ public UUID getId()
+ {
+ return _id;
+ }
+
+ public ConnectionConfigType getConfigType()
+ {
+ return ConnectionConfigType.getInstance();
+ }
+
+ public boolean isDurable()
+ {
+ return false;
+ }
+
+ public synchronized void received(ByteBuffer msg)
+ {
+ if(RAW_LOGGER.isLoggable(Level.FINE))
+ {
+ ByteBuffer dup = msg.duplicate();
+ byte[] data = new byte[dup.remaining()];
+ dup.get(data);
+ Binary bin = new Binary(data);
+ RAW_LOGGER.fine("RECV[" + getRemoteAddress() + "] : " + bin.toString());
+ }
+ _readBytes += msg.remaining();
+ switch(_state)
+ {
+ case A:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ break;
+ }
+ case M:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ _state = State.M;
+ break;
+ }
+
+ case Q:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ _state = State.Q;
+ break;
+ }
+ case P:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ _state = State.P;
+ break;
+ }
+ case PROTOCOL:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ _state = State.PROTOCOL;
+ break;
+ }
+ case MAJOR:
+ if(msg.hasRemaining())
+ {
+ _major = msg.get();
+ }
+ else
+ {
+ _state = State.MAJOR;
+ break;
+ }
+ case MINOR:
+ if(msg.hasRemaining())
+ {
+ _minor = msg.get();
+ }
+ else
+ {
+ _state = State.MINOR;
+ break;
+ }
+ case REVISION:
+ if(msg.hasRemaining())
+ {
+ _revision = msg.get();
+
+ _state = State.FRAME;
+ }
+ else
+ {
+ _state = State.REVISION;
+ break;
+ }
+ case FRAME:
+ if(msg.hasRemaining())
+ {
+ _frameHandler.parse(msg);
+ }
+ }
+
+ }
+
+ public void exception(Throwable t)
+ {
+ t.printStackTrace();
+ }
+
+ public void closed()
+ {
+ _conn.inputClosed();
+ if(_conn != null && _conn.getConnectionEventListener() != null)
+ {
+ ((Connection_1_0)_conn.getConnectionEventListener()).closed();
+ }
+
+ }
+
+ public long getCreateTime()
+ {
+ return _createTime;
+ }
+
+
+ public boolean canSend()
+ {
+ return true;
+ }
+
+ public void send(final AMQFrame amqFrame)
+ {
+ send(amqFrame, null);
+ }
+
+ private final Logger FRAME_LOGGER = Logger.getLogger("FRM");
+ private final Logger RAW_LOGGER = Logger.getLogger("RAW");
+
+
+ public void send(final AMQFrame amqFrame, ByteBuffer buf)
+ {
+ synchronized(_sendLock)
+ {
+
+ if(FRAME_LOGGER.isLoggable(Level.FINE))
+ {
+ FRAME_LOGGER.fine("SEND[" + getRemoteAddress() + "|" + amqFrame.getChannel() + "] : " + amqFrame.getFrameBody());
+ }
+
+
+ _frameWriter.setValue(amqFrame);
+
+
+
+ ByteBuffer dup = ByteBuffer.allocate(_conn.getMaxFrameSize());
+
+ int size = _frameWriter.writeToBuffer(dup);
+ if(size > _conn.getMaxFrameSize())
+ {
+ throw new OversizeFrameException(amqFrame,size);
+ }
+
+ dup.flip();
+ _writtenBytes += dup.limit();
+
+ if(RAW_LOGGER.isLoggable(Level.FINE))
+ {
+ ByteBuffer dup2 = dup.duplicate();
+ byte[] data = new byte[dup2.remaining()];
+ dup2.get(data);
+ Binary bin = new Binary(data);
+ RAW_LOGGER.fine("SEND[" + getRemoteAddress() + "] : " + bin.toString());
+ }
+
+
+ _sender.send(dup);
+ _sender.flush();
+
+ }
+ }
+
+ public void send(short channel, FrameBody body)
+ {
+ AMQFrame frame = AMQFrame.createAMQFrame(channel, body);
+ send(frame);
+
+ }
+
+ public void close()
+ {
+ //TODO
+ }
+
+ public long getConnectionId()
+ {
+ return _connectionId;
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java
new file mode 100644
index 0000000000..ffd5e750b4
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java
@@ -0,0 +1,449 @@
+/*
+ *
+ * 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;
+
+import java.io.PrintWriter;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.security.auth.callback.CallbackHandler;
+import org.apache.qpid.amqp_1_0.codec.FrameWriter;
+import org.apache.qpid.amqp_1_0.codec.ProtocolHandler;
+import org.apache.qpid.amqp_1_0.framing.AMQFrame;
+import org.apache.qpid.amqp_1_0.framing.OversizeFrameException;
+import org.apache.qpid.amqp_1_0.framing.SASLFrameHandler;
+import org.apache.qpid.amqp_1_0.transport.CallbackHandlerSource;
+import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint;
+import org.apache.qpid.amqp_1_0.transport.Container;
+import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler;
+import org.apache.qpid.amqp_1_0.type.Binary;
+import org.apache.qpid.amqp_1_0.type.FrameBody;
+import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.configuration.ConfigStore;
+import org.apache.qpid.server.configuration.ConnectionConfigType;
+import org.apache.qpid.server.protocol.v1_0.Connection_1_0;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.network.NetworkConnection;
+
+public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOutputHandler
+{
+ private long _readBytes;
+ private long _writtenBytes;
+ private final UUID _id;
+ private final IApplicationRegistry _appRegistry;
+ private long _createTime = System.currentTimeMillis();
+ private ConnectionEndpoint _conn;
+ private long _connectionId;
+
+ private static final ByteBuffer HEADER =
+ ByteBuffer.wrap(new byte[]
+ {
+ (byte)'A',
+ (byte)'M',
+ (byte)'Q',
+ (byte)'P',
+ (byte) 3,
+ (byte) 1,
+ (byte) 0,
+ (byte) 0
+ });
+
+ private static final ByteBuffer PROTOCOL_HEADER =
+ ByteBuffer.wrap(new byte[]
+ {
+ (byte)'A',
+ (byte)'M',
+ (byte)'Q',
+ (byte)'P',
+ (byte) 0,
+ (byte) 1,
+ (byte) 0,
+ (byte) 0
+ });
+
+
+ private FrameWriter _frameWriter;
+ private ProtocolHandler _frameHandler;
+ private ByteBuffer _buf = ByteBuffer.allocate(1024 * 1024);
+ private Object _sendLock = new Object();
+ private byte _major;
+ private byte _minor;
+ private byte _revision;
+ private PrintWriter _out;
+ private NetworkConnection _network;
+ private Sender<ByteBuffer> _sender;
+
+
+ static enum State {
+ A,
+ M,
+ Q,
+ P,
+ PROTOCOL,
+ MAJOR,
+ MINOR,
+ REVISION,
+ FRAME
+ }
+
+ private State _state = State.A;
+
+
+ public ProtocolEngine_1_0_0_SASL(final NetworkConnection networkDriver, final IApplicationRegistry appRegistry,
+ long id)
+ {
+ _id = appRegistry.getConfigStore().createId();
+ _connectionId = id;
+ _appRegistry = appRegistry;
+
+ if(networkDriver != null)
+ {
+ setNetworkConnection(networkDriver, networkDriver.getSender());
+ }
+ }
+
+
+ public SocketAddress getRemoteAddress()
+ {
+ return _network.getRemoteAddress();
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return _network.getLocalAddress();
+ }
+
+ public long getReadBytes()
+ {
+ return _readBytes;
+ }
+
+ public long getWrittenBytes()
+ {
+ return _writtenBytes;
+ }
+
+ public void writerIdle()
+ {
+ //Todo
+ }
+
+ public void readerIdle()
+ {
+ //Todo
+ }
+
+ public void setNetworkConnection(final NetworkConnection network, final Sender<ByteBuffer> sender)
+ {
+ _network = network;
+ _sender = sender;
+
+ Container container = new Container(_appRegistry.getBrokerId().toString());
+
+ _conn = new ConnectionEndpoint(container, asCallbackHandlerSource(ApplicationRegistry.getInstance()
+ .getAuthenticationManager()));
+ _conn.setConnectionEventListener(new Connection_1_0(_appRegistry));
+ _conn.setRemoteAddress(getRemoteAddress());
+
+
+ _conn.setFrameOutputHandler(this);
+ _conn.setSaslFrameOutput(this);
+
+ _conn.setOnSaslComplete(new Runnable()
+ {
+
+
+ public void run()
+ {
+ if(_conn.isAuthenticated())
+ {
+ _sender.send(PROTOCOL_HEADER.duplicate());
+ _sender.flush();
+ }
+ else
+ {
+ _network.close();
+ }
+ }
+ });
+ _frameWriter = new FrameWriter(_conn.getDescribedTypeRegistry());
+ _frameHandler = new SASLFrameHandler(_conn);
+
+ _sender.send(HEADER.duplicate());
+ _sender.flush();
+
+ _conn.initiateSASL();
+
+
+ }
+
+ private CallbackHandlerSource asCallbackHandlerSource(final AuthenticationManager authenticationManager)
+ {
+ return new CallbackHandlerSource()
+ {
+ @Override
+ public CallbackHandler getHandler(String mechanism)
+ {
+ return authenticationManager.getHandler(mechanism);
+ }
+ };
+ }
+
+ public String getAddress()
+ {
+ return getRemoteAddress().toString();
+ }
+
+
+ public ConfigStore getConfigStore()
+ {
+ return _appRegistry.getConfigStore();
+ }
+
+ public UUID getId()
+ {
+ return _id;
+ }
+
+ public ConnectionConfigType getConfigType()
+ {
+ return ConnectionConfigType.getInstance();
+ }
+
+ public boolean isDurable()
+ {
+ return false;
+ }
+
+ private final Logger RAW_LOGGER = Logger.getLogger("RAW");
+
+
+ public synchronized void received(ByteBuffer msg)
+ {
+ if(RAW_LOGGER.isLoggable(Level.FINE))
+ {
+ ByteBuffer dup = msg.duplicate();
+ byte[] data = new byte[dup.remaining()];
+ dup.get(data);
+ Binary bin = new Binary(data);
+ RAW_LOGGER.fine("RECV[" + getRemoteAddress() + "] : " + bin.toString());
+ }
+ _readBytes += msg.remaining();
+ switch(_state)
+ {
+ case A:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ break;
+ }
+ case M:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ _state = State.M;
+ break;
+ }
+
+ case Q:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ _state = State.Q;
+ break;
+ }
+ case P:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ _state = State.P;
+ break;
+ }
+ case PROTOCOL:
+ if(msg.hasRemaining())
+ {
+ msg.get();
+ }
+ else
+ {
+ _state = State.PROTOCOL;
+ break;
+ }
+ case MAJOR:
+ if(msg.hasRemaining())
+ {
+ _major = msg.get();
+ }
+ else
+ {
+ _state = State.MAJOR;
+ break;
+ }
+ case MINOR:
+ if(msg.hasRemaining())
+ {
+ _minor = msg.get();
+ }
+ else
+ {
+ _state = State.MINOR;
+ break;
+ }
+ case REVISION:
+ if(msg.hasRemaining())
+ {
+ _revision = msg.get();
+
+ _state = State.FRAME;
+ }
+ else
+ {
+ _state = State.REVISION;
+ break;
+ }
+ case FRAME:
+ if(msg.hasRemaining())
+ {
+ _frameHandler = _frameHandler.parse(msg);
+ }
+ }
+
+ }
+
+ public void exception(Throwable t)
+ {
+ t.printStackTrace();
+ }
+
+ public void closed()
+ {
+ // todo
+ _conn.inputClosed();
+ if(_conn != null && _conn.getConnectionEventListener() != null)
+ {
+ ((Connection_1_0)_conn.getConnectionEventListener()).closed();
+ }
+
+ }
+
+ public long getCreateTime()
+ {
+ return _createTime;
+ }
+
+
+ public boolean canSend()
+ {
+ return true;
+ }
+
+ public void send(final AMQFrame amqFrame)
+ {
+ send(amqFrame, null);
+ }
+
+ private static final Logger FRAME_LOGGER = Logger.getLogger("FRM");
+
+
+ public void send(final AMQFrame amqFrame, ByteBuffer buf)
+ {
+
+ synchronized(_sendLock)
+ {
+
+ if(FRAME_LOGGER.isLoggable(Level.FINE))
+ {
+ FRAME_LOGGER.fine("SEND[" + getRemoteAddress() + "|" + amqFrame.getChannel() + "] : " + amqFrame.getFrameBody());
+ }
+
+
+ _frameWriter.setValue(amqFrame);
+
+
+
+ ByteBuffer dup = ByteBuffer.allocate(_conn.getMaxFrameSize());
+
+ int size = _frameWriter.writeToBuffer(dup);
+ if(size > _conn.getMaxFrameSize())
+ {
+ throw new OversizeFrameException(amqFrame,size);
+ }
+
+ dup.flip();
+ _writtenBytes += dup.limit();
+
+ if(RAW_LOGGER.isLoggable(Level.FINE))
+ {
+ ByteBuffer dup2 = dup.duplicate();
+ byte[] data = new byte[dup2.remaining()];
+ dup2.get(data);
+ Binary bin = new Binary(data);
+ RAW_LOGGER.fine("SEND[" + getRemoteAddress() + "] : " + bin.toString());
+ }
+
+
+ _sender.send(dup);
+ _sender.flush();
+
+
+ }
+ }
+
+ public void send(short channel, FrameBody body)
+ {
+ AMQFrame frame = AMQFrame.createAMQFrame(channel, body);
+ send(frame);
+
+ }
+
+ public void close()
+ {
+ _sender.close();
+ }
+
+ public void setLogOutput(final PrintWriter out)
+ {
+ _out = out;
+ }
+
+ public long getConnectionId()
+ {
+ return _connectionId;
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
new file mode 100644
index 0000000000..318a240b27
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
@@ -0,0 +1,98 @@
+/*
+ *
+ * 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.transport.ConnectionEventListener;
+import org.apache.qpid.amqp_1_0.transport.SessionEndpoint;
+
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Connection_1_0 implements ConnectionEventListener
+{
+
+ private IApplicationRegistry _appRegistry;
+ private VirtualHost _vhost;
+
+
+ public static interface Task
+ {
+ public void doTask(Connection_1_0 connection);
+ }
+
+
+ private List<Task> _closeTasks =
+ Collections.synchronizedList(new ArrayList<Task>());
+
+
+
+ public Connection_1_0(IApplicationRegistry appRegistry)
+ {
+ _appRegistry = appRegistry;
+ _vhost = _appRegistry.getVirtualHostRegistry().getDefaultVirtualHost();
+ }
+
+ public void remoteSessionCreation(SessionEndpoint endpoint)
+ {
+ Session_1_0 session = new Session_1_0(_vhost, _appRegistry, this);
+ endpoint.setSessionEventListener(session);
+ }
+
+
+ void removeConnectionCloseTask(final Task task)
+ {
+ _closeTasks.remove( task );
+ }
+
+ void addConnectionCloseTask(final Task task)
+ {
+ _closeTasks.add( task );
+ }
+
+ public void closeReceived()
+ {
+ List<Task> taskCopy;
+ synchronized (_closeTasks)
+ {
+ taskCopy = new ArrayList<Task>(_closeTasks);
+ }
+ for(Task task : taskCopy)
+ {
+ task.doTask(this);
+ }
+ synchronized (_closeTasks)
+ {
+ _closeTasks.clear();
+ }
+
+ }
+
+ public void closed()
+ {
+ closeReceived();
+ }
+
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Destination.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Destination.java
new file mode 100644
index 0000000000..d45758391c
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Destination.java
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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;
+
+
+public interface Destination
+{
+
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java
new file mode 100644
index 0000000000..ba1a1ca45c
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java
@@ -0,0 +1,108 @@
+/*
+ *
+ * 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 java.util.List;
+import org.apache.qpid.AMQException;
+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.TerminusDurability;
+import org.apache.qpid.amqp_1_0.type.messaging.TerminusExpiryPolicy;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.queue.BaseQueue;
+import org.apache.qpid.server.txn.ServerTransaction;
+
+public class ExchangeDestination implements ReceivingDestination, SendingDestination
+{
+ private static final Accepted ACCEPTED = new Accepted();
+ private static final Outcome[] OUTCOMES = { ACCEPTED };
+
+ private Exchange _exchange;
+ private TerminusDurability _durability;
+ private TerminusExpiryPolicy _expiryPolicy;
+
+ public ExchangeDestination(Exchange 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 List<? extends BaseQueue> queues = _exchange.route(message);
+
+ txn.enqueue(queues,message, new ServerTransaction.Action()
+ {
+
+ BaseQueue[] _queues = queues.toArray(new BaseQueue[queues.size()]);
+
+ public void postCommit()
+ {
+ for(int i = 0; i < _queues.length; i++)
+ {
+ try
+ {
+ _queues[i].enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ // TODO
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public void onRollback()
+ {
+ // NO-OP
+ }
+ }, System.currentTimeMillis());
+
+ return ACCEPTED;
+ }
+
+ TerminusDurability getDurability()
+ {
+ return _durability;
+ }
+
+ TerminusExpiryPolicy getExpiryPolicy()
+ {
+ return _expiryPolicy;
+ }
+
+ public int getCredit()
+ {
+ // TODO - fix
+ return 20000;
+ }
+
+ public Exchange getExchange()
+ {
+ return _exchange;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java
new file mode 100644
index 0000000000..42eea05d37
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java
@@ -0,0 +1,59 @@
+package org.apache.qpid.server.protocol.v1_0;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class LinkRegistry
+{
+ private final Map<String, SendingLink_1_0> _sendingLinks = new HashMap<String, SendingLink_1_0>();
+ private final Map<String, ReceivingLink_1_0> _receivingLinks = new HashMap<String, ReceivingLink_1_0>();
+
+ public synchronized SendingLink_1_0 getDurableSendingLink(String name)
+ {
+ return _sendingLinks.get(name);
+ }
+
+ public synchronized boolean registerSendingLink(String name, SendingLink_1_0 link)
+ {
+ if(_sendingLinks.containsKey(name))
+ {
+ return false;
+ }
+ else
+ {
+ _sendingLinks.put(name, link);
+ return true;
+ }
+ }
+
+ public synchronized boolean unregisterSendingLink(String name)
+ {
+ if(!_sendingLinks.containsKey(name))
+ {
+ return false;
+ }
+ else
+ {
+ _sendingLinks.remove(name);
+ return true;
+ }
+ }
+
+ public synchronized ReceivingLink_1_0 getDurableReceivingLink(String name)
+ {
+ return _receivingLinks.get(name);
+ }
+
+ public synchronized boolean registerReceivingLink(String name, ReceivingLink_1_0 link)
+ {
+ if(_receivingLinks.containsKey(name))
+ {
+ return false;
+ }
+ else
+ {
+ _receivingLinks.put(name, link);
+ return true;
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Link_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Link_1_0.java
new file mode 100644
index 0000000000..db81d3b205
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Link_1_0.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.v1_0;
+
+public interface Link_1_0
+{
+ void start();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java
new file mode 100644
index 0000000000..140a815f57
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java
@@ -0,0 +1,172 @@
+/*
+ *
+ * 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 java.lang.ref.WeakReference;
+import java.nio.ByteBuffer;
+import java.util.List;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.configuration.SessionConfig;
+import org.apache.qpid.server.message.InboundMessage;
+import org.apache.qpid.server.message.MessageMetaData_1_0;
+import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.store.StoredMessage;
+
+public class Message_1_0 implements ServerMessage, InboundMessage
+{
+ private final StoredMessage<MessageMetaData_1_0> _storedMessage;
+ private List<ByteBuffer> _fragments;
+ private WeakReference<Session_1_0> _session;
+
+
+ public Message_1_0(final StoredMessage<MessageMetaData_1_0> storedMessage,
+ final List<ByteBuffer> fragments,
+ final Session_1_0 session)
+ {
+ _storedMessage = storedMessage;
+ _fragments = fragments;
+ _session = new WeakReference<Session_1_0>(session);
+ }
+
+ public String getRoutingKey()
+ {
+ Object routingKey = getMessageHeader().getHeader("routing-key");
+ if(routingKey != null)
+ {
+ return routingKey.toString();
+ }
+ else
+ {
+ return getMessageHeader().getSubject();
+ }
+ }
+
+ public AMQShortString getRoutingKeyShortString()
+ {
+ return AMQShortString.valueOf(getRoutingKey());
+ }
+
+ private MessageMetaData_1_0 getMessageMetaData()
+ {
+ return _storedMessage.getMetaData();
+ }
+
+ public MessageMetaData_1_0.MessageHeader_1_0 getMessageHeader()
+ {
+ return getMessageMetaData().getMessageHeader();
+ }
+
+ public StoredMessage getStoredMessage()
+ {
+ return _storedMessage;
+ }
+
+ public boolean isPersistent()
+ {
+ return getMessageMetaData().isPersistent();
+ }
+
+ public boolean isRedelivered()
+ {
+ // TODO
+ return false;
+ }
+
+ public long getSize()
+ {
+ // TODO
+ return 0l;
+ }
+
+ public boolean isImmediate()
+ {
+ return false;
+ }
+
+ public long getExpiration()
+ {
+ return getMessageHeader().getExpiration();
+ }
+
+ public MessageReference<Message_1_0> newReference()
+ {
+ return new Reference(this);
+ }
+
+ public long getMessageNumber()
+ {
+ return _storedMessage.getMessageNumber();
+ }
+
+ public long getArrivalTime()
+ {
+ return 0; //TODO
+ }
+
+ public int getContent(final ByteBuffer buf, final int offset)
+ {
+ return _storedMessage.getContent(offset, buf);
+ }
+
+ public ByteBuffer getContent(int offset, int size)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(size);
+ buf.limit(getContent(buf, offset));
+
+ return buf;
+ }
+
+ public SessionConfig getSessionConfig()
+ {
+ return null; //TODO
+ }
+
+ public List<ByteBuffer> getFragments()
+ {
+ return _fragments;
+ }
+
+ public Session_1_0 getSession()
+ {
+ return _session.get();
+ }
+
+ public static class Reference extends MessageReference<Message_1_0>
+ {
+ public Reference(Message_1_0 message)
+ {
+ super(message);
+ }
+
+ protected void onReference(Message_1_0 message)
+ {
+
+ }
+
+ protected void onRelease(Message_1_0 message)
+ {
+
+ }
+
+}
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java
new file mode 100644
index 0000000000..af3f0b7872
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java
@@ -0,0 +1,100 @@
+/*
+ *
+ * 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.AMQException;
+import org.apache.qpid.server.queue.AMQQueue;
+
+import org.apache.qpid.server.txn.ServerTransaction;
+
+import java.util.Arrays;
+
+public class QueueDestination implements SendingDestination, ReceivingDestination
+{
+ private static final Accepted ACCEPTED = new Accepted();
+ private static final Outcome[] OUTCOMES = new Outcome[] { ACCEPTED };
+
+
+ private AMQQueue _queue;
+
+ public QueueDestination(AMQQueue queue)
+ {
+ _queue = queue;
+ }
+
+ public Outcome[] getOutcomes()
+ {
+ return OUTCOMES;
+ }
+
+ public Outcome send(final Message_1_0 message, ServerTransaction txn)
+ {
+
+ try
+ {
+ txn.enqueue(_queue,message, new ServerTransaction.Action()
+ {
+
+
+ public void postCommit()
+ {
+ try
+ {
+
+ _queue.enqueue(message);
+ }
+ catch (Exception e)
+ {
+ // TODO
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public void onRollback()
+ {
+ // NO-OP
+ }
+ });
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ return ACCEPTED;
+ }
+
+ public int getCredit()
+ {
+ // TODO - fix
+ return 100;
+ }
+
+ public AMQQueue getQueue()
+ {
+ return _queue;
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingDestination.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingDestination.java
new file mode 100644
index 0000000000..4ae0596e25
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingDestination.java
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol.v1_0;
+
+import org.apache.qpid.amqp_1_0.type.Outcome;
+
+import org.apache.qpid.server.txn.ServerTransaction;
+
+public interface ReceivingDestination extends Destination
+{
+
+ Outcome[] getOutcomes();
+
+ Outcome send(Message_1_0 message, ServerTransaction txn);
+
+ int getCredit();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java
new file mode 100644
index 0000000000..6da5081185
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java
@@ -0,0 +1,51 @@
+package org.apache.qpid.server.protocol.v1_0;
+
+import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler;
+import org.apache.qpid.amqp_1_0.transport.ReceivingLinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.SendingLinkEndpoint;
+import org.apache.qpid.amqp_1_0.type.Binary;
+import org.apache.qpid.amqp_1_0.type.DeliveryState;
+import org.apache.qpid.amqp_1_0.type.Source;
+import org.apache.qpid.amqp_1_0.type.Target;
+
+public class ReceivingLinkAttachment
+{
+ private final Session_1_0 _session;
+ private final ReceivingLinkEndpoint _endpoint;
+
+ public ReceivingLinkAttachment(final Session_1_0 session, final ReceivingLinkEndpoint endpoint)
+ {
+ _session = session;
+ _endpoint = endpoint;
+ }
+
+ public Session_1_0 getSession()
+ {
+ return _session;
+ }
+
+ public ReceivingLinkEndpoint getEndpoint()
+ {
+ return _endpoint;
+ }
+
+ public Source getSource()
+ {
+ return getEndpoint().getSource();
+ }
+
+ public void setDeliveryStateHandler(final DeliveryStateHandler handler)
+ {
+ getEndpoint().setDeliveryStateHandler(handler);
+ }
+
+ public void updateDisposition(final Binary deliveryTag, final DeliveryState state, final boolean settled)
+ {
+ getEndpoint().updateDisposition(deliveryTag, state, settled);
+ }
+
+ public Target getTarget()
+ {
+ return getEndpoint().getTarget();
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLink_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLink_1_0.java
new file mode 100644
index 0000000000..e097dd5c83
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLink_1_0.java
@@ -0,0 +1,305 @@
+/*
+ *
+ * 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 java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.qpid.amqp_1_0.messaging.SectionDecoderImpl;
+import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler;
+import org.apache.qpid.amqp_1_0.transport.LinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.ReceivingLinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.ReceivingLinkListener;
+import org.apache.qpid.amqp_1_0.type.Binary;
+import org.apache.qpid.amqp_1_0.type.DeliveryState;
+import org.apache.qpid.amqp_1_0.type.Outcome;
+import org.apache.qpid.amqp_1_0.type.UnsignedInteger;
+import org.apache.qpid.amqp_1_0.type.messaging.Target;
+import org.apache.qpid.amqp_1_0.type.messaging.TerminusDurability;
+import org.apache.qpid.amqp_1_0.type.transaction.TransactionalState;
+import org.apache.qpid.amqp_1_0.type.transport.Detach;
+import org.apache.qpid.amqp_1_0.type.transport.ReceiverSettleMode;
+import org.apache.qpid.amqp_1_0.type.transport.Transfer;
+import org.apache.qpid.server.message.MessageMetaData_1_0;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+public class ReceivingLink_1_0 implements ReceivingLinkListener, Link_1_0, DeliveryStateHandler
+{
+ private VirtualHost _vhost;
+
+ private ReceivingDestination _destination;
+ private SectionDecoderImpl _sectionDecoder;
+ private volatile ReceivingLinkAttachment _attachment;
+
+
+ private ArrayList<Transfer> _incompleteMessage;
+ private TerminusDurability _durability;
+
+ private Map<Binary, Outcome> _unsettledMap = Collections.synchronizedMap(new HashMap<Binary, Outcome>());
+ private boolean _resumedMessage;
+ private Binary _messageDeliveryTag;
+ private ReceiverSettleMode _receivingSettlementMode;
+
+
+ public ReceivingLink_1_0(ReceivingLinkAttachment receivingLinkAttachment, VirtualHost vhost,
+ ReceivingDestination destination)
+ {
+ _vhost = vhost;
+ _destination = destination;
+ _attachment = receivingLinkAttachment;
+ receivingLinkAttachment.setDeliveryStateHandler(this);
+
+ _durability = ((Target)receivingLinkAttachment.getTarget()).getDurable();
+
+ _sectionDecoder = new SectionDecoderImpl(receivingLinkAttachment.getEndpoint().getSession().getConnection().getDescribedTypeRegistry());
+
+
+ }
+
+ public void messageTransfer(Transfer xfr)
+ {
+ // TODO - cope with fragmented messages
+
+ List<ByteBuffer> fragments = null;
+
+
+
+ if(Boolean.TRUE.equals(xfr.getMore()) && _incompleteMessage == null)
+ {
+ _incompleteMessage = new ArrayList<Transfer>();
+ _incompleteMessage.add(xfr);
+ _resumedMessage = Boolean.TRUE.equals(xfr.getResume());
+ _messageDeliveryTag = xfr.getDeliveryTag();
+ return;
+ }
+ else if(_incompleteMessage != null)
+ {
+ _incompleteMessage.add(xfr);
+
+ if(Boolean.TRUE.equals(xfr.getMore()))
+ {
+ return;
+ }
+
+ fragments = new ArrayList<ByteBuffer>(_incompleteMessage.size());
+ for(Transfer t : _incompleteMessage)
+ {
+ fragments.add(t.getPayload());
+ }
+ _incompleteMessage=null;
+
+ }
+ else
+ {
+ _resumedMessage = Boolean.TRUE.equals(xfr.getResume());
+ _messageDeliveryTag = xfr.getDeliveryTag();
+ fragments = Collections.singletonList(xfr.getPayload());
+ }
+
+ if(_resumedMessage)
+ {
+ if(_unsettledMap.containsKey(_messageDeliveryTag))
+ {
+ Outcome outcome = _unsettledMap.get(_messageDeliveryTag);
+ boolean settled = ReceiverSettleMode.FIRST.equals(getReceivingSettlementMode());
+ getEndpoint().updateDisposition(_messageDeliveryTag, (DeliveryState) outcome, settled);
+ if(settled)
+ {
+ _unsettledMap.remove(_messageDeliveryTag);
+ }
+ }
+ else
+ {
+ System.err.println("UNEXPECTED!!");
+ System.err.println("Delivery Tag: " + _messageDeliveryTag);
+ System.err.println("_unsettledMap: " + _unsettledMap);
+
+ }
+ }
+ else
+ {
+ MessageMetaData_1_0 mmd = null;
+ List<ByteBuffer> immutableSections = new ArrayList<ByteBuffer>(3);
+ mmd = new MessageMetaData_1_0(fragments.toArray(new ByteBuffer[fragments.size()]),
+ _sectionDecoder,
+ immutableSections);
+
+ StoredMessage<MessageMetaData_1_0> storedMessage = _vhost.getMessageStore().addMessage(mmd);
+
+ boolean skipping = true;
+ int offset = 0;
+
+ for(ByteBuffer bareMessageBuf : immutableSections)
+ {
+ storedMessage.addContent(offset, bareMessageBuf.duplicate());
+ offset += bareMessageBuf.remaining();
+ }
+
+ storedMessage.flushToStore();
+
+ Message_1_0 message = new Message_1_0(storedMessage, fragments, getSession());
+
+
+ Binary transactionId = null;
+ org.apache.qpid.amqp_1_0.type.DeliveryState xfrState = xfr.getState();
+ if(xfrState != null)
+ {
+ if(xfrState instanceof TransactionalState)
+ {
+ transactionId = ((TransactionalState)xfrState).getTxnId();
+ }
+ }
+
+ ServerTransaction transaction = null;
+ if(transactionId != null)
+ {
+ transaction = getSession().getTransaction(transactionId);
+ }
+ else
+ {
+ Session_1_0 session = getSession();
+ transaction = session != null ? session.getTransaction(null) : new AutoCommitTransaction(_vhost.getMessageStore());
+ }
+
+ Outcome outcome = _destination.send(message, transaction);
+
+ DeliveryState resultantState;
+
+ if(transactionId == null)
+ {
+ resultantState = (DeliveryState) outcome;
+ }
+ else
+ {
+ TransactionalState transactionalState = new TransactionalState();
+ transactionalState.setOutcome(outcome);
+ transactionalState.setTxnId(transactionId);
+ resultantState = transactionalState;
+
+ }
+
+
+ boolean settled = transaction instanceof AutoCommitTransaction && ReceiverSettleMode.FIRST.equals(getReceivingSettlementMode());
+
+ final Binary deliveryTag = xfr.getDeliveryTag();
+
+ if(!settled)
+ {
+ _unsettledMap.put(deliveryTag, outcome);
+ }
+
+ getEndpoint().updateDisposition(deliveryTag, resultantState, settled);
+
+ if(!(transaction instanceof AutoCommitTransaction))
+ {
+ ServerTransaction.Action a;
+ transaction.addPostTransactionAction(new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ getEndpoint().updateDisposition(deliveryTag, null, true);
+ }
+
+ public void onRollback()
+ {
+ getEndpoint().updateDisposition(deliveryTag, null, true);
+ }
+ });
+ }
+ }
+ }
+
+ private ReceiverSettleMode getReceivingSettlementMode()
+ {
+ return _receivingSettlementMode;
+ }
+
+ public void remoteDetached(LinkEndpoint endpoint, Detach detach)
+ {
+ //TODO
+ // if not durable or close
+ if(!TerminusDurability.UNSETTLED_STATE.equals(_durability) ||
+ (detach != null && Boolean.TRUE.equals(detach.getClosed())))
+ {
+ endpoint.close();
+ }
+ else if(detach == null || detach.getError() != null)
+ {
+ _attachment = null;
+ }
+ }
+
+ public void start()
+ {
+ getEndpoint().setLinkCredit(UnsignedInteger.valueOf(_destination.getCredit()));
+ getEndpoint().setCreditWindow();
+ }
+
+ public ReceivingLinkEndpoint getEndpoint()
+ {
+ return _attachment.getEndpoint();
+ }
+
+
+ public Session_1_0 getSession()
+ {
+ ReceivingLinkAttachment attachment = _attachment;
+ return attachment == null ? null : attachment.getSession();
+ }
+
+ public void handle(Binary deliveryTag, DeliveryState state, Boolean settled)
+ {
+ if(Boolean.TRUE.equals(settled))
+ {
+ _unsettledMap.remove(deliveryTag);
+ }
+ }
+
+ public void setLinkAttachment(ReceivingLinkAttachment linkAttachment)
+ {
+ _attachment = linkAttachment;
+ _receivingSettlementMode = linkAttachment.getEndpoint().getReceivingSettlementMode();
+ ReceivingLinkEndpoint endpoint = linkAttachment.getEndpoint();
+ Map initialUnsettledMap = endpoint.getInitialUnsettledMap();
+
+ Map<Binary, Outcome> unsettledCopy = new HashMap<Binary, Outcome>(_unsettledMap);
+ for(Map.Entry<Binary, Outcome> entry : unsettledCopy.entrySet())
+ {
+ Binary deliveryTag = entry.getKey();
+ if(!initialUnsettledMap.containsKey(deliveryTag))
+ {
+ _unsettledMap.remove(deliveryTag);
+ }
+ }
+
+ }
+
+ public Map getUnsettledOutcomeMap()
+ {
+ return _unsettledMap;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingDestination.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingDestination.java
new file mode 100644
index 0000000000..6d601c9dda
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingDestination.java
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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;
+
+
+public interface SendingDestination extends Destination
+{
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java
new file mode 100644
index 0000000000..9d7af24135
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java
@@ -0,0 +1,44 @@
+package org.apache.qpid.server.protocol.v1_0;
+
+import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler;
+import org.apache.qpid.amqp_1_0.transport.SendingLinkEndpoint;
+import org.apache.qpid.amqp_1_0.type.Binary;
+import org.apache.qpid.amqp_1_0.type.DeliveryState;
+import org.apache.qpid.amqp_1_0.type.Source;
+
+public class SendingLinkAttachment
+{
+ private final Session_1_0 _session;
+ private final SendingLinkEndpoint _endpoint;
+
+ public SendingLinkAttachment(final Session_1_0 session, final SendingLinkEndpoint endpoint)
+ {
+ _session = session;
+ _endpoint = endpoint;
+ }
+
+ public Session_1_0 getSession()
+ {
+ return _session;
+ }
+
+ public SendingLinkEndpoint getEndpoint()
+ {
+ return _endpoint;
+ }
+
+ public Source getSource()
+ {
+ return getEndpoint().getSource();
+ }
+
+ public void setDeliveryStateHandler(final DeliveryStateHandler handler)
+ {
+ getEndpoint().setDeliveryStateHandler(handler);
+ }
+
+ public void updateDisposition(final Binary deliveryTag, final DeliveryState state, final boolean settled)
+ {
+ getEndpoint().updateDisposition(deliveryTag, state, settled);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
new file mode 100644
index 0000000000..b3e9a74d04
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
@@ -0,0 +1,648 @@
+/*
+ *
+ * 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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQInternalException;
+import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler;
+import org.apache.qpid.amqp_1_0.transport.LinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.SendingLinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.SendingLinkListener;
+import org.apache.qpid.amqp_1_0.type.AmqpErrorException;
+import org.apache.qpid.amqp_1_0.type.Binary;
+import org.apache.qpid.amqp_1_0.type.DeliveryState;
+import org.apache.qpid.amqp_1_0.type.Outcome;
+import org.apache.qpid.amqp_1_0.type.Symbol;
+import org.apache.qpid.amqp_1_0.type.UnsignedInteger;
+import org.apache.qpid.amqp_1_0.type.messaging.Accepted;
+import org.apache.qpid.amqp_1_0.type.messaging.ExactSubjectFilter;
+import org.apache.qpid.amqp_1_0.type.messaging.Filter;
+import org.apache.qpid.amqp_1_0.type.messaging.MatchingSubjectFilter;
+import org.apache.qpid.amqp_1_0.type.messaging.Modified;
+import org.apache.qpid.amqp_1_0.type.messaging.NoLocalFilter;
+import org.apache.qpid.amqp_1_0.type.messaging.Released;
+import org.apache.qpid.amqp_1_0.type.messaging.Source;
+import org.apache.qpid.amqp_1_0.type.messaging.StdDistMode;
+import org.apache.qpid.amqp_1_0.type.messaging.TerminusDurability;
+import org.apache.qpid.amqp_1_0.type.transport.AmqpError;
+import org.apache.qpid.amqp_1_0.type.transport.Detach;
+import org.apache.qpid.amqp_1_0.type.transport.Error;
+import org.apache.qpid.amqp_1_0.type.transport.Transfer;
+import org.apache.qpid.filter.SelectorParsingException;
+import org.apache.qpid.filter.selector.ParseException;
+import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.exchange.DirectExchange;
+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.model.UUIDGenerator;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryStateHandler
+{
+ private VirtualHost _vhost;
+ private SendingDestination _destination;
+
+ private Subscription_1_0 _subscription;
+ private boolean _draining;
+ private final Map<Binary, QueueEntry> _unsettledMap =
+ new HashMap<Binary, QueueEntry>();
+
+ 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<Binary> _resumeAcceptedTransfers = new ArrayList<Binary>();
+ private Runnable _closeAction;
+
+ public SendingLink_1_0(final SendingLinkAttachment linkAttachment,
+ final VirtualHost vhost,
+ final SendingDestination destination)
+ throws AmqpErrorException
+ {
+ _vhost = vhost;
+ _destination = destination;
+ _linkAttachment = linkAttachment;
+ final Source source = (Source) linkAttachment.getSource();
+ _durability = source.getDurable();
+ linkAttachment.setDeliveryStateHandler(this);
+ QueueDestination qd = null;
+ AMQQueue queue = null;
+
+
+
+ boolean noLocal = false;
+ JMSSelectorFilter messageFilter = null;
+
+ if(destination instanceof QueueDestination)
+ {
+ queue = ((QueueDestination) _destination).getQueue();
+ if(queue.getArguments() != null && queue.getArguments().containsKey("topic"))
+ {
+ source.setDistributionMode(StdDistMode.COPY);
+ }
+ qd = (QueueDestination) destination;
+
+ Map<Symbol,Filter> filters = source.getFilter();
+
+ Map<Symbol,Filter> actualFilters = new HashMap<Symbol,Filter>();
+
+ if(filters != null)
+ {
+ for(Map.Entry<Symbol,Filter> entry : filters.entrySet())
+ {
+ if(entry.getValue() instanceof NoLocalFilter)
+ {
+ actualFilters.put(entry.getKey(), entry.getValue());
+ noLocal = true;
+ }
+ else if(messageFilter == null && entry.getValue() instanceof org.apache.qpid.amqp_1_0.type.messaging.JMSSelectorFilter)
+ {
+
+ org.apache.qpid.amqp_1_0.type.messaging.JMSSelectorFilter selectorFilter = (org.apache.qpid.amqp_1_0.type.messaging.JMSSelectorFilter) entry.getValue();
+ try
+ {
+ messageFilter = new JMSSelectorFilter(selectorFilter.getValue());
+
+ actualFilters.put(entry.getKey(), entry.getValue());
+ }
+ catch (ParseException e)
+ {
+ Error error = new Error();
+ error.setCondition(AmqpError.INVALID_FIELD);
+ error.setDescription("Invalid JMS Selector: " + selectorFilter.getValue());
+ error.setInfo(Collections.singletonMap(Symbol.valueOf("field"), Symbol.valueOf("filter")));
+ throw new AmqpErrorException(error);
+ }
+ catch (SelectorParsingException e)
+ {
+ Error error = new Error();
+ error.setCondition(AmqpError.INVALID_FIELD);
+ error.setDescription("Invalid JMS Selector: " + selectorFilter.getValue());
+ error.setInfo(Collections.singletonMap(Symbol.valueOf("field"), Symbol.valueOf("filter")));
+ throw new AmqpErrorException(error);
+ }
+
+
+ }
+ }
+ }
+ source.setFilter(actualFilters.isEmpty() ? null : actualFilters);
+
+ _subscription = new Subscription_1_0(this, qd);
+ }
+ else if(destination instanceof ExchangeDestination)
+ {
+ try
+ {
+
+ ExchangeDestination exchangeDestination = (ExchangeDestination) destination;
+
+ boolean isDurable = exchangeDestination.getDurability() == TerminusDurability.CONFIGURATION
+ || exchangeDestination.getDurability() == TerminusDurability.UNSETTLED_STATE;
+ String name;
+ if(isDurable)
+ {
+ String remoteContainerId = getEndpoint().getSession().getConnection().getRemoteContainerId();
+ remoteContainerId = remoteContainerId.replace("_","__").replace(".", "_:");
+
+ String endpointName = linkAttachment.getEndpoint().getName();
+ endpointName = endpointName
+ .replace("_", "__")
+ .replace(".", "_:")
+ .replace("(", "_O")
+ .replace(")", "_C")
+ .replace("<", "_L")
+ .replace(">", "_R");
+ name = "qpid_/" + remoteContainerId + "_/" + endpointName;
+ }
+ else
+ {
+ name = UUID.randomUUID().toString();
+ }
+
+ queue = _vhost.getQueueRegistry().getQueue(name);
+ Exchange exchange = exchangeDestination.getExchange();
+
+ if(queue == null)
+ {
+ queue = AMQQueueFactory.createAMQQueueImpl(
+ UUIDGenerator.generateUUID(),
+ name,
+ isDurable,
+ null,
+ true,
+ true,
+ _vhost,
+ Collections.EMPTY_MAP);
+ }
+ else
+ {
+ List<Binding> bindings = queue.getBindings();
+ List<Binding> bindingsToRemove = new ArrayList<Binding>();
+ for(Binding existingBinding : bindings)
+ {
+ if(existingBinding.getExchange() != _vhost.getExchangeRegistry().getDefaultExchange()
+ && existingBinding.getExchange() != exchange)
+ {
+ bindingsToRemove.add(existingBinding);
+ }
+ }
+ for(Binding existingBinding : bindingsToRemove)
+ {
+ existingBinding.getExchange().removeBinding(existingBinding);
+ }
+ }
+
+
+ String binding = "";
+
+ Map<Symbol,Filter> filters = source.getFilter();
+ Map<Symbol,Filter> actualFilters = new HashMap<Symbol,Filter>();
+ boolean hasBindingFilter = false;
+ if(filters != null && !filters.isEmpty())
+ {
+
+ for(Map.Entry<Symbol,Filter> entry : filters.entrySet())
+ {
+ if(!hasBindingFilter
+ && entry.getValue() instanceof ExactSubjectFilter
+ && exchange.getType() == DirectExchange.TYPE)
+ {
+ ExactSubjectFilter filter = (ExactSubjectFilter) filters.values().iterator().next();
+ source.setFilter(filters);
+ binding = filter.getValue();
+ actualFilters.put(entry.getKey(), entry.getValue());
+ hasBindingFilter = true;
+ }
+ else if(!hasBindingFilter
+ && entry.getValue() instanceof MatchingSubjectFilter
+ && exchange.getType() == TopicExchange.TYPE)
+ {
+ MatchingSubjectFilter filter = (MatchingSubjectFilter) filters.values().iterator().next();
+ source.setFilter(filters);
+ binding = filter.getValue();
+ actualFilters.put(entry.getKey(), entry.getValue());
+ hasBindingFilter = true;
+ }
+ else if(entry.getValue() instanceof NoLocalFilter)
+ {
+ actualFilters.put(entry.getKey(), entry.getValue());
+ noLocal = true;
+ }
+ else if(messageFilter == null && entry.getValue() instanceof org.apache.qpid.amqp_1_0.type.messaging.JMSSelectorFilter)
+ {
+
+ org.apache.qpid.amqp_1_0.type.messaging.JMSSelectorFilter selectorFilter = (org.apache.qpid.amqp_1_0.type.messaging.JMSSelectorFilter) entry.getValue();
+ try
+ {
+ messageFilter = new JMSSelectorFilter(selectorFilter.getValue());
+
+ actualFilters.put(entry.getKey(), entry.getValue());
+ }
+ catch (ParseException e)
+ {
+ Error error = new Error();
+ error.setCondition(AmqpError.INVALID_FIELD);
+ error.setDescription("Invalid JMS Selector: " + selectorFilter.getValue());
+ error.setInfo(Collections.singletonMap(Symbol.valueOf("field"), Symbol.valueOf("filter")));
+ throw new AmqpErrorException(error);
+ }
+ catch (SelectorParsingException e)
+ {
+ Error error = new Error();
+ error.setCondition(AmqpError.INVALID_FIELD);
+ error.setDescription("Invalid JMS Selector: " + selectorFilter.getValue());
+ error.setInfo(Collections.singletonMap(Symbol.valueOf("field"), Symbol.valueOf("filter")));
+ throw new AmqpErrorException(error);
+ }
+
+
+ }
+ }
+ }
+ source.setFilter(actualFilters.isEmpty() ? null : actualFilters);
+
+ vhost.getBindingFactory().addBinding(binding,queue,exchange,null);
+ source.setDistributionMode(StdDistMode.COPY);
+
+ qd = new QueueDestination(queue);
+ }
+ catch (AMQSecurityException e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ }
+ catch (AMQInternalException e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ } catch (AMQException e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ }
+ _subscription = new Subscription_1_0(this, qd, true);
+
+ }
+
+ if(_subscription != null)
+ {
+ _subscription.setNoLocal(noLocal);
+ if(messageFilter!=null)
+ {
+ _subscription.setFilters(new SimpleFilterManager(messageFilter));
+ }
+
+ try
+ {
+
+ queue.registerSubscription(_subscription, false);
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace(); //TODO
+ }
+ }
+
+ }
+
+ public void resume(SendingLinkAttachment linkAttachment)
+ {
+ _linkAttachment = linkAttachment;
+
+ }
+
+ public void remoteDetached(final LinkEndpoint endpoint, final Detach detach)
+ {
+ //TODO
+ // if not durable or close
+ if(!TerminusDurability.UNSETTLED_STATE.equals(_durability))
+ {
+ AMQQueue queue = _subscription.getQueue();
+
+ try
+ {
+
+ queue.unregisterSubscription(_subscription);
+
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace(); //TODO
+ }
+
+ Modified state = new Modified();
+ state.setDeliveryFailed(true);
+
+ for(UnsettledAction action : _unsettledActionMap.values())
+ {
+
+ action.process(state,Boolean.TRUE);
+ }
+ _unsettledActionMap.clear();
+
+ endpoint.close();
+
+ if(_destination instanceof ExchangeDestination
+ && (_durability == TerminusDurability.CONFIGURATION
+ || _durability == TerminusDurability.UNSETTLED_STATE))
+ {
+ try
+ {
+ queue.delete();
+ }
+ catch(AMQException e)
+ {
+ e.printStackTrace(); // TODO - Implement
+ }
+ }
+
+ if(_closeAction != null)
+ {
+ _closeAction.run();
+ }
+ }
+ else if(detach == null || detach.getError() != null)
+ {
+ _linkAttachment = null;
+ _subscription.flowStateChanged();
+ }
+ else
+ {
+ endpoint.detach();
+ }
+ }
+
+ public void start()
+ {
+ //TODO
+ }
+
+ public SendingLinkEndpoint getEndpoint()
+ {
+ return _linkAttachment == null ? null : _linkAttachment.getEndpoint() ;
+ }
+
+ public Session_1_0 getSession()
+ {
+ return _linkAttachment == null ? null : _linkAttachment.getSession();
+ }
+
+ public void flowStateChanged()
+ {
+ if(Boolean.TRUE.equals(getEndpoint().getDrain())
+ && hasCredit())
+ {
+ _draining = true;
+ }
+
+ while(!_resumeAcceptedTransfers.isEmpty() && getEndpoint().hasCreditToSend())
+ {
+ Accepted accepted = new Accepted();
+ synchronized(getLock())
+ {
+
+ Transfer xfr = new Transfer();
+ Binary dt = _resumeAcceptedTransfers.remove(0);
+ xfr.setDeliveryTag(dt);
+ xfr.setState(accepted);
+ xfr.setResume(Boolean.TRUE);
+ getEndpoint().transfer(xfr);
+ }
+
+ }
+ if(_resumeAcceptedTransfers.isEmpty())
+ {
+ _subscription.flowStateChanged();
+ }
+
+ }
+
+ boolean hasCredit()
+ {
+ return getEndpoint().getLinkCredit().compareTo(UnsignedInteger.ZERO) > 0;
+ }
+
+ public boolean isDraining()
+ {
+ return false; //TODO
+ }
+
+ public boolean drained()
+ {
+ if(getEndpoint() != null)
+ {
+ synchronized(getEndpoint().getLock())
+ {
+ if(_draining)
+ {
+ //TODO
+ getEndpoint().drained();
+ _draining = false;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public void addUnsettled(Binary tag, UnsettledAction unsettledAction, QueueEntry queueEntry)
+ {
+ _unsettledActionMap.put(tag,unsettledAction);
+ if(getTransactionId() == null)
+ {
+ _unsettledMap.put(tag, queueEntry);
+ }
+ }
+
+ public void removeUnsettled(Binary tag)
+ {
+ _unsettledActionMap.remove(tag);
+ }
+
+ public void handle(Binary deliveryTag, DeliveryState state, Boolean settled)
+ {
+ UnsettledAction action = _unsettledActionMap.get(deliveryTag);
+ boolean localSettle = false;
+ if(action != null)
+ {
+ localSettle = action.process(state, settled);
+ if(localSettle && !Boolean.TRUE.equals(settled))
+ {
+ _linkAttachment.updateDisposition(deliveryTag, state, true);
+ }
+ }
+ if(Boolean.TRUE.equals(settled) || localSettle)
+ {
+ _unsettledActionMap.remove(deliveryTag);
+ _unsettledMap.remove(deliveryTag);
+ }
+ }
+
+ ServerTransaction getTransaction(Binary transactionId)
+ {
+ return _linkAttachment.getSession().getTransaction(transactionId);
+ }
+
+ public Binary getTransactionId()
+ {
+ SendingLinkEndpoint endpoint = getEndpoint();
+ return endpoint == null ? null : endpoint.getTransactionId();
+ }
+
+ public synchronized Object getLock()
+ {
+ return _linkAttachment == null ? this : getEndpoint().getLock();
+ }
+
+ public boolean isDetached()
+ {
+ return _linkAttachment == null || getEndpoint().isDetached();
+ }
+
+ public boolean isAttached()
+ {
+ return _linkAttachment != null && getEndpoint().isAttached();
+ }
+
+ public synchronized void setLinkAttachment(SendingLinkAttachment linkAttachment)
+ {
+
+ if(_subscription.isActive())
+ {
+ _subscription.suspend();
+ }
+
+ _linkAttachment = linkAttachment;
+
+ SendingLinkEndpoint endpoint = linkAttachment.getEndpoint();
+ endpoint.setDeliveryStateHandler(this);
+ Map initialUnsettledMap = endpoint.getInitialUnsettledMap();
+ Map<Binary, QueueEntry> unsettledCopy = new HashMap<Binary, QueueEntry>(_unsettledMap);
+ _resumeAcceptedTransfers.clear();
+ _resumeFullTransfers.clear();
+
+ for(Map.Entry<Binary, QueueEntry> entry : unsettledCopy.entrySet())
+ {
+ Binary deliveryTag = entry.getKey();
+ final QueueEntry queueEntry = entry.getValue();
+ if(initialUnsettledMap == null || !initialUnsettledMap.containsKey(deliveryTag))
+ {
+ queueEntry.setRedelivered();
+ queueEntry.release();
+ _unsettledMap.remove(deliveryTag);
+ }
+ else if(initialUnsettledMap != null && (initialUnsettledMap.get(deliveryTag) instanceof Outcome))
+ {
+ Outcome outcome = (Outcome) initialUnsettledMap.get(deliveryTag);
+
+ if(outcome instanceof Accepted)
+ {
+ AutoCommitTransaction txn = new AutoCommitTransaction(_vhost.getMessageStore());
+ if(_subscription.acquires())
+ {
+ txn.dequeue(Collections.singleton(queueEntry),
+ new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ queueEntry.discard();
+ }
+
+ public void onRollback()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ });
+ }
+ }
+ else if(outcome instanceof Released)
+ {
+ AutoCommitTransaction txn = new AutoCommitTransaction(_vhost.getMessageStore());
+ if(_subscription.acquires())
+ {
+ txn.dequeue(Collections.singleton(queueEntry),
+ new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ queueEntry.release();
+ }
+
+ public void onRollback()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ });
+ }
+ }
+ //_unsettledMap.remove(deliveryTag);
+ initialUnsettledMap.remove(deliveryTag);
+ _resumeAcceptedTransfers.add(deliveryTag);
+ }
+ else
+ {
+ _resumeFullTransfers.add(queueEntry);
+ // exists in receivers map, but not yet got an outcome ... should resend with resume = true
+ }
+ // TODO - else
+ }
+
+
+ }
+
+ public Map getUnsettledOutcomeMap()
+ {
+ Map<Binary, QueueEntry> unsettled = new HashMap<Binary, QueueEntry>(_unsettledMap);
+
+ for(Map.Entry<Binary, QueueEntry> entry : unsettled.entrySet())
+ {
+ entry.setValue(null);
+ }
+
+ return unsettled;
+ }
+
+ public void setCloseAction(Runnable action)
+ {
+ _closeAction = action;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
new file mode 100644
index 0000000000..48a551e42a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
@@ -0,0 +1,446 @@
+/*
+ *
+ * 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.transport.LinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.ReceivingLinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.SendingLinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.SessionEventListener;
+import org.apache.qpid.amqp_1_0.type.*;
+import org.apache.qpid.amqp_1_0.type.messaging.*;
+import org.apache.qpid.amqp_1_0.type.messaging.Source;
+import org.apache.qpid.amqp_1_0.type.messaging.Target;
+import org.apache.qpid.amqp_1_0.type.transaction.Coordinator;
+import org.apache.qpid.amqp_1_0.type.transaction.TxnCapability;
+import org.apache.qpid.amqp_1_0.type.transport.*;
+
+import org.apache.qpid.amqp_1_0.type.transport.Error;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import java.util.*;
+
+public class Session_1_0 implements SessionEventListener
+{
+ private static final Symbol LIFETIME_POLICY = Symbol.valueOf("lifetime-policy");
+ private IApplicationRegistry _appRegistry;
+ private VirtualHost _vhost;
+ private AutoCommitTransaction _transaction;
+
+ private final LinkedHashMap<Integer, ServerTransaction> _openTransactions =
+ new LinkedHashMap<Integer, ServerTransaction>();
+ private final Connection_1_0 _connection;
+
+
+ public Session_1_0(VirtualHost vhost, IApplicationRegistry appRegistry, final Connection_1_0 connection)
+ {
+ _appRegistry = appRegistry;
+ _vhost = vhost;
+ _transaction = new AutoCommitTransaction(vhost.getMessageStore());
+ _connection = connection;
+
+ }
+
+ public void remoteLinkCreation(final LinkEndpoint endpoint)
+ {
+
+
+ Destination destination;
+ Link_1_0 link = null;
+ Error error = null;
+
+ final LinkRegistry linkRegistry = _vhost.getLinkRegistry(endpoint.getSession().getConnection().getRemoteContainerId());
+
+
+ if(endpoint.getRole() == Role.SENDER)
+ {
+
+ SendingLink_1_0 previousLink = linkRegistry.getDurableSendingLink(endpoint.getName());
+
+ if(previousLink == null)
+ {
+
+ Target target = (Target) endpoint.getTarget();
+ Source source = (Source) endpoint.getSource();
+
+
+ if(source != null)
+ {
+ if(Boolean.TRUE.equals(source.getDynamic()))
+ {
+ AMQQueue tempQueue = createTemporaryQueue(source.getDynamicNodeProperties());
+ source.setAddress(tempQueue.getName());
+ }
+ String addr = source.getAddress();
+ AMQQueue queue = _vhost.getQueueRegistry().getQueue(addr);
+ if(queue != null)
+ {
+
+ destination = new QueueDestination(queue);
+
+
+
+ }
+ else
+ {
+ Exchange exchg = _vhost.getExchangeRegistry().getExchange(addr);
+ if(exchg != null)
+ {
+ destination = new ExchangeDestination(exchg, source.getDurable(), source.getExpiryPolicy());
+ }
+ else
+ {
+
+ endpoint.setSource(null);
+ destination = null;
+ }
+ }
+
+ }
+ else
+ {
+ destination = null;
+ }
+
+ if(destination != null)
+ {
+ final SendingLinkEndpoint sendingLinkEndpoint = (SendingLinkEndpoint) endpoint;
+ try
+ {
+ final SendingLink_1_0 sendingLink = new SendingLink_1_0(new SendingLinkAttachment(this, sendingLinkEndpoint),
+ _vhost,
+ (SendingDestination) destination
+ );
+ sendingLinkEndpoint.setLinkEventListener(sendingLink);
+ link = sendingLink;
+ if(TerminusDurability.UNSETTLED_STATE.equals(source.getDurable()))
+ {
+ linkRegistry.registerSendingLink(endpoint.getName(), sendingLink);
+ }
+ }
+ catch(AmqpErrorException e)
+ {
+ e.printStackTrace();
+ destination = null;
+ sendingLinkEndpoint.setSource(null);
+ error = e.getError();
+ }
+ }
+ }
+ else
+ {
+ Source newSource = (Source) endpoint.getSource();
+
+ Source oldSource = (Source) previousLink.getEndpoint().getSource();
+ final TerminusDurability newSourceDurable = newSource == null ? null : newSource.getDurable();
+ if(newSourceDurable != null)
+ {
+ oldSource.setDurable(newSourceDurable);
+ if(newSourceDurable.equals(TerminusDurability.NONE))
+ {
+ linkRegistry.unregisterSendingLink(endpoint.getName());
+ }
+ }
+ endpoint.setSource(oldSource);
+ SendingLinkEndpoint sendingLinkEndpoint = (SendingLinkEndpoint) endpoint;
+ previousLink.setLinkAttachment(new SendingLinkAttachment(this, sendingLinkEndpoint));
+ sendingLinkEndpoint.setLinkEventListener(previousLink);
+ link = previousLink;
+ endpoint.setLocalUnsettled(previousLink.getUnsettledOutcomeMap());
+ }
+ }
+ else
+ {
+ if(endpoint.getTarget() instanceof Coordinator)
+ {
+ Coordinator coordinator = (Coordinator) endpoint.getTarget();
+ TxnCapability[] capabilities = coordinator.getCapabilities();
+ boolean localTxn = false;
+ boolean multiplePerSession = false;
+ if(capabilities != null)
+ {
+ for(TxnCapability capability : capabilities)
+ {
+ if(capability.equals(TxnCapability.LOCAL_TXN))
+ {
+ localTxn = true;
+ }
+ else if(capability.equals(TxnCapability.MULTI_TXNS_PER_SSN))
+ {
+ multiplePerSession = true;
+ }
+ else
+ {
+ error = new Error();
+ error.setCondition(AmqpError.NOT_IMPLEMENTED);
+ error.setDescription("Unsupported capability: " + capability);
+ break;
+ }
+ }
+ }
+
+ /* if(!localTxn)
+ {
+ capabilities.add(TxnCapabilities.LOCAL_TXN);
+ }*/
+
+ final ReceivingLinkEndpoint receivingLinkEndpoint = (ReceivingLinkEndpoint) endpoint;
+ final TxnCoordinatorLink_1_0 coordinatorLink =
+ new TxnCoordinatorLink_1_0(_vhost, this, receivingLinkEndpoint, _openTransactions);
+ receivingLinkEndpoint.setLinkEventListener(coordinatorLink);
+ link = coordinatorLink;
+
+
+ }
+ else
+ {
+
+ ReceivingLink_1_0 previousLink = linkRegistry.getDurableReceivingLink(endpoint.getName());
+
+ if(previousLink == null)
+ {
+
+ Target target = (Target) endpoint.getTarget();
+
+ if(target != null)
+ {
+ if(Boolean.TRUE.equals(target.getDynamic()))
+ {
+
+ AMQQueue tempQueue = createTemporaryQueue(target.getDynamicNodeProperties());
+ target.setAddress(tempQueue.getName());
+ }
+
+ String addr = target.getAddress();
+ Exchange exchg = _vhost.getExchangeRegistry().getExchange(addr);
+ if(exchg != null)
+ {
+ destination = new ExchangeDestination(exchg, target.getDurable(),
+ target.getExpiryPolicy());
+ }
+ else
+ {
+ AMQQueue queue = _vhost.getQueueRegistry().getQueue(addr);
+ if(queue != null)
+ {
+
+ destination = new QueueDestination(queue);
+ }
+ else
+ {
+ endpoint.setTarget(null);
+ destination = null;
+ }
+
+ }
+
+
+ }
+ else
+ {
+ destination = null;
+ }
+ if(destination != null)
+ {
+ final ReceivingLinkEndpoint receivingLinkEndpoint = (ReceivingLinkEndpoint) endpoint;
+ final ReceivingLink_1_0 receivingLink = new ReceivingLink_1_0(new ReceivingLinkAttachment(this, receivingLinkEndpoint), _vhost,
+ (ReceivingDestination) destination);
+ receivingLinkEndpoint.setLinkEventListener(receivingLink);
+ link = receivingLink;
+ if(TerminusDurability.UNSETTLED_STATE.equals(target.getDurable()))
+ {
+ linkRegistry.registerReceivingLink(endpoint.getName(), receivingLink);
+ }
+ }
+ }
+ else
+ {
+ ReceivingLinkEndpoint receivingLinkEndpoint = (ReceivingLinkEndpoint) endpoint;
+ previousLink.setLinkAttachment(new ReceivingLinkAttachment(this, receivingLinkEndpoint));
+ receivingLinkEndpoint.setLinkEventListener(previousLink);
+ link = previousLink;
+ endpoint.setLocalUnsettled(previousLink.getUnsettledOutcomeMap());
+
+ }
+ }
+ }
+
+ endpoint.attach();
+
+ if(link == null)
+ {
+ if(error == null)
+ {
+ error = new Error();
+ error.setCondition(AmqpError.NOT_FOUND);
+ }
+ endpoint.detach(error);
+ }
+ else
+ {
+ link.start();
+ }
+ }
+
+
+ private AMQQueue createTemporaryQueue(Map properties)
+ {
+ final String queueName = UUID.randomUUID().toString();
+ AMQQueue queue = null;
+ try
+ {
+ LifetimePolicy lifetimePolicy = properties == null
+ ? null
+ : (LifetimePolicy) properties.get(LIFETIME_POLICY);
+
+ final AMQQueue tempQueue = queue = AMQQueueFactory.createAMQQueueImpl( UUIDGenerator.generateUUID(),
+ queueName,
+ false, // durable
+ null, // owner
+ false, // autodelete
+ false, // exclusive
+ _vhost,
+ properties);
+
+
+
+ if (lifetimePolicy == null || lifetimePolicy instanceof DeleteOnClose)
+ {
+ final Connection_1_0.Task deleteQueueTask =
+ new Connection_1_0.Task()
+ {
+ public void doTask(Connection_1_0 session)
+ {
+ if (_vhost.getQueueRegistry().getQueue(queueName) == tempQueue)
+ {
+ try
+ {
+ tempQueue.delete();
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace(); //TODO.
+ }
+ }
+ }
+ };
+
+ _connection.addConnectionCloseTask(deleteQueueTask);
+
+ queue.addQueueDeleteTask(new AMQQueue.Task()
+ {
+ public void doTask(AMQQueue queue)
+ {
+ _connection.removeConnectionCloseTask(deleteQueueTask);
+ }
+
+
+ });
+ }
+ else if(lifetimePolicy instanceof DeleteOnNoLinks)
+ {
+
+ }
+ else if(lifetimePolicy instanceof DeleteOnNoMessages)
+ {
+
+ }
+ else if(lifetimePolicy instanceof DeleteOnNoLinksOrMessages)
+ {
+
+ }
+ }
+ catch (AMQSecurityException e)
+ {
+ e.printStackTrace(); //TODO.
+ } catch (AMQException e)
+ {
+ e.printStackTrace(); //TODO
+ }
+
+ return queue;
+ }
+
+ public ServerTransaction getTransaction(Binary transactionId)
+ {
+ // TODO should treat invalid id differently to null
+ ServerTransaction transaction = _openTransactions.get(binaryToInteger(transactionId));
+ return transaction == null ? _transaction : transaction;
+ }
+
+ public void remoteEnd(End end)
+ {
+ Iterator<Map.Entry<Integer, ServerTransaction>> iter = _openTransactions.entrySet().iterator();
+
+ while(iter.hasNext())
+ {
+ Map.Entry<Integer, ServerTransaction> entry = iter.next();
+ entry.getValue().rollback();
+ iter.remove();
+ }
+
+ }
+
+ Integer binaryToInteger(final Binary txnId)
+ {
+ if(txnId == null)
+ {
+ return null;
+ }
+
+ if(txnId.getLength() > 4)
+ throw new IllegalArgumentException();
+
+ int id = 0;
+ byte[] data = txnId.getArray();
+ for(int i = 0; i < txnId.getLength(); i++)
+ {
+ id <<= 8;
+ id += data[i+txnId.getArrayOffset()];
+ }
+
+ return id;
+
+ }
+
+ Binary integerToBinary(final int txnId)
+ {
+ byte[] data = new byte[4];
+ data[3] = (byte) (txnId & 0xff);
+ data[2] = (byte) ((txnId & 0xff00) >> 8);
+ data[1] = (byte) ((txnId & 0xff0000) >> 16);
+ data[0] = (byte) ((txnId & 0xff000000) >> 24);
+ return new Binary(data);
+
+ }
+
+ public void forceEnd()
+ {
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java
new file mode 100644
index 0000000000..08926d000d
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java
@@ -0,0 +1,634 @@
+/*
+ *
+ * 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 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;
+import org.apache.qpid.amqp_1_0.messaging.SectionEncoderImpl;
+import org.apache.qpid.amqp_1_0.transport.SendingLinkEndpoint;
+import org.apache.qpid.amqp_1_0.type.AmqpErrorException;
+import org.apache.qpid.amqp_1_0.type.Binary;
+import org.apache.qpid.amqp_1_0.type.DeliveryState;
+import org.apache.qpid.amqp_1_0.type.Outcome;
+import org.apache.qpid.amqp_1_0.type.UnsignedInteger;
+import org.apache.qpid.amqp_1_0.type.codec.AMQPDescribedTypeRegistry;
+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.filter.FilterManager;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.message.ServerMessage;
+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.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);
+
+ private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
+ private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this);
+ private final long _id;
+ private final boolean _acquires;
+ private AMQQueue.Context _queueContext;
+ private Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
+ private ReentrantLock _stateChangeLock = new ReentrantLock();
+
+ private boolean _noLocal;
+ private FilterManager _filters;
+
+ 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);
+ }
+
+ public Subscription_1_0(final SendingLink_1_0 link, final QueueDestination destination, boolean acquires)
+ {
+ _link = link;
+ _queue = destination.getQueue();
+ _id = getEndpoint().getLocalHandle().longValue();
+ _acquires = acquires;
+ }
+
+ private SendingLinkEndpoint getEndpoint()
+ {
+ return _link.getEndpoint();
+ }
+
+ public LogActor getLogActor()
+ {
+ return null; //TODO
+ }
+
+ public boolean isTransient()
+ {
+ return true; //TODO
+ }
+
+ public AMQQueue getQueue()
+ {
+ return _queue;
+ }
+
+ public QueueEntry.SubscriptionAcquiredState getOwningState()
+ {
+ return _owningState;
+ }
+
+ public QueueEntry.SubscriptionAssignedState getAssignedState()
+ {
+ return _assignedState;
+ }
+
+ public void setQueue(final AMQQueue queue, final boolean exclusive)
+ {
+ //TODO
+ }
+
+ public void setNoLocal(final boolean noLocal)
+ {
+ _noLocal = noLocal;
+ }
+
+ public boolean isNoLocal()
+ {
+ return _noLocal;
+ }
+
+ public long getSubscriptionID()
+ {
+ return _id;
+ }
+
+ public boolean isSuspended()
+ {
+ return !isActive();// || !getEndpoint().hasCreditToSend();
+
+ }
+
+ public boolean hasInterest(final QueueEntry entry)
+ {
+ return !(_noLocal && (entry.getMessage() instanceof Message_1_0)
+ && ((Message_1_0)entry.getMessage()).getSession() == getSession())
+ && checkFilters(entry);
+
+ }
+
+ private boolean checkFilters(final QueueEntry entry)
+ {
+ return (_filters == null) || _filters.allAllow(entry);
+ }
+
+ 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
+ {
+ // TODO
+ send(entry);
+ }
+
+ public void flushBatched()
+ {
+ // TODO
+ }
+
+ public void send(final QueueEntry queueEntry) throws AMQException
+ {
+ //TODO
+ ServerMessage serverMessage = queueEntry.getMessage();
+ if(serverMessage instanceof Message_1_0)
+ {
+ Message_1_0 message = (Message_1_0) serverMessage;
+ Transfer transfer = new Transfer();
+ //TODO
+
+
+ List<ByteBuffer> fragments = message.getFragments();
+ ByteBuffer payload;
+ if(fragments.size() == 1)
+ {
+ payload = fragments.get(0);
+ }
+ else
+ {
+ int size = 0;
+ for(ByteBuffer fragment : fragments)
+ {
+ size += fragment.remaining();
+ }
+
+ payload = ByteBuffer.allocate(size);
+
+ for(ByteBuffer fragment : fragments)
+ {
+ payload.put(fragment.duplicate());
+ }
+
+ payload.flip();
+ }
+
+ if(queueEntry.getDeliveryCount() != 0)
+ {
+ payload = payload.duplicate();
+ ValueHandler valueHandler = new ValueHandler(_typeRegistry);
+
+ Header oldHeader = null;
+ try
+ {
+ ByteBuffer encodedBuf = payload.duplicate();
+ Object value = valueHandler.parse(payload);
+ if(value instanceof Header)
+ {
+ oldHeader = (Header) value;
+ }
+ else
+ {
+ payload.position(0);
+ }
+ }
+ catch (AmqpErrorException e)
+ {
+ //TODO
+ throw new RuntimeException(e);
+ }
+
+ Header header = new Header();
+ if(oldHeader != null)
+ {
+ header.setDurable(oldHeader.getDurable());
+ header.setPriority(oldHeader.getPriority());
+ header.setTtl(oldHeader.getTtl());
+ }
+ header.setDeliveryCount(UnsignedInteger.valueOf(queueEntry.getDeliveryCount()));
+ _sectionEncoder.reset();
+ _sectionEncoder.encodeObject(header);
+ Binary encodedHeader = _sectionEncoder.getEncoding();
+
+ ByteBuffer oldPayload = payload;
+ payload = ByteBuffer.allocate(oldPayload.remaining() + encodedHeader.getLength());
+ payload.put(encodedHeader.getArray(),encodedHeader.getArrayOffset(),encodedHeader.getLength());
+ payload.put(oldPayload);
+ payload.flip();
+ }
+
+ transfer.setPayload(payload);
+ byte[] data = new byte[8];
+ ByteBuffer.wrap(data).putLong(_deliveryTag++);
+ final Binary tag = new Binary(data);
+
+ transfer.setDeliveryTag(tag);
+
+ synchronized(_link.getLock())
+ {
+ if(_link.isAttached())
+ {
+ if(SenderSettleMode.SETTLED.equals(getEndpoint().getSendingSettlementMode()))
+ {
+ transfer.setSettled(true);
+ }
+ else
+ {
+ UnsettledAction action = _acquires
+ ? new DispositionAction(tag, queueEntry)
+ : new DoNothingAction(tag, queueEntry);
+
+ _link.addUnsettled(tag, action, queueEntry);
+ }
+
+ if(_transactionId != null)
+ {
+ TransactionalState state = new TransactionalState();
+ state.setTxnId(_transactionId);
+ transfer.setState(state);
+ }
+ // TODO - need to deal with failure here
+ if(_acquires && _transactionId != null)
+ {
+ ServerTransaction txn = _link.getTransaction(_transactionId);
+ if(txn != null)
+ {
+ txn.addPostTransactionAction(new ServerTransaction.Action(){
+
+ public void postCommit()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void onRollback()
+ {
+ if(queueEntry.isAcquiredBy(Subscription_1_0.this))
+ {
+ queueEntry.release();
+ _link.getEndpoint().updateDisposition(tag, (DeliveryState)null, true);
+
+
+ }
+ }
+ });
+ }
+
+ }
+
+ getEndpoint().transfer(transfer);
+ }
+ else
+ {
+ queueEntry.release();
+ }
+ }
+ }
+
+ }
+
+ public void queueDeleted(final AMQQueue queue)
+ {
+ //TODO
+ getEndpoint().setSource(null);
+ getEndpoint().detach();
+ }
+
+ public synchronized boolean wouldSuspend(final QueueEntry msg)
+ {
+ final boolean hasCredit = _link.isAttached() && getEndpoint().hasCreditToSend();
+ if(!hasCredit && getState() == State.ACTIVE)
+ {
+ suspend();
+ }
+
+ return !hasCredit;
+ }
+
+ public boolean trySendLock()
+ {
+ return _stateChangeLock.tryLock();
+ }
+
+ public synchronized void suspend()
+ {
+ if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
+ {
+ _stateListener.stateChange(this, 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)
+ {
+ //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 synchronized void queueEmpty()
+ {
+ if(_link.drained())
+ {
+ if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
+ {
+ _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
+ }
+ }
+ }
+
+ public synchronized void flowStateChanged()
+ {
+ if(isSuspended() && getEndpoint() != null)
+ {
+ if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE))
+ {
+ _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE);
+ }
+ _transactionId = _link.getTransactionId();
+ }
+ }
+
+ public Session_1_0 getSession()
+ {
+ return _link.getSession();
+ }
+
+ private class DispositionAction implements UnsettledAction
+ {
+
+ private final QueueEntry _queueEntry;
+ private final Binary _deliveryTag;
+
+ public DispositionAction(Binary tag, QueueEntry queueEntry)
+ {
+ _deliveryTag = tag;
+ _queueEntry = queueEntry;
+ }
+
+ public boolean process(DeliveryState state, final Boolean settled)
+ {
+
+ Binary transactionId = null;
+ final Outcome outcome;
+ // If disposition is settled this overrides the txn?
+ if(state instanceof TransactionalState)
+ {
+ transactionId = ((TransactionalState)state).getTxnId();
+ outcome = ((TransactionalState)state).getOutcome();
+ }
+ else if (state instanceof Outcome)
+ {
+ outcome = (Outcome) state;
+ }
+ else
+ {
+ outcome = null;
+ }
+
+
+ ServerTransaction txn = _link.getTransaction(transactionId);
+
+ if(outcome instanceof Accepted)
+ {
+ txn.dequeue(_queueEntry.getQueue(), _queueEntry.getMessage(),
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ if(_queueEntry.isAcquiredBy(Subscription_1_0.this))
+ {
+ _queueEntry.discard();
+ }
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ txn.addPostTransactionAction(new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ //_link.getEndpoint().settle(_deliveryTag);
+ _link.getEndpoint().updateDisposition(_deliveryTag, (DeliveryState)outcome, true);
+ _link.getEndpoint().sendFlowConditional();
+ }
+
+ public void onRollback()
+ {
+ if(Boolean.TRUE.equals(settled))
+ {
+ final Modified modified = new Modified();
+ modified.setDeliveryFailed(true);
+ _link.getEndpoint().updateDisposition(_deliveryTag, modified, true);
+ _link.getEndpoint().sendFlowConditional();
+ }
+ }
+ });
+ }
+ else if(outcome instanceof Released)
+ {
+ txn.addPostTransactionAction(new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+
+ _queueEntry.release();
+ _link.getEndpoint().settle(_deliveryTag);
+ }
+
+ public void onRollback()
+ {
+ _link.getEndpoint().settle(_deliveryTag);
+ }
+ });
+ }
+
+ else if(outcome instanceof Modified)
+ {
+ txn.addPostTransactionAction(new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+
+ _queueEntry.release();
+ if(Boolean.TRUE.equals(((Modified)outcome).getDeliveryFailed()))
+ {
+ _queueEntry.incrementDeliveryCount();
+ }
+ _link.getEndpoint().settle(_deliveryTag);
+ }
+
+ public void onRollback()
+ {
+ if(Boolean.TRUE.equals(settled))
+ {
+ final Modified modified = new Modified();
+ modified.setDeliveryFailed(true);
+ _link.getEndpoint().updateDisposition(_deliveryTag, modified, true);
+ _link.getEndpoint().sendFlowConditional();
+ }
+ }
+ });
+ }
+
+ return (transactionId == null && outcome != null);
+ }
+ }
+
+ private class DoNothingAction implements UnsettledAction
+ {
+ public DoNothingAction(final Binary tag,
+ final QueueEntry queueEntry)
+ {
+ }
+
+ public boolean process(final DeliveryState state, final Boolean settled)
+ {
+ Binary transactionId = null;
+ Outcome outcome = null;
+ // If disposition is settled this overrides the txn?
+ if(state instanceof TransactionalState)
+ {
+ transactionId = ((TransactionalState)state).getTxnId();
+ outcome = ((TransactionalState)state).getOutcome();
+ }
+ else if (state instanceof Outcome)
+ {
+ outcome = (Outcome) state;
+ }
+ return true;
+ }
+ }
+
+ public FilterManager getFilters()
+ {
+ return _filters;
+ }
+
+ public void setFilters(final FilterManager filters)
+ {
+ _filters = filters;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/TxnCoordinatorLink_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/TxnCoordinatorLink_1_0.java
new file mode 100644
index 0000000000..a05d14816a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/TxnCoordinatorLink_1_0.java
@@ -0,0 +1,195 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol.v1_0;
+
+import org.apache.qpid.amqp_1_0.messaging.SectionDecoder;
+import org.apache.qpid.amqp_1_0.messaging.SectionDecoderImpl;
+import org.apache.qpid.amqp_1_0.transport.LinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.ReceivingLinkEndpoint;
+import org.apache.qpid.amqp_1_0.transport.ReceivingLinkListener;
+import org.apache.qpid.amqp_1_0.type.*;
+import org.apache.qpid.amqp_1_0.type.DeliveryState;
+import org.apache.qpid.amqp_1_0.type.messaging.*;
+import org.apache.qpid.amqp_1_0.type.transaction.Declare;
+import org.apache.qpid.amqp_1_0.type.transaction.Declared;
+import org.apache.qpid.amqp_1_0.type.transaction.Discharge;
+import org.apache.qpid.amqp_1_0.type.transport.*;
+import org.apache.qpid.amqp_1_0.type.transport.Error;
+import org.apache.qpid.server.txn.LocalTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import java.nio.ByteBuffer;
+import java.util.*;
+
+public class TxnCoordinatorLink_1_0 implements ReceivingLinkListener, Link_1_0
+{
+ private VirtualHost _vhost;
+ private ReceivingLinkEndpoint _endpoint;
+
+ private ArrayList<Transfer> _incompleteMessage;
+ private SectionDecoder _sectionDecoder;
+ private LinkedHashMap<Integer, ServerTransaction> _openTransactions;
+ private Session_1_0 _session;
+
+
+ public TxnCoordinatorLink_1_0(VirtualHost vhost,
+ Session_1_0 session_1_0, ReceivingLinkEndpoint endpoint,
+ LinkedHashMap<Integer, ServerTransaction> openTransactions)
+ {
+ _vhost = vhost;
+ _session = session_1_0;
+ _endpoint = endpoint;
+ _sectionDecoder = new SectionDecoderImpl(endpoint.getSession().getConnection().getDescribedTypeRegistry());
+ _openTransactions = openTransactions;
+ }
+
+ public void messageTransfer(Transfer xfr)
+ {
+ // TODO - cope with fragmented messages
+
+ ByteBuffer payload = null;
+
+
+ if(Boolean.TRUE.equals(xfr.getMore()) && _incompleteMessage == null)
+ {
+ _incompleteMessage = new ArrayList<Transfer>();
+ _incompleteMessage.add(xfr);
+ return;
+ }
+ else if(_incompleteMessage != null)
+ {
+ _incompleteMessage.add(xfr);
+ if(Boolean.TRUE.equals(xfr.getMore()))
+ {
+ return;
+ }
+
+ int size = 0;
+ for(Transfer t : _incompleteMessage)
+ {
+ size += t.getPayload().limit();
+ }
+ payload = ByteBuffer.allocate(size);
+ for(Transfer t : _incompleteMessage)
+ {
+ payload.put(t.getPayload().duplicate());
+ }
+ payload.flip();
+ _incompleteMessage=null;
+
+ }
+ else
+ {
+ payload = xfr.getPayload();
+ }
+
+
+ // Only interested int he amqp-value section that holds the message to the co-ordinator
+ try
+ {
+ List<Section> sections = _sectionDecoder.parseAll(payload);
+
+ for(Section section : sections)
+ {
+ if(section instanceof AmqpValue)
+ {
+ Object command = ((AmqpValue) section).getValue();
+
+ if(command instanceof Declare)
+ {
+ Integer txnId = Integer.valueOf(0);
+ Iterator<Integer> existingTxn = _openTransactions.keySet().iterator();
+ while(existingTxn.hasNext())
+ {
+ txnId = existingTxn.next();
+ }
+ txnId = Integer.valueOf(txnId.intValue() + 1);
+
+ _openTransactions.put(txnId, new LocalTransaction(_vhost.getMessageStore()));
+
+ Declared state = new Declared();
+
+
+
+ state.setTxnId(_session.integerToBinary(txnId));
+ _endpoint.updateDisposition(xfr.getDeliveryTag(), state, true);
+
+ }
+ else if(command instanceof Discharge)
+ {
+ Discharge discharge = (Discharge) command;
+
+ DeliveryState state = xfr.getState();
+ discharge(_session.binaryToInteger(discharge.getTxnId()), discharge.getFail());
+ _endpoint.updateDisposition(xfr.getDeliveryTag(), new Accepted(), true);
+
+ }
+ }
+ }
+
+ }
+ catch (AmqpErrorException e)
+ {
+ e.printStackTrace(); //TODO.
+ }
+
+ }
+
+ public void remoteDetached(LinkEndpoint endpoint, Detach detach)
+ {
+ //TODO
+ endpoint.detach();
+ }
+
+ private Error discharge(Integer transactionId, boolean fail)
+ {
+ Error error = null;
+ ServerTransaction txn = _openTransactions.get(transactionId);
+ if(txn != null)
+ {
+ if(fail)
+ {
+ txn.rollback();
+ }
+ else
+ {
+ txn.commit();
+ }
+ _openTransactions.remove(transactionId);
+ }
+ else
+ {
+ error = new Error();
+ error.setCondition(AmqpError.NOT_FOUND);
+ error.setDescription("Unkown transactionId" + transactionId);
+ }
+ return error;
+ }
+
+
+
+ public void start()
+ {
+ _endpoint.setLinkCredit(UnsignedInteger.ONE);
+ _endpoint.setCreditWindow();
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java
new file mode 100644
index 0000000000..c497cc5146
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java
@@ -0,0 +1,8 @@
+package org.apache.qpid.server.protocol.v1_0;
+
+import org.apache.qpid.amqp_1_0.type.DeliveryState;
+
+public interface UnsettledAction
+{
+ boolean process(DeliveryState state, Boolean settled);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
index f6bf6626a0..46c2a635b7 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
@@ -23,19 +23,20 @@ package org.apache.qpid.server.queue;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Map;
+import java.util.UUID;
public class AMQPriorityQueue extends OutOfOrderQueue
{
- protected AMQPriorityQueue(final String name,
+ protected AMQPriorityQueue(UUID id,
+ final String name,
final boolean durable,
final String owner,
final boolean autoDelete,
boolean exclusive,
final VirtualHost virtualHost,
- Map<String, Object> arguments,
- int priorities)
+ Map<String, Object> arguments, int priorities)
{
- super(name, durable, owner, autoDelete, exclusive, virtualHost, new PriorityQueueList.Factory(priorities), arguments);
+ super(id, name, durable, owner, autoDelete, exclusive, virtualHost, new PriorityQueueList.Factory(priorities), arguments);
}
public int getPriorities()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
index a3da598bdf..e643338c3d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
@@ -34,7 +34,6 @@ import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.List;
@@ -141,10 +140,9 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
public List<QueueEntry> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition);
- void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName,
- ServerTransaction transaction);
+ void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName);
- void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction transaction);
+ void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName);
void removeMessagesFromQueue(long fromMessageId, long toMessageId);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
index aca5891d2e..f2b7d7c56b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
@@ -20,6 +20,10 @@
*/
package org.apache.qpid.server.queue;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.exchange.ExchangeDefaults;
@@ -30,12 +34,10 @@ import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import java.util.HashMap;
-import java.util.Map;
-
public class AMQQueueFactory
{
public static final String X_QPID_PRIORITIES = "x-qpid-priorities";
@@ -166,8 +168,13 @@ public class AMQQueueFactory
}
};
-
- /** @see #createAMQQueueImpl(String, boolean, String, boolean, boolean, VirtualHost, Map) */
+ /**
+ * Creates a new queue with a random id.
+ *
+ * @see #createAMQQueueImpl(UUID, String, boolean, String, boolean, boolean, VirtualHost, Map)
+ * @deprecated because only called from unit tests
+ * */
+ @Deprecated
public static AMQQueue createAMQQueueImpl(AMQShortString name,
boolean durable,
AMQShortString owner,
@@ -175,22 +182,28 @@ public class AMQQueueFactory
boolean exclusive,
VirtualHost virtualHost, final FieldTable arguments) throws AMQException
{
- return createAMQQueueImpl(name == null ? null : name.toString(),
+ return createAMQQueueImpl(UUIDGenerator.generateUUID(),
+ name == null ? null : name.toString(),
durable,
owner == null ? null : owner.toString(),
autoDelete,
- exclusive,
- virtualHost, FieldTable.convertToMap(arguments));
+ exclusive, virtualHost, FieldTable.convertToMap(arguments));
}
-
- public static AMQQueue createAMQQueueImpl(String queueName,
+ /**
+ * @param id the id to use. If default then one is generated from queueName. TODO check correctness of calls that pass a null value.
+ */
+ public static AMQQueue createAMQQueueImpl(UUID id,
+ String queueName,
boolean durable,
String owner,
boolean autoDelete,
- boolean exclusive,
- VirtualHost virtualHost, Map<String, Object> arguments) throws AMQSecurityException, AMQException
+ boolean exclusive, VirtualHost virtualHost, Map<String, Object> arguments) throws AMQSecurityException, AMQException
{
+ if (id == null)
+ {
+ throw new IllegalArgumentException("Queue id must not be null");
+ }
if (queueName == null)
{
throw new IllegalArgumentException("Queue name must not be null");
@@ -241,19 +254,19 @@ public class AMQQueueFactory
AMQQueue q;
if(sortingKey != null)
{
- q = new SortedQueue(queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments, sortingKey);
+ q = new SortedQueue(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments, sortingKey);
}
else if(conflationKey != null)
{
- q = new ConflationQueue(queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments, conflationKey);
+ q = new ConflationQueue(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments, conflationKey);
}
else if(priorities > 1)
{
- q = new AMQPriorityQueue(queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments, priorities);
+ q = new AMQPriorityQueue(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments, priorities);
}
else
{
- q = new SimpleAMQQueue(queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments);
+ q = new SimpleAMQQueue(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments);
}
//Register the new queue
@@ -287,12 +300,12 @@ public class AMQQueueFactory
if(dlExchange == null)
{
- dlExchange = exchangeFactory.createExchange(new AMQShortString(dlExchangeName), ExchangeDefaults.FANOUT_EXCHANGE_CLASS, true, false, 0);
+ dlExchange = exchangeFactory.createExchange(UUIDGenerator.generateUUID(dlExchangeName, virtualHost.getName()), new AMQShortString(dlExchangeName), ExchangeDefaults.FANOUT_EXCHANGE_CLASS, true, false, 0);
exchangeRegistry.registerExchange(dlExchange);
//enter the dle in the persistent store
- virtualHost.getDurableConfigurationStore().createExchange(dlExchange);
+ virtualHost.getMessageStore().createExchange(dlExchange);
}
}
@@ -309,10 +322,10 @@ public class AMQQueueFactory
args.put(X_QPID_DLQ_ENABLED, false);
args.put(X_QPID_MAXIMUM_DELIVERY_COUNT, 0);
- dlQueue = createAMQQueueImpl(dlQueueName, true, owner, false, exclusive, virtualHost, args);
+ dlQueue = createAMQQueueImpl(UUIDGenerator.generateUUID(dlQueueName, virtualHost.getName()), dlQueueName, true, owner, false, exclusive, virtualHost, args);
//enter the dlq in the persistent store
- virtualHost.getDurableConfigurationStore().createQueue(dlQueue, FieldTable.convertToFieldTable(args));
+ virtualHost.getMessageStore().createQueue(dlQueue, FieldTable.convertToFieldTable(args));
}
}
@@ -364,7 +377,10 @@ public class AMQQueueFactory
arguments.put(X_QPID_DLQ_ENABLED, true);
}
- AMQQueue q = createAMQQueueImpl(queueName, durable, owner, autodelete, exclusive, host, arguments);
+ // we need queues that are defined in config to have deterministic ids.
+ UUID id = UUIDGenerator.generateUUID(queueName, host.getName());
+
+ AMQQueue q = createAMQQueueImpl(id, queueName, durable, owner, autodelete, exclusive, host, arguments);
q.configure(config);
return q;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
index 7c59097965..b0d4cb3486 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
@@ -36,8 +36,6 @@ import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.txn.LocalTransaction;
-import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.transport.MessageProperties;
import javax.management.JMException;
@@ -613,9 +611,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
}
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore());
- _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn);
- txn.commit();
+ _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName);
}
/**
@@ -648,11 +644,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
}
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore());
-
- _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn);
-
- txn.commit();
+ _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName);
}
/**
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java
index 2c645cc555..c2813bb7a5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java
@@ -21,22 +21,23 @@
package org.apache.qpid.server.queue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.virtualhost.VirtualHost;
public class ConflationQueue extends SimpleAMQQueue
{
- protected ConflationQueue(String name,
+ protected ConflationQueue(UUID id,
+ String name,
boolean durable,
String owner,
boolean autoDelete,
boolean exclusive,
VirtualHost virtualHost,
- Map<String, Object> args,
- String conflationKey)
+ Map<String, Object> args, String conflationKey)
{
- super(name, durable, owner, autoDelete, exclusive, virtualHost, new ConflationQueueList.Factory(conflationKey), args);
+ super(id, name, durable, owner, autoDelete, exclusive, virtualHost, new ConflationQueueList.Factory(conflationKey), args);
}
public String getConflationKey()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
index d76487073d..2493974d45 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
@@ -20,15 +20,21 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.exchange.DefaultExchangeRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collection;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class DefaultQueueRegistry implements QueueRegistry
{
+ private static final Logger LOGGER = Logger.getLogger(DefaultExchangeRegistry.class);
+
private ConcurrentMap<AMQShortString, AMQQueue> _queueMap = new ConcurrentHashMap<AMQShortString, AMQQueue>();
private final VirtualHost _virtualHost;
@@ -72,4 +78,36 @@ public class DefaultQueueRegistry implements QueueRegistry
{
return getQueue(new AMQShortString(queue));
}
+
+ @Override
+ public void stopAllAndUnregisterMBeans()
+ {
+ for (final AMQQueue queue : getQueues())
+ {
+ queue.stop();
+ try
+ {
+ queue.getManagedObject().unregister();
+ }
+ catch (AMQException e)
+ {
+ LOGGER.warn("Failed to unregister mbean", e);
+ }
+ }
+ _queueMap.clear();
+ }
+
+ @Override
+ public synchronized AMQQueue getQueue(UUID queueId)
+ {
+ Collection<AMQQueue> queues = _queueMap.values();
+ for (AMQQueue queue : queues)
+ {
+ if (queue.getId().equals(queueId))
+ {
+ return queue;
+ }
+ }
+ return null;
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
index 0162f1b738..c5a610c7b6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
@@ -70,8 +70,6 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
private Exchange _exchange;
-
- private int _receivedChunkCount = 0;
private List<ContentChunk> _contentChunks = new ArrayList<ContentChunk>();
// we keep both the original meta data object and the store reference to it just in case the
@@ -80,13 +78,20 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
private MessageMetaData _messageMetaData;
private StoredMessage<MessageMetaData> _storedMessageHandle;
+ private Object _connectionReference;
public IncomingMessage(
final MessagePublishInfo info
)
{
+ this(info, null);
+ }
+
+ public IncomingMessage(MessagePublishInfo info, Object reference)
+ {
_messagePublishInfo = info;
+ _connectionReference = reference;
}
public void setContentHeaderBody(final ContentHeaderBody contentHeaderBody) throws AMQException
@@ -125,12 +130,6 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
}
- public MessageMetaData headersReceived()
- {
-
- return headersReceived(System.currentTimeMillis());
- }
-
public MessageMetaData headersReceived(long currentTime)
{
_messageMetaData = new MessageMetaData(_messagePublishInfo, _contentHeaderBody, 0, currentTime);
@@ -143,16 +142,10 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
return _destinationQueues;
}
- public int addContentBodyFrame(final ContentChunk contentChunk)
- throws AMQException
+ public void addContentBodyFrame(final ContentChunk contentChunk) throws AMQException
{
- _storedMessageHandle.addContent((int)_bodyLengthReceived, ByteBuffer.wrap(contentChunk.getData()));
_bodyLengthReceived += contentChunk.getSize();
_contentChunks.add(contentChunk);
-
-
-
- return _receivedChunkCount++;
}
public boolean allContentReceived()
@@ -252,18 +245,12 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
return _expiration;
}
- public int getReceivedChunkCount()
- {
- return _receivedChunkCount;
- }
-
-
public int getBodyCount() throws AMQException
{
return _contentChunks.size();
}
- public ContentChunk getContentChunk(int index) throws IllegalArgumentException, AMQException
+ public ContentChunk getContentChunk(int index)
{
return _contentChunks.get(index);
}
@@ -318,4 +305,14 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
{
return _storedMessageHandle;
}
+
+ public Object getConnectionReference()
+ {
+ return _connectionReference;
+ }
+
+ public MessageMetaData getMessageMetaData()
+ {
+ return _messageMetaData;
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java
index 53121fc031..daa5db393a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java
@@ -1,3 +1,23 @@
+/*
+ *
+ * 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.subscription.Subscription;
@@ -5,15 +25,16 @@ import org.apache.qpid.server.subscription.SubscriptionList;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Map;
+import java.util.UUID;
public abstract class OutOfOrderQueue extends SimpleAMQQueue
{
- protected OutOfOrderQueue(String name, boolean durable, String owner,
- boolean autoDelete, boolean exclusive, VirtualHost virtualHost,
- QueueEntryListFactory entryListFactory, Map<String, Object> arguments)
+ protected OutOfOrderQueue(UUID id, String name, boolean durable,
+ String owner, boolean autoDelete, boolean exclusive,
+ VirtualHost virtualHost, QueueEntryListFactory entryListFactory, Map<String, Object> arguments)
{
- super(name, durable, owner, autoDelete, exclusive, virtualHost, entryListFactory, arguments);
+ super(id, name, durable, owner, autoDelete, exclusive, virtualHost, entryListFactory, arguments);
}
@Override
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
index 05141a48a1..1d13ee66c0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
@@ -25,19 +25,19 @@ import org.apache.qpid.server.message.ServerMessage;
public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
{
private final AMQQueue _queue;
- private final SimpleQueueEntryList[] _priorityLists;
+ private final PriorityQueueEntrySubList[] _priorityLists;
private final int _priorities;
private final int _priorityOffset;
public PriorityQueueList(AMQQueue queue, int priorities)
{
_queue = queue;
- _priorityLists = new SimpleQueueEntryList[priorities];
+ _priorityLists = new PriorityQueueEntrySubList[priorities];
_priorities = priorities;
_priorityOffset = 5-((priorities + 1)/2);
for(int i = 0; i < priorities; i++)
{
- _priorityLists[i] = new SimpleQueueEntryList(queue);
+ _priorityLists[i] = new PriorityQueueEntrySubList(queue);
}
}
@@ -161,4 +161,48 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl>
return new PriorityQueueList(queue, _priorities);
}
}
+
+ private static class PriorityQueueEntrySubList extends SimpleQueueEntryList
+ {
+ public PriorityQueueEntrySubList(AMQQueue queue)
+ {
+ super(queue);
+ }
+
+ @Override
+ protected PriorityQueueEntryImpl createQueueEntry(ServerMessage<?> message)
+ {
+ return new PriorityQueueEntryImpl(this, message);
+ }
+ }
+
+ private static class PriorityQueueEntryImpl extends SimpleQueueEntryImpl
+ {
+ public PriorityQueueEntryImpl(PriorityQueueEntrySubList queueEntryList, ServerMessage<?> message)
+ {
+ super(queueEntryList, message);
+ }
+
+ @Override
+ public int compareTo(final QueueEntry o)
+ {
+ byte thisPriority = getMessageHeader().getPriority();
+ byte otherPriority = o.getMessageHeader().getPriority();
+
+ if(thisPriority != otherPriority)
+ {
+ /*
+ * Different priorities, so answer can only be greater than or less than
+ *
+ * A message with higher priority (e.g. 5) is conceptually 'earlier' in the
+ * priority queue than one with a lower priority (e.g. 4).
+ */
+ return thisPriority > otherPriority ? -1 : 1;
+ }
+ else
+ {
+ return super.compareTo(o);
+ }
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java
index c8f04c7b96..79279b44c7 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java
@@ -52,4 +52,13 @@ final class QueueContext implements AMQQueue.Context
{
return _releasedEntry;
}
+
+ @Override
+ public String toString()
+ {
+ return "QueueContext{" +
+ "_lastSeenEntry=" + _lastSeenEntry +
+ ", _releasedEntry=" + _releasedEntry +
+ '}';
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
index fea5303e23..209553e8fa 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
@@ -227,9 +227,10 @@ public abstract class QueueEntryImpl implements QueueEntry
public void release()
{
EntryState state = _state;
-
+
if((state.getState() == State.ACQUIRED) &&_stateUpdater.compareAndSet(this, state, AVAILABLE_STATE))
{
+
if(state instanceof SubscriptionAcquiredState)
{
getQueue().decrementUnackedMsgCount();
@@ -254,6 +255,7 @@ public abstract class QueueEntryImpl implements QueueEntry
routeToAlternate();
}
}
+
}
public boolean releaseButRetain()
@@ -267,7 +269,6 @@ public abstract class QueueEntryImpl implements QueueEntry
Subscription sub = ((SubscriptionAcquiredState) state).getSubscription();
if(_stateUpdater.compareAndSet(this, state, sub.getAssignedState()))
{
- System.err.println("Message released (and retained)" + getMessage().getMessageNumber());
getQueue().requeue(this);
if(_stateChangeListeners != null)
{
@@ -417,11 +418,19 @@ public abstract class QueueEntryImpl implements QueueEntry
if (alternateExchange != null)
{
- final List<? extends BaseQueue> rerouteQueues = alternateExchange.route(new InboundMessageAdapter(this));
+ InboundMessageAdapter inboundMessageAdapter = new InboundMessageAdapter(this);
+ List<? extends BaseQueue> queues = alternateExchange.route(inboundMessageAdapter);
final ServerMessage message = getMessage();
- if (rerouteQueues != null && rerouteQueues.size() != 0)
+ if ((queues == null || queues.size() == 0) && alternateExchange.getAlternateExchange() != null)
{
+ queues = alternateExchange.getAlternateExchange().route(inboundMessageAdapter);
+ }
+
+
+ if (queues != null && queues.size() != 0)
+ {
+ final List<? extends BaseQueue> rerouteQueues = queues;
ServerTransaction txn = new LocalTransaction(getQueue().getVirtualHost().getMessageStore());
txn.enqueue(rerouteQueues, message, new ServerTransaction.Action()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java
new file mode 100644
index 0000000000..1578d21321
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java
@@ -0,0 +1,22 @@
+package org.apache.qpid.server.queue;
+
+/**
+* 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
+* <p/>
+* http://www.apache.org/licenses/LICENSE-2.0
+* <p/>
+* 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.
+*/
+public interface QueueEntryVisitor
+{
+ boolean visit(QueueEntry entry);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
index 80f6bd1493..72a54c9889 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
@@ -24,6 +24,7 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collection;
+import java.util.UUID;
public interface QueueRegistry
{
@@ -40,4 +41,8 @@ public interface QueueRegistry
Collection<AMQQueue> getQueues();
AMQQueue getQueue(String queue);
+
+ void stopAllAndUnregisterMBeans();
+
+ AMQQueue getQueue(UUID queueId);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
index 891a492b7f..d7eb304c92 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
@@ -191,29 +191,29 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private int _maximumDeliveryCount = ApplicationRegistry.getInstance().getConfiguration().getMaxDeliveryCount();
private final MessageGroupManager _messageGroupManager;
- protected SimpleAMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String,Object> arguments)
+ protected SimpleAMQQueue(UUID id, AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String,Object> arguments)
{
- this(name, durable, owner, autoDelete, exclusive, virtualHost,new SimpleQueueEntryList.Factory(), arguments);
+ this(id, name, durable, owner, autoDelete, exclusive,virtualHost, new SimpleQueueEntryList.Factory(), arguments);
}
- public SimpleAMQQueue(String queueName, boolean durable, String owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String, Object> arguments)
+ public SimpleAMQQueue(UUID id, String queueName, boolean durable, String owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String, Object> arguments)
{
- this(queueName, durable, owner, autoDelete, exclusive, virtualHost, new SimpleQueueEntryList.Factory(), arguments);
+ this(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, new SimpleQueueEntryList.Factory(), arguments);
}
- public SimpleAMQQueue(String queueName, boolean durable, String owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, QueueEntryListFactory entryListFactory, Map<String, Object> arguments)
+ public SimpleAMQQueue(UUID id, String queueName, boolean durable, String owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, QueueEntryListFactory entryListFactory, Map<String, Object> arguments)
{
- this(queueName == null ? null : new AMQShortString(queueName), durable, owner == null ? null : new AMQShortString(owner), autoDelete, exclusive, virtualHost, entryListFactory, arguments);
+ this(id, queueName == null ? null : new AMQShortString(queueName), durable, owner == null ? null : new AMQShortString(owner), autoDelete, exclusive, virtualHost, entryListFactory, arguments);
}
- protected SimpleAMQQueue(AMQShortString name,
+ protected SimpleAMQQueue(UUID id,
+ AMQShortString name,
boolean durable,
AMQShortString owner,
boolean autoDelete,
boolean exclusive,
VirtualHost virtualHost,
- QueueEntryListFactory entryListFactory,
- Map<String,Object> arguments)
+ QueueEntryListFactory entryListFactory, Map<String,Object> arguments)
{
if (name == null)
@@ -236,7 +236,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
_entries = entryListFactory.createQueueEntryList(this);
_arguments = arguments;
- _id = virtualHost.getConfigStore().createId();
+ _id = id;
_asyncDelivery = ReferenceCountingExecutorService.getInstance().acquireExecutorService();
@@ -346,7 +346,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if(isDurable())
{
- getVirtualHost().getDurableConfigurationStore().updateQueue(this);
+ getVirtualHost().getMessageStore().updateQueue(this);
}
}
@@ -862,7 +862,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public void requeue(QueueEntry entry)
{
-
SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.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())
@@ -1198,19 +1197,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public void moveMessagesToAnotherQueue(final long fromMessageId,
final long toMessageId,
- String queueName,
- ServerTransaction txn) throws IllegalArgumentException
+ String destinationQueueName) throws IllegalArgumentException
{
- final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (toQueue == null)
- {
- throw new IllegalArgumentException("Queue '" + queueName + "' is not registered with the virtualhost.");
- }
- else if (toQueue == this)
- {
- throw new IllegalArgumentException("The destination queue cant be the same as the source queue");
- }
+ final AMQQueue toQueue = getValidatedDestinationQueue(destinationQueueName);
List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
{
@@ -1230,65 +1220,68 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
});
-
- // Move the messages in on the message store.
- for (final QueueEntry entry : entries)
+ final ServerTransaction txn = new LocalTransaction(getVirtualHost().getMessageStore());
+ boolean shouldRollback = true;
+ try
{
- final ServerMessage message = entry.getMessage();
- txn.enqueue(toQueue, message,
- new ServerTransaction.Action()
- {
-
- public void postCommit()
+ // Move the messages in on the message store.
+ for (final QueueEntry entry : entries)
+ {
+ final ServerMessage message = entry.getMessage();
+ txn.enqueue(toQueue, message,
+ new ServerTransaction.Action()
{
- try
+
+ public void postCommit()
{
- toQueue.enqueue(message);
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
}
- catch (AMQException e)
+
+ public void onRollback()
{
- throw new RuntimeException(e);
+ entry.release();
}
- }
-
- public void onRollback()
- {
- entry.release();
- }
- });
- txn.dequeue(this, message,
- new ServerTransaction.Action()
- {
-
- public void postCommit()
+ });
+ txn.dequeue(this, message,
+ new ServerTransaction.Action()
{
- entry.discard();
- }
- public void onRollback()
- {
+ public void postCommit()
+ {
+ entry.discard();
+ }
- }
- });
+ public void onRollback()
+ {
+ }
+ });
+ }
+ txn.commit();
+ shouldRollback = false;
+ }
+ finally
+ {
+ if (shouldRollback)
+ {
+ txn.rollback();
+ }
}
}
public void copyMessagesToAnotherQueue(final long fromMessageId,
final long toMessageId,
- String queueName,
- final ServerTransaction txn) throws IllegalArgumentException
+ String destinationQueueName) throws IllegalArgumentException
{
- final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (toQueue == null)
- {
- throw new IllegalArgumentException("Queue '" + queueName + "' is not registered with the virtualhost.");
- }
- else if (toQueue == this)
- {
- throw new IllegalArgumentException("The destination queue cant be the same as the source queue");
- }
+ final AMQQueue toQueue = getValidatedDestinationQueue(destinationQueueName);
List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
{
@@ -1306,36 +1299,63 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
});
-
- // Move the messages in on the message store.
- for (QueueEntry entry : entries)
+ final ServerTransaction txn = new LocalTransaction(_virtualHost.getMessageStore());
+ boolean shouldRollback = true;
+ try
{
- final ServerMessage message = entry.getMessage();
-
- txn.enqueue(toQueue, message, new ServerTransaction.Action()
+ // Copy the messages in on the message store.
+ for (QueueEntry entry : entries)
{
- public void postCommit()
+ final ServerMessage message = entry.getMessage();
+
+ txn.enqueue(toQueue, message, new ServerTransaction.Action()
{
- try
+ public void postCommit()
{
- toQueue.enqueue(message);
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
}
- catch (AMQException e)
+
+ public void onRollback()
{
- throw new RuntimeException(e);
}
- }
+ });
- public void onRollback()
- {
-
- }
- });
+ }
+ txn.commit();
+ shouldRollback = false;
+ }
+ finally
+ {
+ if (shouldRollback)
+ {
+ txn.rollback();
+ }
}
}
+ private AMQQueue getValidatedDestinationQueue(String queueName)
+ {
+ final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
+ if (toQueue == null)
+ {
+ throw new IllegalArgumentException("Queue '" + queueName + "' is not registered with the virtualhost.");
+ }
+ else if (toQueue == this)
+ {
+ throw new IllegalArgumentException("The destination queue can't be the same as the source queue");
+ }
+ return toQueue;
+ }
+
public void removeMessagesFromQueue(long fromMessageId, long toMessageId)
{
@@ -1515,10 +1535,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
for(final QueueEntry entry : entries)
{
adapter.setEntry(entry);
- final List<? extends BaseQueue> rerouteQueues = _alternateExchange.route(adapter);
+ List<? extends BaseQueue> queues = _alternateExchange.route(adapter);
+ if((queues == null || queues.size() == 0) && _alternateExchange.getAlternateExchange() != null)
+ {
+ queues = _alternateExchange.getAlternateExchange().route(adapter);
+ }
+
final ServerMessage message = entry.getMessage();
- if(rerouteQueues != null && rerouteQueues.size() != 0)
+ if(queues != null && queues.size() != 0)
{
+ final List<? extends BaseQueue> rerouteQueues = queues;
txn.enqueue(rerouteQueues, entry.getMessage(),
new ServerTransaction.Action()
{
@@ -1716,6 +1742,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
boolean atTail = false;
final boolean keepSendLockHeld = iterations <= SimpleAMQQueue.MAX_ASYNC_DELIVERIES;
+ boolean queueEmpty = false;
try
{
@@ -1733,12 +1760,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
atTail = attemptDelivery(sub, true);
- if (atTail && !sub.isSuspended() && sub.isAutoClose())
+ if (atTail && getNextAvailableEntry(sub) == null)
{
- unregisterSubscription(sub);
-
- sub.confirmAutoClose();
-
+ queueEmpty = true;
}
else if (!atTail)
{
@@ -1760,6 +1784,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
sub.releaseSendLock();
}
+ if(queueEmpty)
+ {
+ sub.queueEmpty();
+ }
+
sub.flushBatched();
}
@@ -1895,7 +1924,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if(context != null)
{
QueueEntry releasedNode = context.getReleasedEntry();
- return releasedNode == null || releasedNode.compareTo(entry) < 0;
+ return releasedNode != null && releasedNode.compareTo(entry) < 0;
}
else
{
@@ -1982,13 +2011,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
if (subscriptionDone)
{
sub.flushBatched();
- //close autoClose subscriptions if we are not currently intent on continuing
- if (lastLoop && !sub.isSuspended() && sub.isAutoClose())
+ if (lastLoop && !sub.isSuspended())
{
-
- unregisterSubscription(sub);
-
- sub.confirmAutoClose();
+ sub.queueEmpty();
}
break;
}
@@ -2064,9 +2089,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
// Only process nodes that are not currently deleted and not dequeued
if (!node.isDispensed())
{
- // If the node has exired then aquire it
+ // If the node has exired then acquire it
if (node.expired() && node.acquire())
{
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Dequeuing expired node " + node);
+ }
// Then dequeue it.
dequeueEntry(node);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
index e57390163c..b8d8ec19f4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
@@ -104,7 +104,7 @@ public class SimpleQueueEntryList implements QueueEntryList<SimpleQueueEntryImpl
}
}
- protected SimpleQueueEntryImpl createQueueEntry(ServerMessage message)
+ protected SimpleQueueEntryImpl createQueueEntry(ServerMessage<?> message)
{
return new SimpleQueueEntryImpl(this, message);
}
@@ -116,7 +116,6 @@ public class SimpleQueueEntryList implements QueueEntryList<SimpleQueueEntryImpl
public static class QueueEntryIteratorImpl implements QueueEntryIterator<SimpleQueueEntryImpl>
{
-
private SimpleQueueEntryImpl _lastNode;
QueueEntryIteratorImpl(SimpleQueueEntryImpl startNode)
@@ -124,10 +123,9 @@ public class SimpleQueueEntryList implements QueueEntryList<SimpleQueueEntryImpl
_lastNode = startNode;
}
-
public boolean atTail()
{
- return _lastNode.getNextNode() == null;
+ return _lastNode.getNextValidEntry() == null;
}
public SimpleQueueEntryImpl getNode()
@@ -137,28 +135,17 @@ public class SimpleQueueEntryList implements QueueEntryList<SimpleQueueEntryImpl
public boolean advance()
{
+ SimpleQueueEntryImpl nextValidNode = _lastNode.getNextValidEntry();
- if(!atTail())
+ if(nextValidNode != null)
{
- SimpleQueueEntryImpl nextNode = _lastNode.getNextNode();
- while(nextNode.isDispensed() && nextNode.getNextNode() != null)
- {
- nextNode = nextNode.getNextNode();
- }
- _lastNode = nextNode;
- return true;
-
- }
- else
- {
- return false;
+ _lastNode = nextValidNode;
}
+ return nextValidNode != null;
}
-
}
-
public QueueEntryIteratorImpl iterator()
{
return new QueueEntryIteratorImpl(_head);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SortedQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SortedQueue.java
index 446f57b142..b3566df0c4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SortedQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SortedQueue.java
@@ -24,6 +24,7 @@ import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Map;
+import java.util.UUID;
public class SortedQueue extends OutOfOrderQueue
{
@@ -33,12 +34,12 @@ public class SortedQueue extends OutOfOrderQueue
private final Object _sortedQueueLock = new Object();
private final String _sortedPropertyName;
- protected SortedQueue(final String name, final boolean durable,
- final String owner, final boolean autoDelete, final boolean exclusive,
- final VirtualHost virtualHost, Map<String, Object> arguments, String sortedPropertyName)
+ protected SortedQueue(UUID id, final String name,
+ final boolean durable, final String owner, final boolean autoDelete,
+ final boolean exclusive, final VirtualHost virtualHost, Map<String, Object> arguments, String sortedPropertyName)
{
- super(name, durable, owner, autoDelete, exclusive, virtualHost,
- new SortedQueueEntryListFactory(sortedPropertyName), arguments);
+ super(id, name, durable, owner, autoDelete, exclusive,
+ virtualHost, new SortedQueueEntryListFactory(sortedPropertyName), arguments);
this._sortedPropertyName = sortedPropertyName;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
index 224d694932..4ed28b965d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
@@ -186,19 +186,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
_qmfService = qmfService;
}
- static
- {
- Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownService()));
- }
-
- private static class ShutdownService implements Runnable
- {
- public void run()
- {
- remove();
- }
- }
-
public static void initialise(IApplicationRegistry instance) throws Exception
{
if(instance == null)
@@ -273,7 +260,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
_logger.info("Shutting down ApplicationRegistry(" + instance + ")");
}
instance.close();
- instance.getBroker().getSystem().removeBroker(instance.getBroker());
}
}
catch (Exception e)
@@ -536,35 +522,49 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
}
}
-
public void close()
{
if (_logger.isInfoEnabled())
{
_logger.info("Shutting down ApplicationRegistry:" + this);
}
-
- //Stop Statistics Reporting
- if (_reportingTimer != null)
+
+ //Set the Actor for Broker Shutdown
+ CurrentActor.set(new BrokerActor(getRootMessageLogger()));
+ try
{
- _reportingTimer.cancel();
- }
+ //Stop Statistics Reporting
+ if (_reportingTimer != null)
+ {
+ _reportingTimer.cancel();
+ }
+
+ //Stop incoming connections
+ unbind();
- //Stop incoming connections
- unbind();
+ //Shutdown virtualhosts
+ close(_virtualHostRegistry);
- //Shutdown virtualhosts
- close(_virtualHostRegistry);
+ close(_authenticationManager);
- close(_authenticationManager);
+ close(_qmfService);
- close(_qmfService);
+ close(_pluginManager);
- close(_pluginManager);
+ close(_managedObjectRegistry);
- close(_managedObjectRegistry);
+ BrokerConfig broker = getBroker();
+ if(broker != null)
+ {
+ broker.getSystem().removeBroker(broker);
+ }
- CurrentActor.get().message(BrokerMessages.STOPPED());
+ CurrentActor.get().message(BrokerMessages.STOPPED());
+ }
+ finally
+ {
+ CurrentActor.remove();
+ }
}
private void unbind()
@@ -664,7 +664,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public VirtualHost createVirtualHost(final VirtualHostConfiguration vhostConfig) throws Exception
{
- VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig, null);
+ VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig);
_virtualHostRegistry.registerVirtualHost(virtualHost);
getBroker().addVirtualHost(virtualHost);
return virtualHost;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java
index 58fdc99dd3..db436b99e8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java
@@ -114,7 +114,6 @@ public class BrokerConfigAdapter implements BrokerConfig
public void addVirtualHost(final VirtualHostConfig virtualHost)
{
- virtualHost.setBroker(this);
_vhosts.put(virtualHost.getId(), virtualHost);
getConfigStore().addConfiguredObject(virtualHost);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
index e9ba2764e5..b28e3d6c89 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
@@ -25,8 +25,6 @@ import org.osgi.framework.BundleContext;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.logging.actors.BrokerActor;
-import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.management.JMXManagedObjectRegistry;
import org.apache.qpid.server.management.NoopManagedObjectRegistry;
@@ -45,22 +43,6 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
}
@Override
- public void close()
- {
- //Set the Actor for Broker Shutdown
- CurrentActor.set(new BrokerActor(getRootMessageLogger()));
- try
- {
- super.close();
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
-
- @Override
protected void initialiseManagedObjectRegistry() throws AMQException
{
if (getConfiguration().getManagementEnabled())
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
index 4ffa5a4bc2..6c1a917d5b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
@@ -24,6 +24,7 @@ import org.apache.qpid.common.Closeable;
import org.apache.qpid.server.plugins.Plugin;
import org.apache.qpid.server.security.auth.AuthenticationResult;
+import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
@@ -88,4 +89,6 @@ public interface AuthenticationManager extends Closeable, Plugin
* @return authentication result
*/
AuthenticationResult authenticate(String username, String password);
+
+ CallbackHandler getHandler(String mechanism);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
index 3fa0de2af0..b5d70d9200 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
@@ -300,6 +300,11 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
}
}
+ public CallbackHandler getHandler(String mechanism)
+ {
+ return _callbackHandlerMap.get(mechanism);
+ }
+
/**
* @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(String, String)
*/
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
index 3664568b75..4650234972 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
@@ -58,4 +58,4 @@ public class AnonymousSaslServerFactory implements SaslServerFactory
return new String[]{AnonymousSaslServer.MECHANISM};
}
}
-} \ No newline at end of file
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
index c1f306dce9..a811806c00 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
@@ -51,56 +51,65 @@ public class PlainSaslServer implements SaslServer
public byte[] evaluateResponse(byte[] response) throws SaslException
{
- try
+ int authzidNullPosition = findNullPosition(response, 0);
+ if (authzidNullPosition < 0)
{
- int authzidNullPosition = findNullPosition(response, 0);
- if (authzidNullPosition < 0)
- {
- throw new SaslException("Invalid PLAIN encoding, authzid null terminator not found");
- }
- int authcidNullPosition = findNullPosition(response, authzidNullPosition + 1);
- if (authcidNullPosition < 0)
- {
- throw new SaslException("Invalid PLAIN encoding, authcid null terminator not found");
- }
+ throw new SaslException("Invalid PLAIN encoding, authzid null terminator not found");
+ }
+ int authcidNullPosition = findNullPosition(response, authzidNullPosition + 1);
+ if (authcidNullPosition < 0)
+ {
+ throw new SaslException("Invalid PLAIN encoding, authcid null terminator not found");
+ }
+
+ PlainPasswordCallback passwordCb;
+ AuthorizeCallback authzCb;
+ try
+ {
// we do not currently support authcid in any meaningful way
String authzid = new String(response, authzidNullPosition + 1, authcidNullPosition - authzidNullPosition - 1, "utf8");
// TODO: should not get pwd as a String but as a char array...
int passwordLen = response.length - authcidNullPosition - 1;
String pwd = new String(response, authcidNullPosition + 1, passwordLen, "utf8");
-
+
// we do not care about the prompt but it throws if null
NameCallback nameCb = new NameCallback("prompt", authzid);
- PlainPasswordCallback passwordCb = new PlainPasswordCallback("prompt", false, pwd);
- AuthorizeCallback authzCb = new AuthorizeCallback(authzid, authzid);
+ passwordCb = new PlainPasswordCallback("prompt", false, pwd);
+ authzCb = new AuthorizeCallback(authzid, authzid);
Callback[] callbacks = new Callback[]{nameCb, passwordCb, authzCb};
_cbh.handle(callbacks);
- if (passwordCb.isAuthenticated())
- {
- _complete = true;
- }
- if (authzCb.isAuthorized() && _complete)
- {
- _authorizationId = authzCb.getAuthenticationID();
- return null;
- }
- else
- {
- throw new SaslException("Authentication failed");
- }
}
catch (IOException e)
{
+ if(e instanceof SaslException)
+ {
+ throw (SaslException) e;
+ }
throw new SaslException("Error processing data: " + e, e);
}
catch (UnsupportedCallbackException e)
{
throw new SaslException("Unable to obtain data from callback handler: " + e, e);
}
+
+ if (passwordCb.isAuthenticated())
+ {
+ _complete = true;
+ }
+
+ if (authzCb.isAuthorized() && _complete)
+ {
+ _authorizationId = authzCb.getAuthenticationID();
+ return null;
+ }
+ else
+ {
+ throw new SaslException("Authentication failed");
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
index fb67500da9..1307b1dbd4 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
@@ -32,19 +32,19 @@ public interface ConfigurationRecoveryHandler
public static interface QueueRecoveryHandler
{
- void queue(String queueName, String owner, boolean exclusive, FieldTable arguments);
+ void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments);
ExchangeRecoveryHandler completeQueueRecovery();
}
public static interface ExchangeRecoveryHandler
{
- void exchange(String exchangeName, String type, boolean autoDelete);
+ void exchange(UUID id, String exchangeName, String type, boolean autoDelete);
BindingRecoveryHandler completeExchangeRecovery();
}
public static interface BindingRecoveryHandler
{
- void binding(String exchangeName, String queueName, String bindingKey, ByteBuffer buf);
+ void binding(UUID bindingId, UUID exchangeId, UUID queueId, String bindingName, ByteBuffer buf);
BrokerLinkRecoveryHandler completeBindingRecovery();
}
@@ -60,13 +60,4 @@ public interface ConfigurationRecoveryHandler
void completeBridgeRecoveryForLink();
}
- public static interface QueueEntryRecoveryHandler
- {
- void complete();
-
- void queueEntry(String queueName, long messageId);
- }
-
-
-
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java b/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java
new file mode 100644
index 0000000000..1a67fdf540
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java
@@ -0,0 +1,183 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BindingRecoveryHandler;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecoveryHandler;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler;
+import org.apache.qpid.server.util.MapJsonSerializer;
+
+public class ConfiguredObjectHelper
+{
+ /**
+ * Name of queue attribute to store queue creation arguments.
+ * <p>
+ * This attribute is not defined yet on Queue configured object interface.
+ */
+ private static final String QUEUE_ARGUMENTS = "ARGUMENTS";
+
+ private MapJsonSerializer _serializer = new MapJsonSerializer();
+
+ public void loadQueue(ConfiguredObjectRecord configuredObject, QueueRecoveryHandler qrh)
+ {
+ if (Queue.class.getName().equals(configuredObject.getType()))
+ {
+ Map<String, Object> attributeMap = _serializer.deserialize(configuredObject.getAttributes());
+ String queueName = (String) attributeMap.get(Queue.NAME);
+ String owner = (String) attributeMap.get(Queue.OWNER);
+ boolean exclusive = (Boolean) attributeMap.get(Queue.EXCLUSIVE);
+ @SuppressWarnings("unchecked")
+ Map<String, Object> queueArgumentsMap = (Map<String, Object>) attributeMap.get(QUEUE_ARGUMENTS);
+ FieldTable arguments = null;
+ if (queueArgumentsMap != null)
+ {
+ arguments = FieldTable.convertToFieldTable(queueArgumentsMap);
+ }
+ qrh.queue(configuredObject.getId(), queueName, owner, exclusive, arguments);
+ }
+ }
+
+ public ConfiguredObjectRecord updateQueueConfiguredObject(final AMQQueue queue, ConfiguredObjectRecord queueRecord)
+ {
+ Map<String, Object> attributesMap = _serializer.deserialize(queueRecord.getAttributes());
+ attributesMap.put(Queue.NAME, queue.getName());
+ attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive());
+ String newJson = _serializer.serialize(attributesMap);
+ ConfiguredObjectRecord newQueueRecord = new ConfiguredObjectRecord(queue.getId(), queueRecord.getType(), newJson);
+ return newQueueRecord;
+ }
+
+ public ConfiguredObjectRecord createQueueConfiguredObject(AMQQueue queue, FieldTable arguments)
+ {
+ Map<String, Object> attributesMap = new HashMap<String, Object>();
+ attributesMap.put(Queue.NAME, queue.getName());
+ attributesMap.put(Queue.OWNER, AMQShortString.toString(queue.getOwner()));
+ attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive());
+ if (arguments != null)
+ {
+ attributesMap.put(QUEUE_ARGUMENTS, FieldTable.convertToMap(arguments));
+ }
+ String json = _serializer.serialize(attributesMap);
+ ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(queue.getId(), Queue.class.getName(), json);
+ return configuredObject;
+ }
+
+ public void loadExchange(ConfiguredObjectRecord configuredObject, ExchangeRecoveryHandler erh)
+ {
+ if (Exchange.class.getName().equals(configuredObject.getType()))
+ {
+ Map<String, Object> attributeMap = _serializer.deserialize(configuredObject.getAttributes());
+ String exchangeName = (String) attributeMap.get(Exchange.NAME);
+ String exchangeType = (String) attributeMap.get(Exchange.TYPE);
+ String lifeTimePolicy = (String) attributeMap.get(Exchange.LIFETIME_POLICY);
+ boolean autoDelete = lifeTimePolicy == null
+ || LifetimePolicy.valueOf(lifeTimePolicy) == LifetimePolicy.AUTO_DELETE;
+ erh.exchange(configuredObject.getId(), exchangeName, exchangeType, autoDelete);
+ }
+ }
+
+ public ConfiguredObjectRecord createExchangeConfiguredObject(org.apache.qpid.server.exchange.Exchange exchange)
+ {
+ Map<String, Object> attributesMap = new HashMap<String, Object>();
+ attributesMap.put(Exchange.NAME, exchange.getName());
+ attributesMap.put(Exchange.TYPE, AMQShortString.toString(exchange.getTypeShortString()));
+ attributesMap.put(Exchange.LIFETIME_POLICY, exchange.isAutoDelete() ? LifetimePolicy.AUTO_DELETE.name()
+ : LifetimePolicy.PERMANENT.name());
+ String json = _serializer.serialize(attributesMap);
+ ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(exchange.getId(), Exchange.class.getName(), json);
+ return configuredObject;
+ }
+
+ public void loadQueueBinding(ConfiguredObjectRecord configuredObject, BindingRecoveryHandler brh)
+ {
+ if (Binding.class.getName().equals(configuredObject.getType()))
+ {
+ Map<String, Object> attributeMap = _serializer.deserialize(configuredObject.getAttributes());
+ UUID exchangeId = UUID.fromString((String)attributeMap.get(Binding.EXCHANGE));
+ UUID queueId = UUID.fromString((String) attributeMap.get(Binding.QUEUE));
+ String bindingName = (String) attributeMap.get(Binding.NAME);
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> bindingArgumentsMap = (Map<String, Object>) attributeMap.get(Binding.ARGUMENTS);
+ FieldTable arguments = null;
+ if (bindingArgumentsMap != null)
+ {
+ arguments = FieldTable.convertToFieldTable(bindingArgumentsMap);
+ }
+ ByteBuffer argumentsBB = (arguments == null ? null : ByteBuffer.wrap(arguments.getDataAsBytes()));
+
+ brh.binding(configuredObject.getId(), exchangeId, queueId, bindingName, argumentsBB);
+ }
+ }
+
+ public ConfiguredObjectRecord createBindingConfiguredObject(org.apache.qpid.server.binding.Binding binding)
+ {
+ Map<String, Object> attributesMap = new HashMap<String, Object>();
+ attributesMap.put(Binding.NAME, binding.getBindingKey());
+ attributesMap.put(Binding.EXCHANGE, binding.getExchange().getId());
+ attributesMap.put(Binding.QUEUE, binding.getQueue().getId());
+ Map<String, Object> arguments = binding.getArguments();
+ if (arguments != null)
+ {
+ attributesMap.put(Binding.ARGUMENTS, arguments);
+ }
+ String json = _serializer.serialize(attributesMap);
+ ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(binding.getId(), Binding.class.getName(), json);
+ return configuredObject;
+ }
+
+ public void recoverQueues(QueueRecoveryHandler qrh, List<ConfiguredObjectRecord> configuredObjects)
+ {
+ for (ConfiguredObjectRecord configuredObjectRecord : configuredObjects)
+ {
+ loadQueue(configuredObjectRecord, qrh);
+ }
+ }
+
+ public void recoverExchanges(ExchangeRecoveryHandler erh, List<ConfiguredObjectRecord> configuredObjects)
+ {
+ for (ConfiguredObjectRecord configuredObjectRecord : configuredObjects)
+ {
+ loadExchange(configuredObjectRecord, erh);
+ }
+ }
+
+ public void recoverBindings(BindingRecoveryHandler brh, List<ConfiguredObjectRecord> configuredObjects)
+ {
+ for (ConfiguredObjectRecord configuredObjectRecord : configuredObjects)
+ {
+ loadQueueBinding(configuredObjectRecord, brh);
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java
index fc5d2a4e42..95e1713d78 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java
@@ -20,24 +20,46 @@
*/
package org.apache.qpid.server.store;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.messages.MessageStoreMessages;
-import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject;
-import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.UUID;
-public abstract class AbstractMessageStore implements MessageStore
+public class ConfiguredObjectRecord
{
- private LogSubject _logSubject;
+ private UUID _id;
+ private String _type;
+ private String _attributes;
- public void configure(VirtualHost virtualHost) throws Exception
+ public ConfiguredObjectRecord(UUID id, String type, String attributes)
{
- _logSubject = new MessageStoreLogSubject(virtualHost, this);
- CurrentActor.get().message(_logSubject, MessageStoreMessages.CREATED(this.getClass().getName()));
+ super();
+ _id = id;
+ _type = type;
+ _attributes = attributes;
}
- public void close() throws Exception
+ public UUID getId()
{
- CurrentActor.get().message(_logSubject,MessageStoreMessages.CLOSED());
+ return _id;
}
+
+ public void setId(UUID id)
+ {
+ _id = id;
+ }
+
+ public String getType()
+ {
+ return _type;
+ }
+
+ public String getAttributes()
+ {
+ return _attributes;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ConfiguredObjectRecord [id=" + _id + ", type=" + _type + ", attributes=" + _attributes + "]";
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java
index 123ecd8145..655887e5c2 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java
@@ -23,12 +23,11 @@ package org.apache.qpid.server.store;
import org.apache.commons.configuration.Configuration;
import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.binding.Binding;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.federation.Bridge;
import org.apache.qpid.server.federation.BrokerLink;
-import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.queue.AMQQueue;
public interface DurableConfigurationStore
@@ -36,23 +35,21 @@ public interface DurableConfigurationStore
public static interface Source
{
- DurableConfigurationStore getDurableConfigurationStore();
+ DurableConfigurationStore getMessageStore();
}
/**
* Called after instantiation in order to configure the message store. A particular implementation can define
* whatever parameters it wants.
*
- * @param name The name to be used by this storem
+ * @param name The name to be used by this store
* @param recoveryHandler Handler to be called as the store recovers on start up
* @param config The apache commons configuration object.
- *
* @throws Exception If any error occurs that means the store is unable to configure itself.
*/
void configureConfigStore(String name,
ConfigurationRecoveryHandler recoveryHandler,
- Configuration config,
- LogSubject logSubject) throws Exception;
+ Configuration config) throws Exception;
/**
* Makes the specified exchange persistent.
*
@@ -72,28 +69,22 @@ public interface DurableConfigurationStore
void removeExchange(Exchange exchange) throws AMQStoreException;
/**
- * Binds the specified queue to an exchange with a routing key.
+ * Store the queue binding.
*
- * @param exchange The exchange to bind to.
- * @param routingKey The routing key to bind by.
- * @param queue The queue to bind.
- * @param args Additional parameters.
+ * @param binding queue binding
*
* @throws AMQStoreException if the operation fails for any reason.
*/
- void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException;
+ void bindQueue(Binding binding) throws AMQStoreException;
/**
- * Unbinds the specified from an exchange under a particular routing key.
+ * Removes queue binding
*
- * @param exchange The exchange to unbind from.
- * @param routingKey The routing key to unbind.
- * @param queue The queue to unbind.
- * @param args Additonal parameters.
+ * @param binding queue binding to remove
*
* @throws AMQStoreException If the operation fails for any reason.
*/
- void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException;
+ void unbindQueue(Binding binding) throws AMQStoreException;
/**
* Makes the specified queue persistent.
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/Event.java b/java/broker/src/main/java/org/apache/qpid/server/store/Event.java
new file mode 100644
index 0000000000..bbde11ab4c
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/Event.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+public enum Event
+{
+ BEFORE_INIT,
+ AFTER_INIT,
+ BEFORE_ACTIVATE,
+ AFTER_ACTIVATE,
+ BEFORE_PASSIVATE,
+ AFTER_PASSIVATE,
+ BEFORE_CLOSE,
+ AFTER_CLOSE
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/EventListener.java b/java/broker/src/main/java/org/apache/qpid/server/store/EventListener.java
new file mode 100644
index 0000000000..33ae7b5b24
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/EventListener.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+public interface EventListener
+{
+ public void event(Event event);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java b/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java
new file mode 100644
index 0000000000..21ae3924b8
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+public class EventManager
+{
+ private Map<Event, List<EventListener>> _listeners = new EnumMap<Event, List<EventListener>> (Event.class);
+
+ public synchronized void addEventListener(EventListener listener, Event... events)
+ {
+ for(Event event : events)
+ {
+ List<EventListener> list = _listeners.get(event);
+ if(list == null)
+ {
+ list = new ArrayList<EventListener>();
+ _listeners.put(event,list);
+ }
+ list.add(listener);
+ }
+ }
+
+ public synchronized void notifyEvent(Event event)
+ {
+ if (_listeners.containsKey(event))
+ {
+ for (EventListener listener : _listeners.get(event))
+ {
+ listener.event(event);
+ }
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
index 546a81a050..59624b7a75 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
@@ -21,200 +21,117 @@
package org.apache.qpid.server.store;
import org.apache.commons.configuration.Configuration;
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.federation.Bridge;
-import org.apache.qpid.server.federation.BrokerLink;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
-import org.apache.qpid.server.logging.messages.MessageStoreMessages;
import org.apache.qpid.server.message.EnqueableMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
-/** A simple message store that stores the messages in a threadsafe structure in memory. */
-public class MemoryMessageStore implements MessageStore, DurableConfigurationStore
+/** A simple message store that stores the messages in a thread-safe structure in memory. */
+public class MemoryMessageStore extends NullMessageStore
{
- private static final Logger _log = Logger.getLogger(MemoryMessageStore.class);
-
- private static final int DEFAULT_HASHTABLE_CAPACITY = 50000;
-
- private static final String HASHTABLE_CAPACITY_CONFIG = "hashtable-capacity";
-
-
private final AtomicLong _messageId = new AtomicLong(1);
- private AtomicBoolean _closed = new AtomicBoolean(false);
- private LogSubject _logSubject;
+ private final AtomicBoolean _closed = new AtomicBoolean(false);
private static final Transaction IN_MEMORY_TRANSACTION = new Transaction()
{
+ @Override
+ public StoreFuture commitTranAsync() throws AMQStoreException
+ {
+ return StoreFuture.IMMEDIATE_FUTURE;
+ }
+
+ @Override
public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
{
}
+ @Override
public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
{
}
+ @Override
public void commitTran() throws AMQStoreException
{
}
- public StoreFuture commitTranAsync() throws AMQStoreException
+ @Override
+ public void abortTran() throws AMQStoreException
{
- return IMMEDIATE_FUTURE;
}
- public void abortTran() throws AMQStoreException
+ @Override
+ public void removeXid(long format, byte[] globalId, byte[] branchId)
{
}
- };
-
- public void configureConfigStore(String name, ConfigurationRecoveryHandler handler, Configuration configuration, LogSubject logSubject) throws Exception
- {
- _logSubject = logSubject;
- CurrentActor.get().message(_logSubject, ConfigStoreMessages.CREATED(this.getClass().getName()));
-
-
- }
-
- public void configureMessageStore(String name,
- MessageStoreRecoveryHandler recoveryHandler,
- Configuration config,
- LogSubject logSubject) throws Exception
- {
- if(_logSubject == null)
+ @Override
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
{
- _logSubject = logSubject;
}
- int hashtableCapacity = config.getInt(name + "." + HASHTABLE_CAPACITY_CONFIG, DEFAULT_HASHTABLE_CAPACITY);
- _log.info("Using capacity " + hashtableCapacity + " for hash tables");
- CurrentActor.get().message(_logSubject, MessageStoreMessages.CREATED(this.getClass().getName()));
- }
-
- public void close() throws Exception
- {
- _closed.getAndSet(true);
- CurrentActor.get().message(_logSubject,MessageStoreMessages.CLOSED());
-
- }
-
- public StoredMessage addMessage(StorableMessageMetaData metaData)
- {
- final long id = _messageId.getAndIncrement();
- StoredMemoryMessage message = new StoredMemoryMessage(id, metaData);
-
- return message;
- }
-
-
- public void createExchange(Exchange exchange) throws AMQStoreException
- {
-
- }
-
- public void removeExchange(Exchange exchange) throws AMQStoreException
- {
-
- }
-
- public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException
- {
-
- }
-
- public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException
- {
-
- }
-
-
- public void createQueue(AMQQueue queue) throws AMQStoreException
- {
- // Not requred to do anything
- }
+ };
- public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQStoreException
- {
- // Not required to do anything
- }
+ private final StateManager _stateManager;
+ private final EventManager _eventManager = new EventManager();
- public void removeQueue(final AMQQueue queue) throws AMQStoreException
- {
- // Not required to do anything
- }
-
- public void updateQueue(final AMQQueue queue) throws AMQStoreException
+ public MemoryMessageStore()
{
- // Not required to do anything
+ _stateManager = new StateManager(_eventManager);
}
- public void createBrokerLink(final BrokerLink link) throws AMQStoreException
+ @Override
+ public void configureConfigStore(String name, ConfigurationRecoveryHandler recoveryHandler, Configuration config) throws Exception
{
-
+ _stateManager.attainState(State.CONFIGURING);
}
- public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException
+ @Override
+ public void configureMessageStore(String name, MessageStoreRecoveryHandler recoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler, Configuration config) throws Exception
{
-
+ _stateManager.attainState(State.CONFIGURED);
}
- public void createBridge(final Bridge bridge) throws AMQStoreException
+ @Override
+ public void activate() throws Exception
{
-
+ _stateManager.attainState(State.RECOVERING);
+
+ _stateManager.attainState(State.ACTIVE);
}
- public void deleteBridge(final Bridge bridge) throws AMQStoreException
+ @Override
+ public StoredMessage addMessage(StorableMessageMetaData metaData)
{
+ final long id = _messageId.getAndIncrement();
+ StoredMemoryMessage message = new StoredMemoryMessage(id, metaData);
+ return message;
}
- public void configureTransactionLog(String name,
- TransactionLogRecoveryHandler recoveryHandler,
- Configuration storeConfiguration,
- LogSubject logSubject) throws Exception
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
+ @Override
public Transaction newTransaction()
{
return IN_MEMORY_TRANSACTION;
}
-
- public List<AMQQueue> createQueues() throws AMQException
+ @Override
+ public boolean isPersistent()
{
- return null;
+ return false;
}
- public Long getNewMessageId()
+ @Override
+ public void close() throws Exception
{
- return _messageId.getAndIncrement();
+ _stateManager.attainState(State.CLOSING);
+ _closed.getAndSet(true);
+ _stateManager.attainState(State.CLOSED);
}
- public boolean isPersistent()
+ @Override
+ public void addEventListener(EventListener eventListener, Event... events)
{
- return false;
- }
-
- private void checkNotClosed() throws MessageStoreClosedException
- {
- if (_closed.get())
- {
- throw new MessageStoreClosedException();
- }
+ _eventManager.addEventListener(eventListener, events);
}
-
-
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java
new file mode 100644
index 0000000000..8724f102c6
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+public class MemoryMessageStoreFactory implements MessageStoreFactory
+{
+
+ @Override
+ public MessageStore createMessageStore()
+ {
+ return new MemoryMessageStore();
+ }
+
+ @Override
+ public String getStoreClassName()
+ {
+ return MemoryMessageStore.class.getSimpleName();
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java
index 428bb1e41b..0fab60b6f3 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java
@@ -22,13 +22,16 @@ package org.apache.qpid.server.store;
import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.server.message.MessageMetaData_0_10;
+import org.apache.qpid.server.message.MessageMetaData_1_0;
import java.nio.ByteBuffer;
public enum MessageMetaDataType
{
META_DATA_0_8 { public Factory<MessageMetaData> getFactory() { return MessageMetaData.FACTORY; } },
- META_DATA_0_10 { public Factory<MessageMetaData_0_10> getFactory() { return MessageMetaData_0_10.FACTORY; } };
+ META_DATA_0_10 { public Factory<MessageMetaData_0_10> getFactory() { return MessageMetaData_0_10.FACTORY; } },
+ META_DATA_1_0 { public Factory<MessageMetaData_1_0> getFactory() { return MessageMetaData_1_0.FACTORY; } };
+
public static interface Factory<M extends StorableMessageMetaData>
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
index 2fecd5d4be..cf08ee00ff 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
@@ -22,52 +22,28 @@ package org.apache.qpid.server.store;
import org.apache.commons.configuration.Configuration;
-import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.message.EnqueableMessage;
-
/**
* MessageStore defines the interface to a storage area, which can be used to preserve the state of messages.
*
*/
-public interface MessageStore
+public interface MessageStore extends DurableConfigurationStore
{
- StoreFuture IMMEDIATE_FUTURE = new StoreFuture()
- {
- public boolean isComplete()
- {
- return true;
- }
-
- public void waitForCompletion()
- {
-
- }
- };
-
-
/**
* Called after instantiation in order to configure the message store. A particular implementation can define
* whatever parameters it wants.
*
- * @param name The name to be used by this storem
- * @param recoveryHandler Handler to be called as the store recovers on start up
+ * @param name The name to be used by this store
+ * @param messageRecoveryHandler Handler to be called as the store recovers on start up
+ * @param tlogRecoveryHandler
* @param config The apache commons configuration object.
- *
* @throws Exception If any error occurs that means the store is unable to configure itself.
*/
void configureMessageStore(String name,
- MessageStoreRecoveryHandler recoveryHandler,
- Configuration config,
- LogSubject logSubject) throws Exception;
-
- /**
- * Called to close and cleanup any resources used by the message store.
- *
- * @throws Exception If the close fails.
- */
- void close() throws Exception;
+ MessageStoreRecoveryHandler messageRecoveryHandler,
+ TransactionLogRecoveryHandler tlogRecoveryHandler,
+ Configuration config) throws Exception;
+ void activate() throws Exception;
public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(T metaData);
@@ -79,70 +55,16 @@ public interface MessageStore
*/
boolean isPersistent();
-
-
- public static interface Transaction
- {
- /**
- * Places a message onto a specified queue, in a given transactional context.
- *
- *
- *
- * @param queue The queue to place the message on.
- * @param message
- * @throws org.apache.qpid.AMQStoreException If the operation fails for any reason.
- */
- void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException;
-
- /**
- * Extracts a message from a specified queue, in a given transactional context.
- *
- * @param queue The queue to place the message on.
- * @param message The message to dequeue.
- * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist.
- */
- void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException;
-
-
- /**
- * Commits all operations performed within a given transactional context.
- *
- * @throws AMQStoreException If the operation fails for any reason.
- */
- void commitTran() throws AMQStoreException;
-
- /**
- * Commits all operations performed within a given transactional context.
- *
- * @throws AMQStoreException If the operation fails for any reason.
- */
- StoreFuture commitTranAsync() throws AMQStoreException;
-
- /**
- * Abandons all operations performed within a given transactional context.
- *
- * @throws AMQStoreException If the operation fails for any reason.
- */
- void abortTran() throws AMQStoreException;
-
-
-
- }
-
- public void configureTransactionLog(String name,
- TransactionLogRecoveryHandler recoveryHandler,
- Configuration storeConfiguration,
- LogSubject logSubject) throws Exception;
-
Transaction newTransaction();
+ /**
+ * Called to close and cleanup any resources used by the message store.
+ *
+ * @throws Exception If the close fails.
+ */
+ void close() throws Exception;
+ void addEventListener(EventListener eventListener, Event... events);
- public static interface StoreFuture
- {
- boolean isComplete();
-
- void waitForCompletion();
- }
-
+ String getStoreLocation();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java
new file mode 100644
index 0000000000..aba7456a44
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+public class MessageStoreConstants
+{
+
+ public static final String ENVIRONMENT_PATH_PROPERTY = "environment-path";
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java
new file mode 100644
index 0000000000..a35db62b03
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+public interface MessageStoreFactory
+{
+ MessageStore createMessageStore();
+
+ String getStoreClassName();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
new file mode 100644
index 0000000000..34c7d2d933
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.federation.Bridge;
+import org.apache.qpid.server.federation.BrokerLink;
+import org.apache.qpid.server.queue.AMQQueue;
+
+public class NullMessageStore implements MessageStore
+{
+ @Override
+ public void configureConfigStore(String name,
+ ConfigurationRecoveryHandler recoveryHandler,
+ Configuration config) throws Exception
+ {
+ }
+
+ @Override
+ public void createExchange(Exchange exchange) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void removeExchange(Exchange exchange) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void bindQueue(Binding binding) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void unbindQueue(Binding binding) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void createQueue(AMQQueue queue) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void removeQueue(AMQQueue queue) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void updateQueue(AMQQueue queue) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void createBrokerLink(final BrokerLink link) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void createBridge(final Bridge bridge) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void deleteBridge(final Bridge bridge) throws AMQStoreException
+ {
+ }
+
+ @Override
+ public void configureMessageStore(String name,
+ MessageStoreRecoveryHandler recoveryHandler,
+ TransactionLogRecoveryHandler tlogRecoveryHandler, Configuration config) throws Exception
+ {
+ }
+
+ @Override
+ public void close() throws Exception
+ {
+ }
+
+ @Override
+ public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(T metaData)
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isPersistent()
+ {
+ return false;
+ }
+
+ @Override
+ public Transaction newTransaction()
+ {
+ return null;
+ }
+
+ @Override
+ public void activate() throws Exception
+ {
+ }
+
+ @Override
+ public void addEventListener(EventListener eventListener, Event... events)
+ {
+ }
+
+ @Override
+ public String getStoreLocation()
+ {
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java b/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java
new file mode 100644
index 0000000000..caff17daa5
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.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.store;
+
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
+import org.apache.qpid.server.logging.messages.MessageStoreMessages;
+import org.apache.qpid.server.logging.messages.TransactionLogMessages;
+
+public class OperationalLoggingListener implements EventListener
+{
+ protected final LogSubject _logSubject;
+ private MessageStore _store;
+
+ private OperationalLoggingListener(final MessageStore store, LogSubject logSubject)
+ {
+ _logSubject = logSubject;
+ store.addEventListener(this, Event.BEFORE_INIT, Event.AFTER_INIT, Event.BEFORE_ACTIVATE, Event.AFTER_ACTIVATE, Event.AFTER_CLOSE);
+ _store = store;
+ }
+
+ public void event(Event event)
+ {
+ switch(event)
+ {
+ case BEFORE_INIT:
+ CurrentActor.get().message(_logSubject, ConfigStoreMessages.CREATED());
+ break;
+ case AFTER_INIT:
+ CurrentActor.get().message(_logSubject, MessageStoreMessages.CREATED());
+ CurrentActor.get().message(_logSubject, TransactionLogMessages.CREATED());
+ String storeLocation = _store.getStoreLocation();
+ if (storeLocation != null)
+ {
+ CurrentActor.get().message(_logSubject, MessageStoreMessages.STORE_LOCATION(storeLocation));
+ }
+ break;
+ case BEFORE_ACTIVATE:
+ CurrentActor.get().message(_logSubject, MessageStoreMessages.RECOVERY_START());
+ break;
+ case AFTER_ACTIVATE:
+ CurrentActor.get().message(_logSubject, MessageStoreMessages.RECOVERY_COMPLETE());
+ break;
+ case AFTER_CLOSE:
+ CurrentActor.get().message(_logSubject,MessageStoreMessages.CLOSED());
+ break;
+
+ }
+ }
+
+ public static void listen(final MessageStore store, LogSubject logSubject)
+ {
+ new OperationalLoggingListener(store, logSubject);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/State.java b/java/broker/src/main/java/org/apache/qpid/server/store/State.java
new file mode 100644
index 0000000000..7cbdede85e
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/State.java
@@ -0,0 +1,38 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+public enum State
+{
+
+ INITIAL,
+ CONFIGURING,
+ CONFIGURED,
+ RECOVERING,
+ ACTIVE,
+ QUIESCING,
+ QUIESCED,
+ CLOSING,
+ CLOSED;
+
+
+
+} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java b/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java
new file mode 100644
index 0000000000..5998be5bb6
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java
@@ -0,0 +1,151 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+
+import java.util.EnumMap;
+import java.util.Map;
+
+public class StateManager
+{
+ private State _state = State.INITIAL;
+ private EventListener _eventListener;
+
+ private static final Map<State,Map<State, Transition>> _validTransitions = new EnumMap<State, Map<State, Transition>>(State.class);
+
+
+ static class Transition
+ {
+ private final Event _event;
+ private final State _endState;
+ private final State _startState;
+
+ public Transition(State startState, State endState, Event event)
+ {
+ _event = event;
+ _startState = startState;
+ _endState = endState;
+
+ Map<State, Transition> stateTransitions = _validTransitions.get(startState);
+ if(stateTransitions == null)
+ {
+ stateTransitions = new EnumMap<State, Transition>(State.class);
+ _validTransitions.put(startState, stateTransitions);
+ }
+ stateTransitions.put(endState, this);
+ }
+
+ public Event getEvent()
+ {
+ return _event;
+ }
+
+ public State getStartState()
+ {
+ return _startState;
+ }
+
+ public State getEndState()
+ {
+ return _endState;
+ }
+
+ }
+
+ public static final Transition CONFIGURE = new Transition(State.INITIAL, State.CONFIGURING, Event.BEFORE_INIT);
+ public static final Transition CONFIGURE_COMPLETE = new Transition(State.CONFIGURING, State.CONFIGURED, Event.AFTER_INIT);
+ public static final Transition RECOVER = new Transition(State.CONFIGURED, State.RECOVERING, Event.BEFORE_ACTIVATE);
+ public static final Transition ACTIVATE = new Transition(State.RECOVERING, State.ACTIVE, Event.AFTER_ACTIVATE);
+ public static final Transition CLOSE_ACTIVE = new Transition(State.ACTIVE, State.CLOSING, Event.BEFORE_CLOSE);
+ public static final Transition CLOSE_QUIESCED = new Transition(State.QUIESCED, State.CLOSING, Event.BEFORE_CLOSE);
+ public static final Transition CLOSE_COMPLETE = new Transition(State.CLOSING, State.CLOSED, Event.AFTER_CLOSE);
+ public static final Transition QUIESCE = new Transition(State.ACTIVE, State.QUIESCING, Event.BEFORE_PASSIVATE);
+ public static final Transition QUIESCE_COMPLETE = new Transition(State.QUIESCING, State.QUIESCED, Event.BEFORE_PASSIVATE);
+ public static final Transition RESTART = new Transition(State.QUIESCED, State.RECOVERING, Event.BEFORE_ACTIVATE);
+
+
+ public StateManager(final EventManager eventManager)
+ {
+ this(new EventListener()
+ {
+ @Override
+ public void event(Event event)
+ {
+ eventManager.notifyEvent(event);
+ }
+ });
+ }
+
+
+ public StateManager(EventListener eventListener)
+ {
+ _eventListener = eventListener;
+ }
+
+ public synchronized State getState()
+ {
+ return _state;
+ }
+
+ public synchronized void stateTransition(final State current, final State desired)
+ {
+ if (_state != current)
+ {
+ throw new IllegalStateException("Cannot transition to the state: " + desired + "; need to be in state: " + current
+ + "; currently in state: " + _state);
+ }
+ attainState(desired);
+ }
+
+ public synchronized void attainState(State desired)
+ {
+ Transition transition = null;
+ final Map<State, Transition> stateTransitionMap = _validTransitions.get(_state);
+ if(stateTransitionMap != null)
+ {
+ transition = stateTransitionMap.get(desired);
+ }
+ if(transition == null)
+ {
+ throw new IllegalStateException("No valid transition from state " + _state + " to state " + desired);
+ }
+ _state = desired;
+ _eventListener.event(transition.getEvent());
+ }
+
+ public synchronized boolean isInState(State testedState)
+ {
+ return _state.equals(testedState);
+ }
+
+ public synchronized boolean isNotInState(State testedState)
+ {
+ return !isInState(testedState);
+ }
+
+ public synchronized void checkInState(State checkedState)
+ {
+ if (isNotInState(checkedState))
+ {
+ throw new IllegalStateException("Unexpected state. Was : " + _state + " but expected : " + checkedState);
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/StoreFuture.java b/java/broker/src/main/java/org/apache/qpid/server/store/StoreFuture.java
new file mode 100644
index 0000000000..7d3bf90a75
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/StoreFuture.java
@@ -0,0 +1,40 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.store;
+
+public interface StoreFuture
+{
+ StoreFuture IMMEDIATE_FUTURE = new StoreFuture()
+ {
+ public boolean isComplete()
+ {
+ return true;
+ }
+
+ public void waitForCompletion()
+ {
+ }
+ };
+
+ boolean isComplete();
+
+ void waitForCompletion();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java b/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java
index 144cc629bd..e7302270bb 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java
@@ -122,9 +122,9 @@ public class StoredMemoryMessage implements StoredMessage
return buf;
}
- public MessageStore.StoreFuture flushToStore()
+ public StoreFuture flushToStore()
{
- return MessageStore.IMMEDIATE_FUTURE;
+ return StoreFuture.IMMEDIATE_FUTURE;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java b/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java
index d4a0381929..7909003855 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java
@@ -34,7 +34,7 @@ public interface StoredMessage<M extends StorableMessageMetaData>
ByteBuffer getContent(int offsetInMessage, int size);
- MessageStore.StoreFuture flushToStore();
+ StoreFuture flushToStore();
void remove();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/Transaction.java b/java/broker/src/main/java/org/apache/qpid/server/store/Transaction.java
new file mode 100644
index 0000000000..ed6b89e373
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/Transaction.java
@@ -0,0 +1,81 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.message.EnqueableMessage;
+
+public interface Transaction
+{
+ /**
+ * Places a message onto a specified queue, in a given transactional context.
+ *
+ *
+ *
+ * @param queue The queue to place the message on.
+ * @param message
+ * @throws org.apache.qpid.AMQStoreException If the operation fails for any reason.
+ */
+ void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException;
+
+ /**
+ * Extracts a message from a specified queue, in a given transactional context.
+ *
+ * @param queue The queue to place the message on.
+ * @param message The message to dequeue.
+ * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist.
+ */
+ void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException;
+
+
+ /**
+ * Commits all operations performed within a given transactional context.
+ *
+ * @throws AMQStoreException If the operation fails for any reason.
+ */
+ void commitTran() throws AMQStoreException;
+
+ /**
+ * Commits all operations performed within a given transactional context.
+ *
+ * @throws AMQStoreException If the operation fails for any reason.
+ */
+ StoreFuture commitTranAsync() throws AMQStoreException;
+
+ /**
+ * Abandons all operations performed within a given transactional context.
+ *
+ * @throws AMQStoreException If the operation fails for any reason.
+ */
+ void abortTran() throws AMQStoreException;
+
+
+ public static interface Record
+ {
+ TransactionLogResource getQueue();
+ EnqueableMessage getMessage();
+ }
+
+ void removeXid(long format, byte[] globalId, byte[] branchId) throws AMQStoreException;
+
+ void recordXid(long format, byte[] globalId, byte[] branchId, Transaction.Record[] enqueues, Transaction.Record[] dequeues)
+ throws AMQStoreException;
+} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java
index 802596ed1e..bd4da648f9 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java
@@ -20,14 +20,23 @@
*/
package org.apache.qpid.server.store;
+import java.util.UUID;
+
public interface TransactionLogRecoveryHandler
{
QueueEntryRecoveryHandler begin(MessageStore log);
public static interface QueueEntryRecoveryHandler
{
- void queueEntry(String queuename, long messageId);
+ DtxRecordRecoveryHandler completeQueueEntryRecovery();
+
+ void queueEntry(UUID queueId, long messageId);
+ }
+
+ public static interface DtxRecordRecoveryHandler
+ {
+ void dtxRecord(long format, byte[] globalId, byte[] branchId, Transaction.Record[] enqueues, Transaction.Record[] dequeues);
- void completeQueueEntryRecovery();
+ void completeDtxRecordRecovery();
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java
index 0d81dd151d..576dca847d 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java
@@ -20,7 +20,9 @@
*/
package org.apache.qpid.server.store;
+import java.util.UUID;
+
public interface TransactionLogResource
{
- public String getResourceName();
+ public UUID getId();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
index 2877e25645..0371cdcfcb 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
@@ -18,25 +18,8 @@
* under the License.
*
*/
-package org.apache.qpid.server.store;
+package org.apache.qpid.server.store.derby;
-import org.apache.commons.configuration.Configuration;
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.federation.Bridge;
-import org.apache.qpid.server.federation.BrokerLink;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
-import org.apache.qpid.server.logging.messages.MessageStoreMessages;
-import org.apache.qpid.server.logging.messages.TransactionLogMessages;
-import org.apache.qpid.server.message.EnqueableMessage;
-import org.apache.qpid.server.queue.AMQQueue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -46,6 +29,7 @@ import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.Driver;
@@ -62,38 +46,67 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import org.apache.commons.configuration.Configuration;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.federation.Bridge;
+import org.apache.qpid.server.federation.BrokerLink;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
+import org.apache.qpid.server.store.ConfiguredObjectHelper;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.server.store.Event;
+import org.apache.qpid.server.store.EventListener;
+import org.apache.qpid.server.store.EventManager;
+import org.apache.qpid.server.store.MessageMetaDataType;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreConstants;
+import org.apache.qpid.server.store.MessageStoreRecoveryHandler;
+import org.apache.qpid.server.store.State;
+import org.apache.qpid.server.store.StateManager;
+import org.apache.qpid.server.store.StorableMessageMetaData;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.StoredMemoryMessage;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.store.Transaction;
+import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
+import org.apache.qpid.server.store.TransactionLogResource;
/**
- * An implementation of a {@link MessageStore} that uses Apache Derby as the persistance
+ * An implementation of a {@link MessageStore} that uses Apache Derby as the persistence
* mechanism.
- *
+ *
* TODO extract the SQL statements into a generic JDBC store
*/
-public class DerbyMessageStore implements MessageStore, DurableConfigurationStore
+public class DerbyMessageStore implements MessageStore
{
private static final Logger _logger = Logger.getLogger(DerbyMessageStore.class);
- public static final String ENVIRONMENT_PATH_PROPERTY = "environment-path";
-
-
private static final String SQL_DRIVER_NAME = "org.apache.derby.jdbc.EmbeddedDriver";
private static final String DB_VERSION_TABLE_NAME = "QPID_DB_VERSION";
- private static final String EXCHANGE_TABLE_NAME = "QPID_EXCHANGE";
- private static final String QUEUE_TABLE_NAME = "QPID_QUEUE";
- private static final String BINDINGS_TABLE_NAME = "QPID_BINDINGS";
- private static final String QUEUE_ENTRY_TABLE_NAME = "QPID_QUEUE_ENTRY";
+ private static final String QUEUE_ENTRY_TABLE_NAME = "QPID_QUEUE_ENTRIES";
- private static final String META_DATA_TABLE_NAME = "QPID_META_DATA";
+ private static final String META_DATA_TABLE_NAME = "QPID_MESSAGE_METADATA";
private static final String MESSAGE_CONTENT_TABLE_NAME = "QPID_MESSAGE_CONTENT";
private static final String LINKS_TABLE_NAME = "QPID_LINKS";
private static final String BRIDGES_TABLE_NAME = "QPID_BRIDGES";
+ private static final String XID_TABLE_NAME = "QPID_XIDS";
+ private static final String XID_ACTIONS_TABLE_NAME = "QPID_XID_ACTIONS";
+
+ private static final String CONFIGURED_OBJECTS_TABLE_NAME = "QPID_CONFIGURED_OBJECTS";
- private static final int DB_VERSION = 3;
+ private static final int DB_VERSION = 6;
@@ -109,38 +122,23 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
private static final String CREATE_DB_VERSION_TABLE = "CREATE TABLE "+DB_VERSION_TABLE_NAME+" ( version int not null )";
private static final String INSERT_INTO_DB_VERSION = "INSERT INTO "+DB_VERSION_TABLE_NAME+" ( version ) VALUES ( ? )";
- private static final String CREATE_EXCHANGE_TABLE = "CREATE TABLE "+EXCHANGE_TABLE_NAME+" ( name varchar(255) not null, type varchar(255) not null, autodelete SMALLINT not null, PRIMARY KEY ( name ) )";
- private static final String CREATE_QUEUE_TABLE = "CREATE TABLE "+QUEUE_TABLE_NAME+" ( name varchar(255) not null, owner varchar(255), exclusive SMALLINT not null, arguments blob, PRIMARY KEY ( name ))";
- private static final String CREATE_BINDINGS_TABLE = "CREATE TABLE "+BINDINGS_TABLE_NAME+" ( exchange_name varchar(255) not null, queue_name varchar(255) not null, binding_key varchar(255) not null, arguments blob , PRIMARY KEY ( exchange_name, queue_name, binding_key ) )";
- private static final String SELECT_FROM_QUEUE = "SELECT name, owner, exclusive, arguments FROM " + QUEUE_TABLE_NAME;
- private static final String FIND_QUEUE = "SELECT name, owner FROM " + QUEUE_TABLE_NAME + " WHERE name = ?";
- private static final String UPDATE_QUEUE_EXCLUSIVITY = "UPDATE " + QUEUE_TABLE_NAME + " SET exclusive = ? WHERE name = ?";
- private static final String SELECT_FROM_EXCHANGE = "SELECT name, type, autodelete FROM " + EXCHANGE_TABLE_NAME;
- private static final String SELECT_FROM_BINDINGS =
- "SELECT exchange_name, queue_name, binding_key, arguments FROM " + BINDINGS_TABLE_NAME + " ORDER BY exchange_name";
- private static final String FIND_BINDING =
- "SELECT * FROM " + BINDINGS_TABLE_NAME + " WHERE exchange_name = ? AND queue_name = ? AND binding_key = ? ";
- private static final String INSERT_INTO_EXCHANGE = "INSERT INTO " + EXCHANGE_TABLE_NAME + " ( name, type, autodelete ) VALUES ( ?, ?, ? )";
- private static final String DELETE_FROM_EXCHANGE = "DELETE FROM " + EXCHANGE_TABLE_NAME + " WHERE name = ?";
- private static final String FIND_EXCHANGE = "SELECT name FROM " + EXCHANGE_TABLE_NAME + " WHERE name = ?";
- private static final String INSERT_INTO_BINDINGS = "INSERT INTO " + BINDINGS_TABLE_NAME + " ( exchange_name, queue_name, binding_key, arguments ) values ( ?, ?, ?, ? )";
- private static final String DELETE_FROM_BINDINGS = "DELETE FROM " + BINDINGS_TABLE_NAME + " WHERE exchange_name = ? AND queue_name = ? AND binding_key = ?";
- private static final String INSERT_INTO_QUEUE = "INSERT INTO " + QUEUE_TABLE_NAME + " (name, owner, exclusive, arguments) VALUES (?, ?, ?, ?)";
- private static final String DELETE_FROM_QUEUE = "DELETE FROM " + QUEUE_TABLE_NAME + " WHERE name = ?";
-
- private static final String CREATE_QUEUE_ENTRY_TABLE = "CREATE TABLE "+QUEUE_ENTRY_TABLE_NAME+" ( queue_name varchar(255) not null, message_id bigint not null, PRIMARY KEY (queue_name, message_id) )";
- private static final String INSERT_INTO_QUEUE_ENTRY = "INSERT INTO " + QUEUE_ENTRY_TABLE_NAME + " (queue_name, message_id) values (?,?)";
- private static final String DELETE_FROM_QUEUE_ENTRY = "DELETE FROM " + QUEUE_ENTRY_TABLE_NAME + " WHERE queue_name = ? AND message_id =?";
- private static final String SELECT_FROM_QUEUE_ENTRY = "SELECT queue_name, message_id FROM " + QUEUE_ENTRY_TABLE_NAME + " ORDER BY queue_name, message_id";
-
-
- private static final String CREATE_META_DATA_TABLE = "CREATE TABLE "+META_DATA_TABLE_NAME+" ( message_id bigint not null, meta_data blob, PRIMARY KEY ( message_id ) )";
- private static final String CREATE_MESSAGE_CONTENT_TABLE = "CREATE TABLE "+MESSAGE_CONTENT_TABLE_NAME+" ( message_id bigint not null, offset int not null, last_byte int not null, content blob , PRIMARY KEY (message_id, offset) )";
-
- private static final String INSERT_INTO_MESSAGE_CONTENT = "INSERT INTO " + MESSAGE_CONTENT_TABLE_NAME + "( message_id, offset, last_byte, content ) values (?, ?, ?, ?)";
- private static final String SELECT_FROM_MESSAGE_CONTENT =
- "SELECT offset, content FROM " + MESSAGE_CONTENT_TABLE_NAME + " WHERE message_id = ? AND last_byte > ? AND offset < ? ORDER BY message_id, offset";
- private static final String DELETE_FROM_MESSAGE_CONTENT = "DELETE FROM " + MESSAGE_CONTENT_TABLE_NAME + " WHERE message_id = ?";
+ private static final String CREATE_QUEUE_ENTRY_TABLE = "CREATE TABLE "+QUEUE_ENTRY_TABLE_NAME+" ( queue_id varchar(36) not null, message_id bigint not null, PRIMARY KEY (queue_id, message_id) )";
+ private static final String INSERT_INTO_QUEUE_ENTRY = "INSERT INTO " + QUEUE_ENTRY_TABLE_NAME + " (queue_id, message_id) values (?,?)";
+ private static final String DELETE_FROM_QUEUE_ENTRY = "DELETE FROM " + QUEUE_ENTRY_TABLE_NAME + " WHERE queue_id = ? AND message_id =?";
+ private static final String SELECT_FROM_QUEUE_ENTRY = "SELECT queue_id, message_id FROM " + QUEUE_ENTRY_TABLE_NAME + " ORDER BY queue_id, message_id";
+
+
+ private static final String CREATE_META_DATA_TABLE = "CREATE TABLE " + META_DATA_TABLE_NAME
+ + " ( message_id bigint not null, meta_data blob, PRIMARY KEY ( message_id ) )";
+ private static final String CREATE_MESSAGE_CONTENT_TABLE = "CREATE TABLE " + MESSAGE_CONTENT_TABLE_NAME
+ + " ( message_id bigint not null, content blob , PRIMARY KEY (message_id) )";
+
+ private static final String INSERT_INTO_MESSAGE_CONTENT = "INSERT INTO " + MESSAGE_CONTENT_TABLE_NAME
+ + "( message_id, content ) values (?, ?)";
+ private static final String SELECT_FROM_MESSAGE_CONTENT = "SELECT content FROM " + MESSAGE_CONTENT_TABLE_NAME
+ + " WHERE message_id = ?";
+ private static final String DELETE_FROM_MESSAGE_CONTENT = "DELETE FROM " + MESSAGE_CONTENT_TABLE_NAME
+ + " WHERE message_id = ?";
private static final String INSERT_INTO_META_DATA = "INSERT INTO " + META_DATA_TABLE_NAME + "( message_id , meta_data ) values (?, ?)";;
private static final String SELECT_FROM_META_DATA =
@@ -155,7 +153,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
+ " arguments blob, PRIMARY KEY ( id_lsb, id_msb ))";
private static final String SELECT_FROM_LINKS =
"SELECT create_time, arguments FROM " + LINKS_TABLE_NAME + " WHERE id_lsb = ? and id_msb";
- private static final String DELETE_FROM_LINKS = "DELETE FROM " + LINKS_TABLE_NAME
+ private static final String DELETE_FROM_LINKS = "DELETE FROM " + LINKS_TABLE_NAME
+ " WHERE id_lsb = ? and id_msb = ?";
private static final String SELECT_ALL_FROM_LINKS = "SELECT id_lsb, id_msb, create_time, "
+ "arguments FROM " + LINKS_TABLE_NAME;
@@ -173,12 +171,12 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
+ " link_id_msb bigint not null,"
+ " arguments blob, PRIMARY KEY ( id_lsb, id_msb ))";
private static final String SELECT_FROM_BRIDGES =
- "SELECT create_time, link_id_lsb, link_id_msb, arguments FROM "
+ "SELECT create_time, link_id_lsb, link_id_msb, arguments FROM "
+ BRIDGES_TABLE_NAME + " WHERE id_lsb = ? and id_msb = ?";
- private static final String DELETE_FROM_BRIDGES = "DELETE FROM " + BRIDGES_TABLE_NAME
+ private static final String DELETE_FROM_BRIDGES = "DELETE FROM " + BRIDGES_TABLE_NAME
+ " WHERE id_lsb = ? and id_msb = ?";
- private static final String SELECT_ALL_FROM_BRIDGES = "SELECT id_lsb, id_msb, "
- + " create_time,"
+ private static final String SELECT_ALL_FROM_BRIDGES = "SELECT id_lsb, id_msb, "
+ + " create_time,"
+ " link_id_lsb, link_id_msb, "
+ "arguments FROM " + BRIDGES_TABLE_NAME
+ " WHERE link_id_lsb = ? and link_id_msb = ?";
@@ -190,125 +188,112 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
+ "arguments )"
+ " values (?, ?, ?, ?, ?, ?)";
+ private static final String CREATE_XIDS_TABLE =
+ "CREATE TABLE "+XID_TABLE_NAME+" ( format bigint not null,"
+ + " global_id varchar(64) for bit data, branch_id varchar(64) for bit data, PRIMARY KEY ( format, " +
+ "global_id, branch_id ))";
+ private static final String INSERT_INTO_XIDS =
+ "INSERT INTO "+XID_TABLE_NAME+" ( format, global_id, branch_id ) values (?, ?, ?)";
+ private static final String DELETE_FROM_XIDS = "DELETE FROM " + XID_TABLE_NAME
+ + " WHERE format = ? and global_id = ? and branch_id = ?";
+ private static final String SELECT_ALL_FROM_XIDS = "SELECT format, global_id, branch_id FROM " + XID_TABLE_NAME;
+
+
+ private static final String CREATE_XID_ACTIONS_TABLE =
+ "CREATE TABLE "+XID_ACTIONS_TABLE_NAME+" ( format bigint not null,"
+ + " global_id varchar(64) for bit data not null, branch_id varchar(64) for bit data not null, " +
+ "action_type char not null, queue_id varchar(36) not null, message_id bigint not null" +
+ ", PRIMARY KEY ( " +
+ "format, global_id, branch_id, action_type, queue_id, message_id))";
+ private static final String INSERT_INTO_XID_ACTIONS =
+ "INSERT INTO "+XID_ACTIONS_TABLE_NAME+" ( format, global_id, branch_id, action_type, " +
+ "queue_id, message_id ) values (?,?,?,?,?,?) ";
+ private static final String DELETE_FROM_XID_ACTIONS = "DELETE FROM " + XID_ACTIONS_TABLE_NAME
+ + " WHERE format = ? and global_id = ? and branch_id = ?";
+ private static final String SELECT_ALL_FROM_XID_ACTIONS =
+ "SELECT action_type, queue_id, message_id FROM " + XID_ACTIONS_TABLE_NAME +
+ " WHERE format = ? and global_id = ? and branch_id = ?";
+
+ private static final String CREATE_CONFIGURED_OBJECTS_TABLE = "CREATE TABLE " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " ( id VARCHAR(36) not null, object_type varchar(255), attributes blob, PRIMARY KEY (id))";
+ private static final String INSERT_INTO_CONFIGURED_OBJECTS = "INSERT INTO " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " ( id, object_type, attributes) VALUES (?,?,?)";
+ private static final String UPDATE_CONFIGURED_OBJECTS = "UPDATE " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " set object_type =?, attributes = ? where id = ?";
+ private static final String DELETE_FROM_CONFIGURED_OBJECTS = "DELETE FROM " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " where id = ?";
+ private static final String FIND_CONFIGURED_OBJECT = "SELECT object_type, attributes FROM " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " where id = ?";
+ private static final String SELECT_FROM_CONFIGURED_OBJECTS = "SELECT id, object_type, attributes FROM " + CONFIGURED_OBJECTS_TABLE_NAME;
+
+ private final Charset UTF8_CHARSET = Charset.forName("UTF-8");
private static final String DERBY_SINGLE_DB_SHUTDOWN_CODE = "08006";
+ private final StateManager _stateManager;
+
+ private final EventManager _eventManager = new EventManager();
- private LogSubject _logSubject;
- private boolean _configured;
-
+ private MessageStoreRecoveryHandler _messageRecoveryHandler;
- private static final class CommitStoreFuture implements StoreFuture
- {
- public boolean isComplete()
- {
- return true;
- }
+ private TransactionLogRecoveryHandler _tlogRecoveryHandler;
- public void waitForCompletion()
- {
+ private ConfigurationRecoveryHandler _configRecoveryHandler;
+ private String _storeLocation;
- }
- }
-
- private enum State
+ public DerbyMessageStore()
{
- INITIAL,
- CONFIGURING,
- RECOVERING,
- STARTED,
- CLOSING,
- CLOSED
+ _stateManager = new StateManager(_eventManager);
}
- private State _state = State.INITIAL;
-
+ private ConfiguredObjectHelper _configuredObjectHelper = new ConfiguredObjectHelper();
+ @Override
public void configureConfigStore(String name,
- ConfigurationRecoveryHandler recoveryHandler,
- Configuration storeConfiguration,
- LogSubject logSubject) throws Exception
+ ConfigurationRecoveryHandler configRecoveryHandler,
+ Configuration storeConfiguration) throws Exception
{
- stateTransition(State.INITIAL, State.CONFIGURING);
- _logSubject = logSubject;
- CurrentActor.get().message(_logSubject, ConfigStoreMessages.CREATED(this.getClass().getName()));
+ _stateManager.attainState(State.CONFIGURING);
+ _configRecoveryHandler = configRecoveryHandler;
- if(!_configured)
- {
- commonConfiguration(name, storeConfiguration, logSubject);
- _configured = true;
- }
-
- // this recovers durable exchanges, queues, and bindings
- recover(recoveryHandler);
-
-
- stateTransition(State.RECOVERING, State.STARTED);
+ commonConfiguration(name, storeConfiguration);
}
-
+ @Override
public void configureMessageStore(String name,
MessageStoreRecoveryHandler recoveryHandler,
- Configuration storeConfiguration,
- LogSubject logSubject) throws Exception
+ TransactionLogRecoveryHandler tlogRecoveryHandler,
+ Configuration storeConfiguration) throws Exception
{
- if(!_configured)
- {
-
- _logSubject = logSubject;
- }
-
- CurrentActor.get().message(_logSubject, MessageStoreMessages.CREATED(this.getClass().getName()));
-
- if(!_configured)
- {
-
- commonConfiguration(name, storeConfiguration, logSubject);
- _configured = true;
- }
-
- recoverMessages(recoveryHandler);
+ _tlogRecoveryHandler = tlogRecoveryHandler;
+ _messageRecoveryHandler = recoveryHandler;
+ _stateManager.attainState(State.CONFIGURED);
}
-
-
- public void configureTransactionLog(String name,
- TransactionLogRecoveryHandler recoveryHandler,
- Configuration storeConfiguration,
- LogSubject logSubject) throws Exception
+ @Override
+ public void activate() throws Exception
{
+ _stateManager.attainState(State.RECOVERING);
- if(!_configured)
- {
- _logSubject = logSubject;
- }
- CurrentActor.get().message(_logSubject, TransactionLogMessages.CREATED(this.getClass().getName()));
-
- if(!_configured)
- {
-
- _logSubject = logSubject;
-
- commonConfiguration(name, storeConfiguration, logSubject);
- _configured = true;
- }
-
- recoverQueueEntries(recoveryHandler);
+ // this recovers durable exchanges, queues, and bindings
+ recoverConfiguration(_configRecoveryHandler);
+ recoverMessages(_messageRecoveryHandler);
+ TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh = recoverQueueEntries(_tlogRecoveryHandler);
+ recoverXids(dtxrh);
+ _stateManager.attainState(State.ACTIVE);
}
-
-
- private void commonConfiguration(String name, Configuration storeConfiguration, LogSubject logSubject)
+ private void commonConfiguration(String name, Configuration storeConfiguration)
throws ClassNotFoundException, SQLException
{
initialiseDriver();
//Update to pick up QPID_WORK and use that as the default location not just derbyDB
- final String databasePath = storeConfiguration.getString(ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK")
+ final String databasePath = storeConfiguration.getString(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK")
+ File.separator + "derbyDB");
File environmentPath = new File(databasePath);
@@ -321,7 +306,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
- CurrentActor.get().message(_logSubject, MessageStoreMessages.STORE_LOCATION(environmentPath.getAbsolutePath()));
+ _storeLocation = databasePath;
createOrOpenDatabase(name, databasePath);
}
@@ -342,15 +327,14 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
Connection conn = newAutoCommitConnection();
createVersionTable(conn);
- createExchangeTable(conn);
- createQueueTable(conn);
- createBindingsTable(conn);
+ createConfiguredObjectsTable(conn);
createQueueEntryTable(conn);
createMetaDataTable(conn);
createMessageContentTable(conn);
createLinkTable(conn);
createBridgeTable(conn);
-
+ createXidTable(conn);
+ createXidActionTable(conn);
conn.close();
}
@@ -384,15 +368,14 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
-
- private void createExchangeTable(final Connection conn) throws SQLException
+ private void createConfiguredObjectsTable(final Connection conn) throws SQLException
{
- if(!tableExists(EXCHANGE_TABLE_NAME, conn))
+ if(!tableExists(CONFIGURED_OBJECTS_TABLE_NAME, conn))
{
Statement stmt = conn.createStatement();
try
{
- stmt.execute(CREATE_EXCHANGE_TABLE);
+ stmt.execute(CREATE_CONFIGURED_OBJECTS_TABLE);
}
finally
{
@@ -401,30 +384,31 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
- private void createQueueTable(final Connection conn) throws SQLException
+ private void createQueueEntryTable(final Connection conn) throws SQLException
{
- if(!tableExists(QUEUE_TABLE_NAME, conn))
+ if(!tableExists(QUEUE_ENTRY_TABLE_NAME, conn))
{
Statement stmt = conn.createStatement();
try
{
- stmt.execute(CREATE_QUEUE_TABLE);
+ stmt.execute(CREATE_QUEUE_ENTRY_TABLE);
}
finally
{
stmt.close();
}
}
+
}
- private void createBindingsTable(final Connection conn) throws SQLException
+ private void createMetaDataTable(final Connection conn) throws SQLException
{
- if(!tableExists(BINDINGS_TABLE_NAME, conn))
+ if(!tableExists(META_DATA_TABLE_NAME, conn))
{
Statement stmt = conn.createStatement();
try
{
- stmt.execute(CREATE_BINDINGS_TABLE);
+ stmt.execute(CREATE_META_DATA_TABLE);
}
finally
{
@@ -434,14 +418,15 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
- private void createQueueEntryTable(final Connection conn) throws SQLException
+
+ private void createMessageContentTable(final Connection conn) throws SQLException
{
- if(!tableExists(QUEUE_ENTRY_TABLE_NAME, conn))
+ if(!tableExists(MESSAGE_CONTENT_TABLE_NAME, conn))
{
Statement stmt = conn.createStatement();
try
{
- stmt.execute(CREATE_QUEUE_ENTRY_TABLE);
+ stmt.execute(CREATE_MESSAGE_CONTENT_TABLE);
}
finally
{
@@ -451,49 +436,47 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
- private void createMetaDataTable(final Connection conn) throws SQLException
+ private void createLinkTable(final Connection conn) throws SQLException
{
- if(!tableExists(META_DATA_TABLE_NAME, conn))
+ if(!tableExists(LINKS_TABLE_NAME, conn))
{
Statement stmt = conn.createStatement();
try
{
- stmt.execute(CREATE_META_DATA_TABLE);
+ stmt.execute(CREATE_LINKS_TABLE);
}
finally
{
stmt.close();
}
}
-
}
- private void createMessageContentTable(final Connection conn) throws SQLException
+ private void createBridgeTable(final Connection conn) throws SQLException
{
- if(!tableExists(MESSAGE_CONTENT_TABLE_NAME, conn))
+ if(!tableExists(BRIDGES_TABLE_NAME, conn))
{
Statement stmt = conn.createStatement();
try
{
- stmt.execute(CREATE_MESSAGE_CONTENT_TABLE);
+ stmt.execute(CREATE_BRIDGES_TABLE);
}
finally
{
stmt.close();
}
}
-
}
- private void createLinkTable(final Connection conn) throws SQLException
+ private void createXidTable(final Connection conn) throws SQLException
{
- if(!tableExists(LINKS_TABLE_NAME, conn))
+ if(!tableExists(XID_TABLE_NAME, conn))
{
Statement stmt = conn.createStatement();
try
{
- stmt.execute(CREATE_LINKS_TABLE);
+ stmt.execute(CREATE_XIDS_TABLE);
}
finally
{
@@ -503,14 +486,14 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
- private void createBridgeTable(final Connection conn) throws SQLException
+ private void createXidActionTable(final Connection conn) throws SQLException
{
- if(!tableExists(BRIDGES_TABLE_NAME, conn))
+ if(!tableExists(XID_ACTIONS_TABLE_NAME, conn))
{
Statement stmt = conn.createStatement();
try
{
- stmt.execute(CREATE_BRIDGES_TABLE);
+ stmt.execute(CREATE_XID_ACTIONS_TABLE);
}
finally
{
@@ -519,9 +502,6 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
-
-
-
private boolean tableExists(final String tableName, final Connection conn) throws SQLException
{
PreparedStatement stmt = conn.prepareStatement(TABLE_EXISTANCE_QUERY);
@@ -542,34 +522,29 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
{
stmt.close();
}
-
}
- public void recover(ConfigurationRecoveryHandler recoveryHandler) throws AMQException
+ private void recoverConfiguration(ConfigurationRecoveryHandler recoveryHandler) throws AMQException
{
- stateTransition(State.CONFIGURING, State.RECOVERING);
-
- CurrentActor.get().message(_logSubject,MessageStoreMessages.RECOVERY_START());
-
try
{
+ List<ConfiguredObjectRecord> configuredObjects = loadConfiguredObjects();
ConfigurationRecoveryHandler.QueueRecoveryHandler qrh = recoveryHandler.begin(this);
- loadQueues(qrh);
+ _configuredObjectHelper.recoverQueues(qrh, configuredObjects);
ConfigurationRecoveryHandler.ExchangeRecoveryHandler erh = qrh.completeQueueRecovery();
- List<String> exchanges = loadExchanges(erh);
+ _configuredObjectHelper.recoverExchanges(erh, configuredObjects);
+
ConfigurationRecoveryHandler.BindingRecoveryHandler brh = erh.completeExchangeRecovery();
- recoverBindings(brh, exchanges);
+ _configuredObjectHelper.recoverBindings(brh, configuredObjects);
+
ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler lrh = brh.completeBindingRecovery();
recoverBrokerLinks(lrh);
}
catch (SQLException e)
{
-
throw new AMQStoreException("Error recovering persistent state: " + e.getMessage(), e);
}
-
-
}
private void recoverBrokerLinks(final ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler lrh)
@@ -598,12 +573,12 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
Blob argumentsAsBlob = rs.getBlob(4);
byte[] dataAsBytes = argumentsAsBlob.getBytes(1,(int) argumentsAsBlob.length());
-
+
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(dataAsBytes));
int size = dis.readInt();
-
+
Map<String,String> arguments = new HashMap<String, String>();
-
+
for(int i = 0; i < size; i++)
{
arguments.put(dis.readUTF(), dis.readUTF());
@@ -710,179 +685,11 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
- private void loadQueues(ConfigurationRecoveryHandler.QueueRecoveryHandler qrh) throws SQLException
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- Statement stmt = conn.createStatement();
- try
- {
- ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE);
- try
- {
-
- while(rs.next())
- {
- String queueName = rs.getString(1);
- String owner = rs.getString(2);
- boolean exclusive = rs.getBoolean(3);
- Blob argumentsAsBlob = rs.getBlob(4);
-
- byte[] dataAsBytes = argumentsAsBlob.getBytes(1,(int) argumentsAsBlob.length());
- FieldTable arguments;
- if(dataAsBytes.length > 0)
- {
-
- try
- {
- arguments = new FieldTable(new DataInputStream(new ByteArrayInputStream(dataAsBytes)),dataAsBytes.length);
- }
- catch (IOException e)
- {
- throw new RuntimeException("IO Exception should not be thrown",e);
- }
- }
- else
- {
- arguments = null;
- }
-
- qrh.queue(queueName, owner, exclusive, arguments);
-
- }
-
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
-
-
- private List<String> loadExchanges(ConfigurationRecoveryHandler.ExchangeRecoveryHandler erh) throws SQLException
- {
-
- List<String> exchanges = new ArrayList<String>();
- Connection conn = null;
- try
- {
- conn = newAutoCommitConnection();
-
- Statement stmt = conn.createStatement();
- try
- {
- ResultSet rs = stmt.executeQuery(SELECT_FROM_EXCHANGE);
- try
- {
- while(rs.next())
- {
- String exchangeName = rs.getString(1);
- String type = rs.getString(2);
- boolean autoDelete = rs.getShort(3) != 0;
-
- exchanges.add(exchangeName);
-
- erh.exchange(exchangeName, type, autoDelete);
-
- }
- return exchanges;
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- if(conn != null)
- {
- conn.close();
- }
- }
-
- }
-
- private void recoverBindings(ConfigurationRecoveryHandler.BindingRecoveryHandler brh, List<String> exchanges) throws SQLException
- {
- _logger.info("Recovering bindings...");
-
- Connection conn = null;
- try
- {
- conn = newAutoCommitConnection();
-
- PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_BINDINGS);
-
- try
- {
- ResultSet rs = stmt.executeQuery();
-
- try
- {
-
- while(rs.next())
- {
- String exchangeName = rs.getString(1);
- String queueName = rs.getString(2);
- String bindingKey = rs.getString(3);
- Blob arguments = rs.getBlob(4);
- java.nio.ByteBuffer buf;
-
- if(arguments != null && arguments.length() != 0)
- {
- byte[] argumentBytes = arguments.getBytes(1, (int) arguments.length());
- buf = java.nio.ByteBuffer.wrap(argumentBytes);
- }
- else
- {
- buf = null;
- }
-
- brh.binding(exchangeName, queueName, bindingKey, buf);
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
-
- }
- finally
- {
- if(conn != null)
- {
- conn.close();
- }
- }
- }
-
-
-
+ @Override
public void close() throws Exception
{
- CurrentActor.get().message(_logSubject,MessageStoreMessages.CLOSED());
_closed.getAndSet(true);
+ _stateManager.stateTransition(State.ACTIVE, State.CLOSING);
try
{
@@ -892,9 +699,9 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
_logger.error("Unable to shut down the store");
}
catch (SQLException e)
- {
- if (e.getSQLState().equalsIgnoreCase(DERBY_SINGLE_DB_SHUTDOWN_CODE))
- {
+ {
+ if (e.getSQLState().equalsIgnoreCase(DERBY_SINGLE_DB_SHUTDOWN_CODE))
+ {
//expected and represents a clean shutdown of this database only, do nothing.
}
else
@@ -902,8 +709,11 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
_logger.error("Exception whilst shutting down the store: " + e);
}
}
+
+ _stateManager.stateTransition(State.CLOSING, State.CLOSED);
}
+ @Override
public StoredMessage addMessage(StorableMessageMetaData metaData)
{
if(metaData.isPersistent())
@@ -981,291 +791,67 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
+ @Override
public void createExchange(Exchange exchange) throws AMQStoreException
{
- if (_state != State.RECOVERING)
+ if (_stateManager.isInState(State.ACTIVE))
{
- try
- {
- Connection conn = newAutoCommitConnection();
-
- try
- {
-
-
- PreparedStatement stmt = conn.prepareStatement(FIND_EXCHANGE);
- try
- {
- stmt.setString(1, exchange.getNameShortString().toString());
- ResultSet rs = stmt.executeQuery();
- try
- {
-
- // If we don't have any data in the result set then we can add this exchange
- if (!rs.next())
- {
-
- PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_EXCHANGE);
- try
- {
- insertStmt.setString(1, exchange.getName().toString());
- insertStmt.setString(2, exchange.getTypeShortString().asString());
- insertStmt.setShort(3, exchange.isAutoDelete() ? (short) 1 : (short) 0);
- insertStmt.execute();
- }
- finally
- {
- insertStmt.close();
- }
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
-
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error writing Exchange with name " + exchange.getNameShortString() + " to database: " + e.getMessage(), e);
- }
+ ConfiguredObjectRecord configuredObject = _configuredObjectHelper.createExchangeConfiguredObject(exchange);
+ insertConfiguredObject(configuredObject);
}
}
+ @Override
public void removeExchange(Exchange exchange) throws AMQStoreException
{
-
- try
+ int results = removeConfiguredObject(exchange.getId());
+ if (results == 0)
{
- Connection conn = newAutoCommitConnection();
- try
- {
- PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_EXCHANGE);
- try
- {
- stmt.setString(1, exchange.getNameShortString().toString());
- int results = stmt.executeUpdate();
- stmt.close();
- if(results == 0)
- {
- throw new AMQStoreException("Exchange " + exchange.getNameShortString() + " not found");
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error deleting Exchange with name " + exchange.getNameShortString() + " from database: " + e.getMessage(), e);
+ throw new AMQStoreException("Exchange " + exchange.getName() + " with id " + exchange.getId() + " not found");
}
}
- public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args)
+ @Override
+ public void bindQueue(Binding binding)
throws AMQStoreException
{
- if (_state != State.RECOVERING)
+ if (_stateManager.isInState(State.ACTIVE))
{
- try
- {
- Connection conn = newAutoCommitConnection();
-
- try
- {
-
- PreparedStatement stmt = conn.prepareStatement(FIND_BINDING);
- try
- {
- stmt.setString(1, exchange.getNameShortString().toString() );
- stmt.setString(2, queue.getNameShortString().toString());
- stmt.setString(3, routingKey == null ? null : routingKey.toString());
-
- ResultSet rs = stmt.executeQuery();
- try
- {
- // If this binding is not already in the store then create it.
- if (!rs.next())
- {
- PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_BINDINGS);
- try
- {
- insertStmt.setString(1, exchange.getNameShortString().toString() );
- insertStmt.setString(2, queue.getNameShortString().toString());
- insertStmt.setString(3, routingKey == null ? null : routingKey.toString());
- if(args != null)
- {
- // TODO - In Java 6 we could use create/set Blob
- byte[] bytes = args.getDataAsBytes();
- ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
- insertStmt.setBinaryStream(4, bis, bytes.length);
- }
- else
- {
- insertStmt.setNull(4, Types.BLOB);
- }
-
- insertStmt.executeUpdate();
- }
- finally
- {
- insertStmt.close();
- }
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error writing binding for AMQQueue with name " + queue.getNameShortString() + " to exchange "
- + exchange.getNameShortString() + " to database: " + e.getMessage(), e);
- }
-
+ ConfiguredObjectRecord configuredObject = _configuredObjectHelper.createBindingConfiguredObject(binding);
+ insertConfiguredObject(configuredObject);
}
-
-
}
- public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args)
+ @Override
+ public void unbindQueue(Binding binding)
throws AMQStoreException
{
- Connection conn = null;
- PreparedStatement stmt = null;
-
- try
+ int results = removeConfiguredObject(binding.getId());
+ if (results == 0)
{
- conn = newAutoCommitConnection();
- // exchange_name varchar(255) not null, queue_name varchar(255) not null, binding_key varchar(255), arguments blob
- stmt = conn.prepareStatement(DELETE_FROM_BINDINGS);
- stmt.setString(1, exchange.getNameShortString().toString() );
- stmt.setString(2, queue.getNameShortString().toString());
- stmt.setString(3, routingKey == null ? null : routingKey.toString());
-
- int result = stmt.executeUpdate();
-
- if(result != 1)
- {
- throw new AMQStoreException("Queue binding for queue with name " + queue.getNameShortString() + " to exchange "
- + exchange.getNameShortString() + " not found");
- }
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error removing binding for AMQQueue with name " + queue.getNameShortString() + " to exchange "
- + exchange.getNameShortString() + " in database: " + e.getMessage(), e);
- }
- finally
- {
- closePreparedStatement(stmt);
- closeConnection(conn);
+ throw new AMQStoreException("Binding " + binding + " not found");
}
}
+ @Override
public void createQueue(AMQQueue queue) throws AMQStoreException
{
createQueue(queue, null);
}
+ @Override
public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQStoreException
{
_logger.debug("public void createQueue(AMQQueue queue = " + queue + "): called");
- if (_state != State.RECOVERING)
+ if (_stateManager.isInState(State.ACTIVE))
{
- try
- {
- Connection conn = newAutoCommitConnection();
-
- PreparedStatement stmt = conn.prepareStatement(FIND_QUEUE);
- try
- {
- stmt.setString(1, queue.getNameShortString().toString());
- ResultSet rs = stmt.executeQuery();
- try
- {
-
- // If we don't have any data in the result set then we can add this queue
- if (!rs.next())
- {
- PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_QUEUE);
-
- try
- {
- String owner = queue.getOwner() == null ? null : queue.getOwner().toString();
-
- insertStmt.setString(1, queue.getNameShortString().toString());
- insertStmt.setString(2, owner);
- insertStmt.setBoolean(3,queue.isExclusive());
-
- final byte[] underlying;
- if(arguments != null)
- {
- underlying = arguments.getDataAsBytes();
- }
- else
- {
- underlying = new byte[0];
- }
-
- ByteArrayInputStream bis = new ByteArrayInputStream(underlying);
- insertStmt.setBinaryStream(4,bis,underlying.length);
-
- insertStmt.execute();
- }
- finally
- {
- insertStmt.close();
- }
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- conn.close();
-
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error writing AMQQueue with name " + queue.getNameShortString() + " to database: " + e.getMessage(), e);
- }
+ ConfiguredObjectRecord queueConfiguredObject = _configuredObjectHelper.createQueueConfiguredObject(queue, arguments);
+ insertConfiguredObject(queueConfiguredObject);
}
}
-
+
/**
* Updates the specified queue in the persistent store, IF it is already present. If the queue
* is not present in the store, it will not be added.
@@ -1275,61 +861,19 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
* @param queue The queue to update the entry for.
* @throws AMQStoreException If the operation fails for any reason.
*/
+ @Override
public void updateQueue(final AMQQueue queue) throws AMQStoreException
{
- if (_state != State.RECOVERING)
+ if (_stateManager.isInState(State.ACTIVE))
{
- try
+ ConfiguredObjectRecord queueConfiguredObject = loadConfiguredObject(queue.getId());
+ if (queueConfiguredObject != null)
{
- Connection conn = newAutoCommitConnection();
-
- try
- {
- PreparedStatement stmt = conn.prepareStatement(FIND_QUEUE);
- try
- {
- stmt.setString(1, queue.getNameShortString().toString());
-
- ResultSet rs = stmt.executeQuery();
- try
- {
- if (rs.next())
- {
- PreparedStatement stmt2 = conn.prepareStatement(UPDATE_QUEUE_EXCLUSIVITY);
- try
- {
- stmt2.setBoolean(1,queue.isExclusive());
- stmt2.setString(2, queue.getNameShortString().toString());
-
- stmt2.execute();
- }
- finally
- {
- stmt2.close();
- }
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error updating AMQQueue with name " + queue.getNameShortString() + " to database: " + e.getMessage(), e);
+ ConfiguredObjectRecord newQueueRecord = _configuredObjectHelper.updateQueueConfiguredObject(queue, queueConfiguredObject);
+ updateConfiguredObject(newQueueRecord);
}
}
-
+
}
/**
@@ -1355,7 +899,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
throw sqlEx;
}
}
-
+
return connection;
}
@@ -1385,42 +929,24 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
return connection;
}
+ @Override
public void removeQueue(final AMQQueue queue) throws AMQStoreException
{
AMQShortString name = queue.getNameShortString();
_logger.debug("public void removeQueue(AMQShortString name = " + name + "): called");
- Connection conn = null;
- PreparedStatement stmt = null;
- try
- {
- conn = newAutoCommitConnection();
- stmt = conn.prepareStatement(DELETE_FROM_QUEUE);
- stmt.setString(1, name.toString());
- int results = stmt.executeUpdate();
-
- if (results == 0)
- {
- throw new AMQStoreException("Queue " + name + " not found");
- }
- }
- catch (SQLException e)
+ int results = removeConfiguredObject(queue.getId());
+ if (results == 0)
{
- throw new AMQStoreException("Error deleting AMQQueue with name " + name + " from database: " + e.getMessage(), e);
+ throw new AMQStoreException("Queue " + name + " with id " + queue.getId() + " not found");
}
- finally
- {
- closePreparedStatement(stmt);
- closeConnection(conn);
- }
-
-
}
+ @Override
public void createBrokerLink(final BrokerLink link) throws AMQStoreException
{
_logger.debug("public void createBrokerLink(BrokerLink = " + link + "): called");
- if (_state != State.RECOVERING)
+ if (_stateManager.isInState(State.ACTIVE))
{
try
{
@@ -1429,7 +955,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
PreparedStatement stmt = conn.prepareStatement(FIND_LINK);
try
{
-
+
stmt.setLong(1, link.getId().getLeastSignificantBits());
stmt.setLong(2, link.getId().getMostSignificantBits());
ResultSet rs = stmt.executeQuery();
@@ -1443,7 +969,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
try
{
-
+
insertStmt.setLong(1, link.getId().getLeastSignificantBits());
insertStmt.setLong(2, link.getId().getMostSignificantBits());
insertStmt.setLong(3, link.getCreateTime());
@@ -1512,6 +1038,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
return argumentBytes;
}
+ @Override
public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException
{
_logger.debug("public void deleteBrokerLink( " + link + "): called");
@@ -1543,11 +1070,12 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
+ @Override
public void createBridge(final Bridge bridge) throws AMQStoreException
{
_logger.debug("public void createBridge(BrokerLink = " + bridge + "): called");
- if (_state != State.RECOVERING)
+ if (_stateManager.isInState(State.ACTIVE))
{
try
{
@@ -1613,6 +1141,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
+ @Override
public void deleteBridge(final Bridge bridge) throws AMQStoreException
{
_logger.debug("public void deleteBridge( " + bridge + "): called");
@@ -1643,6 +1172,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
+ @Override
public Transaction newTransaction()
{
return new DerbyTransaction();
@@ -1650,8 +1180,6 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
public void enqueueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQStoreException
{
- String name = queue.getResourceName();
-
Connection conn = connWrapper.getConnection();
@@ -1659,13 +1187,13 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
{
if (_logger.isDebugEnabled())
{
- _logger.debug("Enqueuing message " + messageId + " on queue " + name + "[Connection" + conn + "]");
+ _logger.debug("Enqueuing message " + messageId + " on queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" ) + queue.getId()+ "[Connection" + conn + "]");
}
-
+
PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_QUEUE_ENTRY);
try
{
- stmt.setString(1,name);
+ stmt.setString(1, queue.getId().toString());
stmt.setLong(2,messageId);
stmt.executeUpdate();
}
@@ -1677,7 +1205,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
catch (SQLException e)
{
_logger.error("Failed to enqueue: " + e.getMessage(), e);
- throw new AMQStoreException("Error writing enqueued message with id " + messageId + " for queue " + name
+ throw new AMQStoreException("Error writing enqueued message with id " + messageId + " for queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" ) + " with id " + queue.getId()
+ " to database", e);
}
@@ -1685,8 +1213,6 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
public void dequeueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQStoreException
{
- String name = queue.getResourceName();
-
Connection conn = connWrapper.getConnection();
@@ -1696,7 +1222,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_QUEUE_ENTRY);
try
{
- stmt.setString(1,name);
+ stmt.setString(1, queue.getId().toString());
stmt.setLong(2,messageId);
int results = stmt.executeUpdate();
@@ -1704,12 +1230,14 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
if(results != 1)
{
- throw new AMQStoreException("Unable to find message with id " + messageId + " on queue " + name);
+ throw new AMQStoreException("Unable to find message with id " + messageId + " on queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" )
+ + " with id " + queue.getId());
}
if (_logger.isDebugEnabled())
{
- _logger.debug("Dequeuing message " + messageId + " on queue " + name );
+ _logger.debug("Dequeuing message " + messageId + " on queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" )
+ + " with id " + queue.getId());
}
}
finally
@@ -1720,8 +1248,128 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
catch (SQLException e)
{
_logger.error("Failed to dequeue: " + e.getMessage(), e);
- throw new AMQStoreException("Error deleting enqueued message with id " + messageId + " for queue " + name
- + " from database", e);
+ throw new AMQStoreException("Error deleting enqueued message with id " + messageId + " for queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" )
+ + " with id " + queue.getId() + " from database", e);
+ }
+
+ }
+
+
+ private void removeXid(ConnectionWrapper connWrapper, long format, byte[] globalId, byte[] branchId)
+ throws AMQStoreException
+ {
+ Connection conn = connWrapper.getConnection();
+
+
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_XIDS);
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2,globalId);
+ stmt.setBytes(3,branchId);
+ int results = stmt.executeUpdate();
+
+
+
+ if(results != 1)
+ {
+ throw new AMQStoreException("Unable to find message with xid");
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ stmt = conn.prepareStatement(DELETE_FROM_XID_ACTIONS);
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2,globalId);
+ stmt.setBytes(3,branchId);
+ int results = stmt.executeUpdate();
+
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ }
+ catch (SQLException e)
+ {
+ _logger.error("Failed to dequeue: " + e.getMessage(), e);
+ throw new AMQStoreException("Error deleting enqueued message with xid", e);
+ }
+
+ }
+
+
+ private void recordXid(ConnectionWrapper connWrapper, long format, byte[] globalId, byte[] branchId,
+ Transaction.Record[] enqueues, Transaction.Record[] dequeues) throws AMQStoreException
+ {
+ Connection conn = connWrapper.getConnection();
+
+
+ try
+ {
+
+ PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_XIDS);
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2, globalId);
+ stmt.setBytes(3, branchId);
+ stmt.executeUpdate();
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ stmt = conn.prepareStatement(INSERT_INTO_XID_ACTIONS);
+
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2, globalId);
+ stmt.setBytes(3, branchId);
+
+ if(enqueues != null)
+ {
+ stmt.setString(4, "E");
+ for(Transaction.Record record : enqueues)
+ {
+ stmt.setString(5, record.getQueue().getId().toString());
+ stmt.setLong(6, record.getMessage().getMessageNumber());
+ stmt.executeUpdate();
+ }
+ }
+
+ if(dequeues != null)
+ {
+ stmt.setString(4, "D");
+ for(Transaction.Record record : dequeues)
+ {
+ stmt.setString(5, record.getQueue().getId().toString());
+ stmt.setLong(6, record.getMessage().getMessageNumber());
+ stmt.executeUpdate();
+ }
+ }
+
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ }
+ catch (SQLException e)
+ {
+ _logger.error("Failed to enqueue: " + e.getMessage(), e);
+ throw new AMQStoreException("Error writing xid ", e);
}
}
@@ -1770,7 +1418,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
public StoreFuture commitTranAsync(ConnectionWrapper connWrapper) throws AMQStoreException
{
commitTran(connWrapper);
- return new CommitStoreFuture();
+ return StoreFuture.IMMEDIATE_FUTURE;
}
public void abortTran(ConnectionWrapper connWrapper) throws AMQStoreException
@@ -1811,7 +1459,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
{
_logger.debug("Adding metadata for message " +messageId);
}
-
+
PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_META_DATA);
try
{
@@ -1854,7 +1502,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
{
stmt.close();
}
-
+
}
@@ -1919,7 +1567,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
- private void recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) throws SQLException
+ private TransactionLogRecoveryHandler.DtxRecordRecoveryHandler recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) throws SQLException
{
Connection conn = newAutoCommitConnection();
try
@@ -1935,9 +1583,9 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
while(rs.next())
{
- String queueName = rs.getString(1);
+ String id = rs.getString(1);
long messageId = rs.getLong(2);
- queueEntryHandler.queueEntry(queueName,messageId);
+ queueEntryHandler.queueEntry(UUID.fromString(id), messageId);
}
}
finally
@@ -1950,7 +1598,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
stmt.close();
}
- queueEntryHandler.completeQueueEntryRecovery();
+ return queueEntryHandler.completeQueueEntryRecovery();
}
finally
{
@@ -1958,6 +1606,172 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
+ private static final class Xid
+ {
+
+ private final long _format;
+ private final byte[] _globalId;
+ private final byte[] _branchId;
+
+ public Xid(long format, byte[] globalId, byte[] branchId)
+ {
+ _format = format;
+ _globalId = globalId;
+ _branchId = branchId;
+ }
+
+ public long getFormat()
+ {
+ return _format;
+ }
+
+ public byte[] getGlobalId()
+ {
+ return _globalId;
+ }
+
+ public byte[] getBranchId()
+ {
+ return _branchId;
+ }
+ }
+
+ private static class RecordImpl implements Transaction.Record, TransactionLogResource, EnqueableMessage
+ {
+
+ private long _messageNumber;
+ private UUID _queueId;
+
+ public RecordImpl(UUID queueId, long messageNumber)
+ {
+ _messageNumber = messageNumber;
+ _queueId = queueId;
+ }
+
+ @Override
+ public TransactionLogResource getQueue()
+ {
+ return this;
+ }
+
+ @Override
+ public EnqueableMessage getMessage()
+ {
+ return this;
+ }
+
+ @Override
+ public long getMessageNumber()
+ {
+ return _messageNumber;
+ }
+
+ @Override
+ public boolean isPersistent()
+ {
+ return true;
+ }
+
+ @Override
+ public StoredMessage getStoredMessage()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return _queueId;
+ }
+ }
+
+ private void recoverXids(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh) throws SQLException
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ List<Xid> xids = new ArrayList<Xid>();
+
+ Statement stmt = conn.createStatement();
+ try
+ {
+ ResultSet rs = stmt.executeQuery(SELECT_ALL_FROM_XIDS);
+ try
+ {
+ while(rs.next())
+ {
+
+ long format = rs.getLong(1);
+ byte[] globalId = rs.getBytes(2);
+ byte[] branchId = rs.getBytes(3);
+ xids.add(new Xid(format, globalId, branchId));
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+
+
+ for(Xid xid : xids)
+ {
+ List<RecordImpl> enqueues = new ArrayList<RecordImpl>();
+ List<RecordImpl> dequeues = new ArrayList<RecordImpl>();
+
+ PreparedStatement pstmt = conn.prepareStatement(SELECT_ALL_FROM_XID_ACTIONS);
+
+ try
+ {
+ pstmt.setLong(1, xid.getFormat());
+ pstmt.setBytes(2, xid.getGlobalId());
+ pstmt.setBytes(3, xid.getBranchId());
+
+ ResultSet rs = pstmt.executeQuery();
+ try
+ {
+ while(rs.next())
+ {
+
+ String actionType = rs.getString(1);
+ UUID queueId = UUID.fromString(rs.getString(2));
+ long messageId = rs.getLong(3);
+
+ RecordImpl record = new RecordImpl(queueId, messageId);
+ List<RecordImpl> records = "E".equals(actionType) ? enqueues : dequeues;
+ records.add(record);
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ pstmt.close();
+ }
+
+ dtxrh.dtxRecord(xid.getFormat(), xid.getGlobalId(), xid.getBranchId(),
+ enqueues.toArray(new RecordImpl[enqueues.size()]),
+ dequeues.toArray(new RecordImpl[dequeues.size()]));
+ }
+
+
+ dtxrh.completeDtxRecordRecovery();
+ }
+ finally
+ {
+ conn.close();
+ }
+
+ }
+
StorableMessageMetaData getMetaData(long messageId) throws SQLException
{
@@ -2007,11 +1821,11 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
- private void addContent(Connection conn, long messageId, int offset, ByteBuffer src)
+ private void addContent(Connection conn, long messageId, ByteBuffer src)
{
if(_logger.isDebugEnabled())
{
- _logger.debug("Adding content chunk offset " + offset + " for message " +messageId);
+ _logger.debug("Adding content for message " +messageId);
}
PreparedStatement stmt = null;
@@ -2024,20 +1838,15 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
stmt = conn.prepareStatement(INSERT_INTO_MESSAGE_CONTENT);
stmt.setLong(1,messageId);
- stmt.setInt(2, offset);
- stmt.setInt(3, offset+chunkData.length);
-
-
- // TODO in Java 6 we could just use blobs
ByteArrayInputStream bis = new ByteArrayInputStream(chunkData);
- stmt.setBinaryStream(4, bis, chunkData.length);
+ stmt.setBinaryStream(2, bis, chunkData.length);
stmt.executeUpdate();
}
catch (SQLException e)
{
closeConnection(conn);
- throw new RuntimeException("Error adding content chunk offset " + offset + " for message " + messageId + ": " + e.getMessage(), e);
+ throw new RuntimeException("Error adding content for message " + messageId + ": " + e.getMessage(), e);
}
finally
{
@@ -2058,33 +1867,32 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
stmt = conn.prepareStatement(SELECT_FROM_MESSAGE_CONTENT);
stmt.setLong(1,messageId);
- stmt.setInt(2, offset);
- stmt.setInt(3, offset+dst.remaining());
ResultSet rs = stmt.executeQuery();
int written = 0;
- while(rs.next())
+ if (rs.next())
{
- int offsetInMessage = rs.getInt(1);
- Blob dataAsBlob = rs.getBlob(2);
+
+ Blob dataAsBlob = rs.getBlob(1);
final int size = (int) dataAsBlob.length();
byte[] dataAsBytes = dataAsBlob.getBytes(1, size);
- int posInArray = offset + written - offsetInMessage;
- int count = size - posInArray;
- if(count > dst.remaining())
+ if (offset > size)
{
- count = dst.remaining();
+ throw new RuntimeException("Offset " + offset + " is greater than message size " + size
+ + " for message id " + messageId + "!");
+
}
- dst.put(dataAsBytes,posInArray,count);
- written+=count;
- if(dst.remaining() == 0)
+ written = size - offset;
+ if(written > dst.remaining())
{
- break;
+ written = dst.remaining();
}
+
+ dst.put(dataAsBytes, offset, written);
}
return written;
@@ -2103,24 +1911,13 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
+ @Override
public boolean isPersistent()
{
return true;
}
- private synchronized void stateTransition(State requiredState, State newState) throws AMQStoreException
- {
- if (_state != requiredState)
- {
- throw new AMQStoreException("Cannot transition to the state: " + newState + "; need to be in state: " + requiredState
- + "; currently in state: " + _state);
- }
-
- _state = newState;
- }
-
-
private class DerbyTransaction implements Transaction
{
private final ConnectionWrapper _connWrapper;
@@ -2138,6 +1935,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
+ @Override
public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
{
if(message.getStoredMessage() instanceof StoredDerbyMessage)
@@ -2155,28 +1953,47 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
DerbyMessageStore.this.enqueueMessage(_connWrapper, queue, message.getMessageNumber());
}
+ @Override
public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
{
DerbyMessageStore.this.dequeueMessage(_connWrapper, queue, message.getMessageNumber());
}
+ @Override
public void commitTran() throws AMQStoreException
{
DerbyMessageStore.this.commitTran(_connWrapper);
}
+ @Override
public StoreFuture commitTranAsync() throws AMQStoreException
{
return DerbyMessageStore.this.commitTranAsync(_connWrapper);
}
+ @Override
public void abortTran() throws AMQStoreException
{
DerbyMessageStore.this.abortTran(_connWrapper);
}
+
+ @Override
+ public void removeXid(long format, byte[] globalId, byte[] branchId) throws AMQStoreException
+ {
+ DerbyMessageStore.this.removeXid(_connWrapper, format, globalId, branchId);
+ }
+
+ @Override
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ throws AMQStoreException
+ {
+ DerbyMessageStore.this.recordXid(_connWrapper, format, globalId, branchId, enqueues, dequeues);
+ }
}
+
+
private class StoredDerbyMessage implements StoredMessage
{
@@ -2185,7 +2002,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
private volatile SoftReference<StorableMessageMetaData> _metaDataRef;
private byte[] _data;
private volatile SoftReference<byte[]> _dataRef;
-
+
StoredDerbyMessage(long messageId, StorableMessageMetaData metaData)
{
@@ -2197,15 +2014,16 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
StorableMessageMetaData metaData, boolean persist)
{
_messageId = messageId;
-
+
_metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
if(persist)
{
- _metaData = metaData;
+ _metaData = metaData;
}
}
+ @Override
public StorableMessageMetaData getMetaData()
{
StorableMessageMetaData metaData = _metaData == null ? _metaDataRef.get() : _metaData;
@@ -2225,11 +2043,13 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
return metaData;
}
+ @Override
public long getMessageNumber()
{
return _messageId;
}
+ @Override
public void addContent(int offsetInMessage, java.nio.ByteBuffer src)
{
src = src.slice();
@@ -2249,9 +2069,10 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
System.arraycopy(oldData,0,_data,0,oldData.length);
src.duplicate().get(_data, oldData.length, src.remaining());
}
-
+
}
+ @Override
public int getContent(int offsetInMessage, java.nio.ByteBuffer dst)
{
byte[] data = _dataRef == null ? null : _dataRef.get();
@@ -2268,6 +2089,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
+ @Override
public ByteBuffer getContent(int offsetInMessage, int size)
{
ByteBuffer buf = ByteBuffer.allocate(size);
@@ -2276,6 +2098,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
return buf;
}
+ @Override
public synchronized StoreFuture flushToStore()
{
try
@@ -2285,7 +2108,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
Connection conn = newConnection();
store(conn);
-
+
conn.commit();
conn.close();
}
@@ -2298,7 +2121,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
throw new RuntimeException(e);
}
- return IMMEDIATE_FUTURE;
+ return StoreFuture.IMMEDIATE_FUTURE;
}
private synchronized void store(final Connection conn) throws SQLException
@@ -2308,7 +2131,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
try
{
storeMetaData(conn, _messageId, _metaData);
- DerbyMessageStore.this.addContent(conn, _messageId, 0,
+ DerbyMessageStore.this.addContent(conn, _messageId,
_data == null ? ByteBuffer.allocate(0) : ByteBuffer.wrap(_data));
}
finally
@@ -2324,6 +2147,7 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
+ @Override
public void remove()
{
DerbyMessageStore.this.removeMessage(_messageId);
@@ -2360,4 +2184,266 @@ public class DerbyMessageStore implements MessageStore, DurableConfigurationStor
}
}
-}
+ @Override
+ public void addEventListener(EventListener eventListener, Event... events)
+ {
+ _eventManager.addEventListener(eventListener, events);
+ }
+
+ @Override
+ public String getStoreLocation()
+ {
+ return _storeLocation;
+ }
+
+ private void insertConfiguredObject(ConfiguredObjectRecord configuredObject) throws AMQStoreException
+ {
+ if (_stateManager.isInState(State.ACTIVE))
+ {
+ try
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
+ try
+ {
+ stmt.setString(1, configuredObject.getId().toString());
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ // If we don't have any data in the result set then we can add this configured object
+ if (!rs.next())
+ {
+ PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_CONFIGURED_OBJECTS);
+ try
+ {
+ insertStmt.setString(1, configuredObject.getId().toString());
+ insertStmt.setString(2, configuredObject.getType());
+ if(configuredObject.getAttributes() == null)
+ {
+ insertStmt.setNull(3, Types.BLOB);
+ }
+ else
+ {
+ byte[] attributesAsBytes = configuredObject.getAttributes().getBytes(UTF8_CHARSET);
+ ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes);
+ insertStmt.setBinaryStream(3, bis, attributesAsBytes.length);
+ }
+ insertStmt.execute();
+ }
+ finally
+ {
+ insertStmt.close();
+ }
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error inserting of configured object " + configuredObject + " into database: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ private int removeConfiguredObject(UUID id) throws AMQStoreException
+ {
+ int results = 0;
+ try
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_CONFIGURED_OBJECTS);
+ try
+ {
+ stmt.setString(1, id.toString());
+ results = stmt.executeUpdate();
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error deleting of configured object with id " + id + " from database: " + e.getMessage(), e);
+ }
+ return results;
+ }
+
+ private void updateConfiguredObject(final ConfiguredObjectRecord configuredObject) throws AMQStoreException
+ {
+ if (_stateManager.isInState(State.ACTIVE))
+ {
+ try
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
+ try
+ {
+ stmt.setString(1, configuredObject.getId().toString());
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ if (rs.next())
+ {
+ PreparedStatement stmt2 = conn.prepareStatement(UPDATE_CONFIGURED_OBJECTS);
+ try
+ {
+ stmt2.setString(1, configuredObject.getType());
+ if (configuredObject.getAttributes() != null)
+ {
+ byte[] attributesAsBytes = configuredObject.getAttributes().getBytes(UTF8_CHARSET);
+ ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes);
+ stmt2.setBinaryStream(2, bis, attributesAsBytes.length);
+ }
+ else
+ {
+ stmt2.setNull(2, Types.BLOB);
+ }
+ stmt2.setString(3, configuredObject.getId().toString());
+ stmt2.execute();
+ }
+ finally
+ {
+ stmt2.close();
+ }
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error updating configured object " + configuredObject + " in database: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ private ConfiguredObjectRecord loadConfiguredObject(final UUID id) throws AMQStoreException
+ {
+ ConfiguredObjectRecord result = null;
+ try
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
+ try
+ {
+ stmt.setString(1, id.toString());
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ if (rs.next())
+ {
+ String type = rs.getString(1);
+ Blob blob = rs.getBlob(2);
+ String attributes = null;
+ if (blob != null)
+ {
+ attributes = blobToString(blob);
+ }
+ result = new ConfiguredObjectRecord(id, type, attributes);
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error loading of configured object with id " + id + " from database: "
+ + e.getMessage(), e);
+ }
+ return result;
+ }
+
+ private String blobToString(Blob blob) throws SQLException
+ {
+ byte[] bytes = blob.getBytes(1, (int)blob.length());
+ return new String(bytes, UTF8_CHARSET);
+ }
+
+ private List<ConfiguredObjectRecord> loadConfiguredObjects() throws SQLException
+ {
+ ArrayList<ConfiguredObjectRecord> results = new ArrayList<ConfiguredObjectRecord>();
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_CONFIGURED_OBJECTS);
+ try
+ {
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ while (rs.next())
+ {
+ String id = rs.getString(1);
+ String objectType = rs.getString(2);
+ String attributes = blobToString(rs.getBlob(3));
+ results.add(new ConfiguredObjectRecord(UUID.fromString(id), objectType, attributes));
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ return results;
+ }
+} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java
new file mode 100644
index 0000000000..12d7f64a8d
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store.derby;
+
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreFactory;
+
+public class DerbyMessageStoreFactory implements MessageStoreFactory
+{
+
+ @Override
+ public MessageStore createMessageStore()
+ {
+ return new DerbyMessageStore();
+ }
+
+ @Override
+ public String getStoreClassName()
+ {
+ return DerbyMessageStore.class.getSimpleName();
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
index f8a585b562..66825caa24 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
@@ -54,16 +54,12 @@ public interface Subscription
void setNoLocal(boolean noLocal);
- AMQShortString getConsumerTag();
-
long getSubscriptionID();
boolean isSuspended();
boolean hasInterest(QueueEntry msg);
- boolean isAutoClose();
-
boolean isClosed();
boolean acquires();
@@ -105,11 +101,11 @@ public interface Subscription
boolean isActive();
- void confirmAutoClose();
-
public void set(String key, Object value);
public Object get(String key);
boolean isSessionTransactional();
+
+ void queueEmpty() throws AMQException;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
index 32baa17fc7..1f25c215cc 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
@@ -375,7 +375,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
{
return getQueue().getConfigStore();
}
-
+
public Long getDelivered()
{
return _deliveredCount.get();
@@ -810,12 +810,22 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
{
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);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
index 9a7d69b10d..76d975a789 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
@@ -109,7 +109,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
public void stateChange(Subscription sub, State oldState, State newState)
{
- CurrentActor.get().message(SubscriptionMessages.STATE(newState.toString()));
+ CurrentActor.get().message(SubscriptionMessages.STATE(newState.toString()));
}
};
private AMQQueue _queue;
@@ -199,12 +199,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
CurrentActor.get().message(this, SubscriptionMessages.CREATE(filterLogString, queue.isDurable() && exclusive,
filterLogString.length() > 0));
}
-
- }
- public AMQShortString getConsumerTag()
- {
- return new AMQShortString(_destination);
}
public boolean isSuspended()
@@ -244,12 +239,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
return (_filters == null) || _filters.allAllow(entry);
}
- public boolean isAutoClose()
- {
- // no such thing in 0-10
- return false;
- }
-
public boolean isClosed()
{
return getState() == State.CLOSED;
@@ -302,7 +291,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
{
return getQueue().getConfigStore();
}
-
+
public Long getDelivered()
{
return _deliveredCount.get();
@@ -409,6 +398,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
{
deliveryProps.setTimestamp(origDeliveryProps.getTimestamp());
}
+ if(origDeliveryProps.hasTtl())
+ {
+ deliveryProps.setTtl(origDeliveryProps.getTtl());
+ }
}
@@ -684,7 +677,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
{
entry.setRedelivered();
entry.routeToAlternate();
-
+ if(entry.isAcquiredBy(this))
+ {
+ entry.discard();
+ }
}
void release(final QueueEntry entry, final boolean setRedelivered)
@@ -816,11 +812,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
return getState() == State.ACTIVE;
}
- public void confirmAutoClose()
- {
- //No such thing in 0-10
- }
-
public void set(String key, Object value)
{
_properties.put(key, value);
@@ -1019,6 +1010,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
return _session.isTransactional();
}
+ public void queueEmpty()
+ {
+ }
+
public long getCreateTime()
{
return _createTime;
@@ -1026,7 +1021,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
public String toLogString()
{
- String queueInfo = MessageFormat.format(QUEUE_FORMAT, _queue.getVirtualHost().getName(),
+ String queueInfo = MessageFormat.format(QUEUE_FORMAT, _queue.getVirtualHost().getName(),
_queue.getNameShortString());
String result = "[" + MessageFormat.format(SUBSCRIPTION_FORMAT, getSubscriptionID()) + "("
// queueString is "vh(/{0})/qu({1}) " so need to trim
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
index 02c4ffa012..5460c89eab 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
@@ -33,6 +33,7 @@ import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.auth.AuthenticationResult;
import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
import org.apache.qpid.server.subscription.Subscription_0_10;
+import org.apache.qpid.server.virtualhost.State;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.*;
import org.slf4j.Logger;
@@ -177,6 +178,11 @@ public class ServerConnectionDelegate extends ServerDelegate
sconn.setState(Connection.State.CLOSING);
sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, "Permission denied '"+vhostName+"'"));
}
+ else if (vhost.getState() != State.ACTIVE)
+ {
+ sconn.setState(Connection.State.CLOSING);
+ sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, "Virtual host '"+vhostName+"' is not active"));
+ }
else
{
sconn.setState(Connection.State.OPEN);
@@ -231,23 +237,26 @@ public class ServerConnectionDelegate extends ServerDelegate
@Override public void sessionDetach(Connection conn, SessionDetach dtc)
{
- // To ensure a clean detach, we unregister any remaining subscriptions. Unregister ensures
- // that any in-progress delivery (SubFlushRunner/QueueRunner) is completed before the unregister
+ // To ensure a clean detach, we stop any remaining subscriptions. Stop ensures
+ // that any in-progress delivery (SubFlushRunner/QueueRunner) is completed before the stop
// completes.
- unregisterAllSubscriptions(conn, dtc);
+ stopAllSubscriptions(conn, dtc);
+ Session ssn = conn.getSession(dtc.getChannel());
+ ((ServerSession)ssn).setClose(true);
super.sessionDetach(conn, dtc);
}
- private void unregisterAllSubscriptions(Connection conn, SessionDetach dtc)
+ private void stopAllSubscriptions(Connection conn, SessionDetach dtc)
{
final ServerSession ssn = (ServerSession) conn.getSession(dtc.getChannel());
final Collection<Subscription_0_10> subs = ssn.getSubscriptions();
for (Subscription_0_10 subscription_0_10 : subs)
{
- ssn.unregister(subscription_0_10);
+ subscription_0_10.stop();
}
}
+
@Override
public void sessionAttach(final Connection conn, final SessionAttach atc)
{
@@ -255,8 +264,7 @@ public class ServerConnectionDelegate extends ServerDelegate
if(isSessionNameUnique(atc.getName(), conn))
{
- ssn = sessionAttachImpl(conn, atc);
- conn.registerSession(ssn);
+ super.sessionAttach(conn, atc);
((ServerConnection)conn).checkForNotification();
}
else
@@ -306,4 +314,4 @@ public class ServerConnectionDelegate extends ServerDelegate
{
return _clientProperties == null ? null : (String) _clientProperties.get(ConnectionStartProperties.VERSION_0_10);
}
-} \ No newline at end of file
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
index e4268ed2dc..6f979e035e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
@@ -21,6 +21,11 @@
package org.apache.qpid.server.transport;
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT;
+import org.apache.qpid.server.message.InboundMessage;
+import org.apache.qpid.server.message.MessageMetaData_0_10;
+import org.apache.qpid.server.message.MessageTransferMessage;
+import org.apache.qpid.server.txn.RollbackOnlyDtxException;
+import org.apache.qpid.server.txn.TimeoutDtxException;
import static org.apache.qpid.util.Serial.gt;
import java.security.Principal;
@@ -44,6 +49,7 @@ import java.util.concurrent.atomic.AtomicLong;
import javax.security.auth.Subject;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.server.configuration.ConfigStore;
@@ -66,25 +72,21 @@ 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.subscription.Subscription_0_10;
+import org.apache.qpid.server.txn.AlreadyKnownDtxException;
import org.apache.qpid.server.txn.AsyncAutoCommitTransaction;
+import org.apache.qpid.server.txn.DistributedTransaction;
+import org.apache.qpid.server.txn.DtxNotSelectedException;
+import org.apache.qpid.server.txn.IncorrectDtxStateException;
+import org.apache.qpid.server.txn.JoinAndResumeDtxException;
import org.apache.qpid.server.txn.LocalTransaction;
+import org.apache.qpid.server.txn.NotAssociatedDtxException;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.SuspendAndFailDtxException;
+import org.apache.qpid.server.txn.UnknownDtxBranchException;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.transport.Binary;
-import org.apache.qpid.transport.Connection;
-import org.apache.qpid.transport.MessageCreditUnit;
-import org.apache.qpid.transport.MessageFlow;
-import org.apache.qpid.transport.MessageFlowMode;
-import org.apache.qpid.transport.MessageSetFlowMode;
-import org.apache.qpid.transport.MessageStop;
-import org.apache.qpid.transport.MessageTransfer;
-import org.apache.qpid.transport.Method;
-import org.apache.qpid.transport.Range;
-import org.apache.qpid.transport.RangeSet;
-import org.apache.qpid.transport.RangeSetFactory;
-import org.apache.qpid.transport.Session;
-import org.apache.qpid.transport.SessionDelegate;
+import org.apache.qpid.transport.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -109,7 +111,6 @@ public class ServerSession extends Session
private ChannelLogSubject _logSubject;
private final AtomicInteger _outstandingCredit = new AtomicInteger(UNLIMITED_CREDIT);
-
public static interface MessageDispositionChangeListener
{
public void onAccept();
@@ -133,7 +134,7 @@ public class ServerSession extends Session
new ConcurrentSkipListMap<Integer, MessageDispositionChangeListener>();
private ServerTransaction _transaction;
-
+
private final AtomicLong _txnStarts = new AtomicLong(0);
private final AtomicLong _txnCommits = new AtomicLong(0);
private final AtomicLong _txnRejects = new AtomicLong(0);
@@ -152,7 +153,7 @@ public class ServerSession extends Session
public ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry, ConnectionConfig connConfig)
{
super(connection, delegate, name, expiry);
- _connectionConfig = connConfig;
+ _connectionConfig = connConfig;
_transaction = new AsyncAutoCommitTransaction(this.getMessageStore(),this);
_logSubject = new ChannelLogSubject(this);
_id = getConfigStore().createId();
@@ -352,14 +353,22 @@ public class ServerSession extends Session
}
}
- public void removeDispositionListener(Method method)
+ public void removeDispositionListener(Method method)
{
_messageDispositionListenerMap.remove(method.getId());
}
public void onClose()
{
- _transaction.rollback();
+ if(_transaction instanceof LocalTransaction)
+ {
+ _transaction.rollback();
+ }
+ else if(_transaction instanceof DistributedTransaction)
+ {
+ getVirtualHost().getDtxRegistry().endAssociations(this);
+ }
+
for(MessageDispositionChangeListener listener : _messageDispositionListenerMap.values())
{
listener.onRelease(true);
@@ -372,7 +381,7 @@ public class ServerSession extends Session
{
task.doTask(this);
}
-
+
CurrentActor.get().message(getLogSubject(), ChannelMessages.CLOSE());
}
@@ -395,6 +404,9 @@ public class ServerSession extends Session
public void onRollback()
{
+ // The client has acknowledge the message and therefore have seen it.
+ // In the event of rollback, the message must be marked as redelivered.
+ entry.setRedelivered();
entry.release();
}
});
@@ -418,7 +430,7 @@ public class ServerSession extends Session
public void unregister(Subscription_0_10 sub)
{
- _subscriptions.remove(sub.getConsumerTag().toString());
+ _subscriptions.remove(sub.getName());
try
{
sub.getSendLock();
@@ -455,10 +467,99 @@ public class ServerSession extends Session
_txnStarts.incrementAndGet();
}
+ public void selectDtx()
+ {
+ _transaction = new DistributedTransaction(this, getMessageStore(), getVirtualHost());
+
+ }
+
+
+ public void startDtx(Xid xid, boolean join, boolean resume)
+ throws JoinAndResumeDtxException,
+ UnknownDtxBranchException,
+ AlreadyKnownDtxException,
+ DtxNotSelectedException
+ {
+ DistributedTransaction distributedTransaction = assertDtxTransaction();
+ distributedTransaction.start(xid, join, resume);
+ }
+
+
+ public void endDtx(Xid xid, boolean fail, boolean suspend)
+ throws NotAssociatedDtxException,
+ UnknownDtxBranchException,
+ DtxNotSelectedException,
+ SuspendAndFailDtxException, TimeoutDtxException
+ {
+ DistributedTransaction distributedTransaction = assertDtxTransaction();
+ distributedTransaction.end(xid, fail, suspend);
+ }
+
+
+ public long getTimeoutDtx(Xid xid)
+ throws UnknownDtxBranchException
+ {
+ return getVirtualHost().getDtxRegistry().getTimeout(xid);
+ }
+
+
+ public void setTimeoutDtx(Xid xid, long timeout)
+ throws UnknownDtxBranchException
+ {
+ getVirtualHost().getDtxRegistry().setTimeout(xid, timeout);
+ }
+
+
+ public void prepareDtx(Xid xid)
+ throws UnknownDtxBranchException,
+ IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException
+ {
+ getVirtualHost().getDtxRegistry().prepare(xid);
+ }
+
+ public void commitDtx(Xid xid, boolean onePhase)
+ throws UnknownDtxBranchException,
+ IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException
+ {
+ getVirtualHost().getDtxRegistry().commit(xid, onePhase);
+ }
+
+
+ public void rollbackDtx(Xid xid)
+ throws UnknownDtxBranchException,
+ IncorrectDtxStateException, AMQStoreException, TimeoutDtxException
+ {
+ getVirtualHost().getDtxRegistry().rollback(xid);
+ }
+
+
+ public void forgetDtx(Xid xid) throws UnknownDtxBranchException, IncorrectDtxStateException
+ {
+ getVirtualHost().getDtxRegistry().forget(xid);
+ }
+
+ public List<Xid> recoverDtx()
+ {
+ return getVirtualHost().getDtxRegistry().recover();
+ }
+
+ private DistributedTransaction assertDtxTransaction() throws DtxNotSelectedException
+ {
+ if(_transaction instanceof DistributedTransaction)
+ {
+ return (DistributedTransaction) _transaction;
+ }
+ else
+ {
+ throw new DtxNotSelectedException();
+ }
+ }
+
+
public void commit()
{
_transaction.commit();
-
+
_txnCommits.incrementAndGet();
_txnStarts.incrementAndGet();
decrementOutstandingTxnsIfNecessary();
@@ -467,13 +568,13 @@ public class ServerSession extends Session
public void rollback()
{
_transaction.rollback();
-
+
_txnRejects.incrementAndGet();
_txnStarts.incrementAndGet();
decrementOutstandingTxnsIfNecessary();
}
-
+
private void incrementOutstandingTxnsIfNecessary()
{
if(isTransactional())
@@ -483,7 +584,7 @@ public class ServerSession extends Session
_txnCount.compareAndSet(0,1);
}
}
-
+
private void decrementOutstandingTxnsIfNecessary()
{
if(isTransactional())
@@ -524,7 +625,7 @@ public class ServerSession extends Session
{
return _txnCount.get();
}
-
+
public Principal getAuthorizedPrincipal()
{
return getConnection().getAuthorizedPrincipal();
@@ -620,11 +721,6 @@ public class ServerSession extends Session
close();
}
- public Object getID()
- {
- return getName();
- }
-
public AMQConnectionModel getConnectionModel()
{
return getConnection();
@@ -704,7 +800,7 @@ public class ServerSession extends Session
{
if(_blockingQueues.remove(queue) && _blockingQueues.isEmpty())
{
- if(_blocking.compareAndSet(true,false))
+ if(_blocking.compareAndSet(true,false) && !isClosing())
{
_actor.message(_logSubject, ChannelMessages.FLOW_REMOVED());
@@ -720,6 +816,14 @@ public class ServerSession extends Session
}
}
+ public boolean onSameConnection(InboundMessage inbound)
+ {
+ return ((inbound instanceof MessageTransferMessage)
+ && ((MessageTransferMessage)inbound).getConnectionReference() == getConnection().getReference())
+ || ((inbound instanceof MessageMetaData_0_10)
+ && (((MessageMetaData_0_10)inbound).getConnectionReference())== getConnection().getReference());
+ }
+
public String toLogString()
{
@@ -746,7 +850,6 @@ public class ServerSession extends Session
// unregister subscriptions in order to prevent sending of new messages
// to subscriptions with closing session
unregisterSubscriptions();
-
super.close();
}
@@ -759,6 +862,16 @@ public class ServerSession extends Session
}
}
+ void stopSubscriptions()
+ {
+ final Collection<Subscription_0_10> subscriptions = getSubscriptions();
+ for (Subscription_0_10 subscription_0_10 : subscriptions)
+ {
+ subscription_0_10.stop();
+ }
+ }
+
+
public void receivedComplete()
{
final Collection<Subscription_0_10> subscriptions = getSubscriptions();
@@ -863,17 +976,17 @@ public class ServerSession extends Session
return _unfinishedCommandsQueue.isEmpty() ? null : _unfinishedCommandsQueue.getLast();
}
- public void recordFuture(final MessageStore.StoreFuture future, final ServerTransaction.Action action)
+ public void recordFuture(final StoreFuture future, final ServerTransaction.Action action)
{
_unfinishedCommandsQueue.add(new AsyncCommand(future, action));
}
private static class AsyncCommand
{
- private final MessageStore.StoreFuture _future;
+ private final StoreFuture _future;
private ServerTransaction.Action _action;
- public AsyncCommand(final MessageStore.StoreFuture future, final ServerTransaction.Action action)
+ public AsyncCommand(final StoreFuture future, final ServerTransaction.Action action)
{
_future = future;
_action = action;
@@ -900,9 +1013,14 @@ public class ServerSession extends Session
}
}
- @Override
+ protected void setClose(boolean close)
+ {
+ super.setClose(close);
+ }
+
public int compareTo(AMQSessionModel session)
{
- return getId().toString().compareTo(session.getID().toString());
+ return getId().compareTo(session.getId());
}
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
index 8e4fb3635b..79a8bc0e4c 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.transport;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
import org.apache.qpid.AMQUnknownExchangeType;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
@@ -39,6 +40,7 @@ import org.apache.qpid.server.flow.WindowCreditManager;
import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.message.MessageMetaData_0_10;
import org.apache.qpid.server.message.MessageTransferMessage;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.BaseQueue;
@@ -47,10 +49,20 @@ import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
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.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.subscription.Subscription_0_10;
+import org.apache.qpid.server.txn.AlreadyKnownDtxException;
+import org.apache.qpid.server.txn.DtxNotSelectedException;
+import org.apache.qpid.server.txn.IncorrectDtxStateException;
+import org.apache.qpid.server.txn.JoinAndResumeDtxException;
+import org.apache.qpid.server.txn.NotAssociatedDtxException;
+import org.apache.qpid.server.txn.RollbackOnlyDtxException;
import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.SuspendAndFailDtxException;
+import org.apache.qpid.server.txn.TimeoutDtxException;
+import org.apache.qpid.server.txn.UnknownDtxBranchException;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.*;
@@ -116,7 +128,7 @@ public class ServerSessionDelegate extends SessionDelegate
serverSession.accept(method.getTransfers());
if(!serverSession.isTransactional())
{
- serverSession.recordFuture(MessageStore.IMMEDIATE_FUTURE,
+ serverSession.recordFuture(StoreFuture.IMMEDIATE_FUTURE,
new CommandProcessedAction(serverSession, method));
}
}
@@ -199,6 +211,10 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
}
+ else if(queue.isExclusive() && queue.getExclusiveOwningSession() != null && queue.getExclusiveOwningSession() != session)
+ {
+ exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
+ }
else
{
if(queue.isExclusive())
@@ -221,7 +237,6 @@ public class ServerSessionDelegate extends SessionDelegate
}
});
}
-
}
FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L);
@@ -281,6 +296,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
final MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr);
+ messageMetaData.setConnectionReference(((ServerSession)ssn).getReference());
if (!getVirtualHost(ssn).getSecurityManager().authorisePublish(messageMetaData.isImmediate(), messageMetaData.getRoutingKey(), exchange.getName()))
{
@@ -342,7 +358,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
else
{
- serverSession.recordFuture(MessageStore.IMMEDIATE_FUTURE, new CommandProcessedAction(serverSession, xfr));
+ serverSession.recordFuture(StoreFuture.IMMEDIATE_FUTURE, new CommandProcessedAction(serverSession, xfr));
}
}
@@ -426,6 +442,235 @@ public class ServerSessionDelegate extends SessionDelegate
((ServerSession)session).rollback();
}
+ @Override
+ public void dtxSelect(Session session, DtxSelect method)
+ {
+ // TODO - check current tx mode
+ ((ServerSession)session).selectDtx();
+ }
+
+ @Override
+ public void dtxStart(Session session, DtxStart method)
+ {
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ ((ServerSession)session).startDtx(method.getXid(), method.getJoin(), method.getResume());
+ session.executionResult(method.getId(), result);
+ }
+ catch(JoinAndResumeDtxException e)
+ {
+ exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage());
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Unknown xid " + method.getXid());
+ }
+ catch(AlreadyKnownDtxException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Xid already started an neither join nor " +
+ "resume set" + method.getXid());
+ }
+ catch(DtxNotSelectedException e)
+ {
+ exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage());
+ }
+
+ }
+
+ @Override
+ public void dtxEnd(Session session, DtxEnd method)
+ {
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ try
+ {
+ ((ServerSession)session).endDtx(method.getXid(), method.getFail(), method.getSuspend());
+ }
+ catch (TimeoutDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBTIMEOUT);
+ }
+ session.executionResult(method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(NotAssociatedDtxException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(DtxNotSelectedException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(SuspendAndFailDtxException e)
+ {
+ exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage());
+ }
+
+ }
+
+ @Override
+ public void dtxCommit(Session session, DtxCommit method)
+ {
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ try
+ {
+ ((ServerSession)session).commitDtx(method.getXid(), method.getOnePhase());
+ }
+ catch (RollbackOnlyDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBROLLBACK);
+ }
+ catch (TimeoutDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBTIMEOUT);
+ }
+ session.executionResult(method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ catch(IncorrectDtxStateException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(AMQStoreException e)
+ {
+ exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage());
+ }
+ }
+
+ @Override
+ public void dtxForget(Session session, DtxForget method)
+ {
+ try
+ {
+ ((ServerSession)session).forgetDtx(method.getXid());
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ catch(IncorrectDtxStateException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+
+ }
+
+ @Override
+ public void dtxGetTimeout(Session session, DtxGetTimeout method)
+ {
+ GetTimeoutResult result = new GetTimeoutResult();
+ try
+ {
+ result.setTimeout(((ServerSession) session).getTimeoutDtx(method.getXid()));
+ session.executionResult(method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ }
+
+ @Override
+ public void dtxPrepare(Session session, DtxPrepare method)
+ {
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ try
+ {
+ ((ServerSession)session).prepareDtx(method.getXid());
+ }
+ catch (RollbackOnlyDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBROLLBACK);
+ }
+ catch (TimeoutDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBTIMEOUT);
+ }
+ session.executionResult((int) method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ catch(IncorrectDtxStateException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(AMQStoreException e)
+ {
+ exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage());
+ }
+ }
+
+ @Override
+ public void dtxRecover(Session session, DtxRecover method)
+ {
+ RecoverResult result = new RecoverResult();
+ List inDoubt = ((ServerSession)session).recoverDtx();
+ result.setInDoubt(inDoubt);
+ session.executionResult(method.getId(), result);
+ }
+
+ @Override
+ public void dtxRollback(Session session, DtxRollback method)
+ {
+
+ XaResult result = new XaResult();
+ result.setStatus(DtxXaStatus.XA_OK);
+ try
+ {
+ try
+ {
+ ((ServerSession)session).rollbackDtx(method.getXid());
+ }
+ catch (TimeoutDtxException e)
+ {
+ result.setStatus(DtxXaStatus.XA_RBTIMEOUT);
+ }
+ session.executionResult(method.getId(), result);
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ catch(IncorrectDtxStateException e)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage());
+ }
+ catch(AMQStoreException e)
+ {
+ exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage());
+ }
+ }
+
+ @Override
+ public void dtxSetTimeout(Session session, DtxSetTimeout method)
+ {
+ try
+ {
+ ((ServerSession)session).setTimeoutDtx(method.getXid(), method.getTimeout());
+ }
+ catch(UnknownDtxBranchException e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage());
+ }
+ }
@Override
public void executionSync(final Session ssn, final ExecutionSync sync)
@@ -439,13 +684,12 @@ public class ServerSessionDelegate extends SessionDelegate
{
String exchangeName = method.getExchange();
VirtualHost virtualHost = getVirtualHost(session);
- Exchange exchange = getExchange(session, exchangeName);
+ ExchangeRegistry exchangeRegistry = getExchangeRegistry(session);
//we must check for any unsupported arguments present and throw not-implemented
if(method.hasArguments())
{
Map<String,Object> args = method.getArguments();
-
//QPID-3392: currently we don't support any!
if(!args.isEmpty())
{
@@ -453,72 +697,113 @@ public class ServerSessionDelegate extends SessionDelegate
return;
}
}
-
- if(method.getPassive())
+ synchronized(exchangeRegistry)
{
- if(exchange == null)
- {
- exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: exchange-name '"+exchangeName+"'");
+ Exchange exchange = getExchange(session, exchangeName);
- }
- else
+ if(method.getPassive())
{
- if(!exchange.getTypeShortString().toString().equals(method.getType()) && (method.getType() != null && method.getType().length() > 0))
+ if(exchange == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: exchange-name '" + exchangeName + "'");
+ }
+ else
{
- exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to redeclare exchange: " + exchangeName + " of type " + exchange.getTypeShortString() + " to " + method.getType() +".");
+ if (!exchange.getTypeShortString().toString().equals(method.getType())
+ && (method.getType() != null && method.getType().length() > 0))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to redeclare exchange: "
+ + exchangeName + " of type " + exchange.getTypeShortString() + " to " + method.getType() + ".");
+ }
}
}
-
- }
- else
- {
- if (exchange == null)
+ else
{
- ExchangeRegistry exchangeRegistry = getExchangeRegistry(session);
- ExchangeFactory exchangeFactory = virtualHost.getExchangeFactory();
-
-
-
- try
+ if (exchange == null)
{
-
- exchange = exchangeFactory.createExchange(method.getExchange(),
- method.getType(),
- method.getDurable(),
- method.getAutoDelete());
-
- String alternateExchangeName = method.getAlternateExchange();
- if(alternateExchangeName != null && alternateExchangeName.length() != 0)
+ if (exchangeName.startsWith("amq."))
{
- Exchange alternate = getExchange(session, alternateExchangeName);
- exchange.setAlternateExchange(alternate);
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to declare exchange: "
+ + exchangeName + " which begins with reserved prefix 'amq.'.");
}
-
- if (exchange.isDurable())
+ else if (exchangeName.startsWith("qpid."))
{
- DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
- store.createExchange(exchange);
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to declare exchange: "
+ + exchangeName + " which begins with reserved prefix 'qpid.'.");
+ }
+ else
+ {
+ ExchangeFactory exchangeFactory = virtualHost.getExchangeFactory();
+ try
+ {
+ exchange = exchangeFactory.createExchange(method.getExchange(),
+ method.getType(),
+ method.getDurable(),
+ method.getAutoDelete());
+ String alternateExchangeName = method.getAlternateExchange();
+ boolean validAlternate;
+ if(alternateExchangeName != null && alternateExchangeName.length() != 0)
+ {
+ Exchange alternate = getExchange(session, alternateExchangeName);
+ if(alternate == null)
+ {
+ validAlternate = false;
+ }
+ else
+ {
+ exchange.setAlternateExchange(alternate);
+ validAlternate = true;
+ }
+ }
+ else
+ {
+ validAlternate = true;
+ }
+ if(validAlternate)
+ {
+ if (exchange.isDurable())
+ {
+ DurableConfigurationStore store = virtualHost.getMessageStore();
+ store.createExchange(exchange);
+ }
+ exchangeRegistry.registerExchange(exchange);
+ }
+ else
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND,
+ "Unknown alternate exchange " + alternateExchangeName);
+ }
+ }
+ catch(AMQUnknownExchangeType e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "Unknown Exchange Type: " + method.getType());
+ }
+ catch (AMQException e)
+ {
+ exception(session, method, e, "Cannot declare exchange '" + exchangeName);
+ }
}
-
- exchangeRegistry.registerExchange(exchange);
- }
- catch(AMQUnknownExchangeType e)
- {
- exception(session, method, ExecutionErrorCode.NOT_FOUND, "Unknown Exchange Type: " + method.getType());
- }
- catch (AMQException e)
- {
- exception(session, method, e, "Cannot declare exchange '" + exchangeName);
}
- }
- else
- {
- if(!exchange.getTypeShortString().toString().equals(method.getType()))
+ else
{
- exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to redeclare exchange: " + exchangeName + " of type " + exchange.getTypeShortString() + " to " + method.getType() +".");
+ if(!exchange.getTypeShortString().toString().equals(method.getType()))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED,
+ "Attempt to redeclare exchange: " + exchangeName
+ + " of type " + exchange.getTypeShortString()
+ + " to " + method.getType() +".");
+ }
+ else if(method.hasAlternateExchange()
+ && (exchange.getAlternateExchange() == null ||
+ !method.getAlternateExchange().equals(exchange.getAlternateExchange().getName())))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED,
+ "Attempt to change alternate exchange of: " + exchangeName
+ + " from " + exchange.getAlternateExchange()
+ + " to " + method.getAlternateExchange() +".");
+ }
}
}
-
}
}
@@ -633,7 +918,7 @@ public class ServerSessionDelegate extends SessionDelegate
if (exchange.isDurable() && !exchange.isAutoDelete())
{
- DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+ DurableConfigurationStore store = virtualHost.getMessageStore();
store.removeExchange(exchange);
}
}
@@ -732,10 +1017,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
else
{
- AMQShortString routingKey = new AMQShortString(method.getBindingKey());
- FieldTable fieldTable = FieldTable.convertToFieldTable(method.getArguments());
-
- if (!exchange.isBound(routingKey, fieldTable, queue))
+ if (!exchange.isBound(method.getBindingKey(), method.getArguments(), queue))
{
try
{
@@ -847,12 +1129,6 @@ public class ServerSessionDelegate extends SessionDelegate
if(method.hasBindingKey())
{
- if(method.hasArguments())
- {
- FieldTable args = FieldTable.convertToFieldTable(method.getArguments());
-
- result.setArgsNotMatched(!exchange.isBound(new AMQShortString(method.getBindingKey()), args, queue));
- }
if(queueMatched)
{
result.setKeyNotMatched(!exchange.isBound(method.getBindingKey(), queue));
@@ -861,23 +1137,28 @@ public class ServerSessionDelegate extends SessionDelegate
{
result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
}
+
+ if(method.hasArguments())
+ {
+ result.setArgsNotMatched(!exchange.isBound(result.getKeyNotMatched() ? null : method.getBindingKey(), method.getArguments(), queueMatched ? queue : null));
+ }
+
}
else if (method.hasArguments())
{
- // TODO
-
+ result.setArgsNotMatched(!exchange.isBound(null, method.getArguments(), queueMatched ? queue : null));
}
- result.setQueueNotMatched(!exchange.isBound(queue));
-
}
else if(exchange != null && method.hasBindingKey())
{
+ result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
+
if(method.hasArguments())
{
- // TODO
+ result.setArgsNotMatched(!exchange.isBound(result.getKeyNotMatched() ? null : method.getBindingKey(), method.getArguments(), queue));
}
- result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
+
}
@@ -886,11 +1167,15 @@ public class ServerSessionDelegate extends SessionDelegate
{
if(method.hasArguments())
{
- // TODO
+ result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments(), null));
}
result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
}
+ else if(exchange != null && method.hasArguments())
+ {
+ result.setArgsNotMatched(!exchange.isBound(null, method.getArguments(), null));
+ }
session.executionResult((int) method.getId(), result);
@@ -914,7 +1199,7 @@ public class ServerSessionDelegate extends SessionDelegate
{
VirtualHost virtualHost = getVirtualHost(session);
- DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+ DurableConfigurationStore store = virtualHost.getMessageStore();
String queueName = method.getQueue();
AMQQueue queue;
@@ -1104,8 +1389,8 @@ public class ServerSessionDelegate extends SessionDelegate
{
String owner = body.getExclusive() ? session.getClientID() : null;
- final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, body.getDurable(), owner, body.getAutoDelete(),
- body.getExclusive(), virtualHost, body.getArguments());
+ final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), queueName, body.getDurable(), owner,
+ body.getAutoDelete(), body.getExclusive(), virtualHost, body.getArguments());
return queue;
}
@@ -1134,6 +1419,10 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
}
+ else if(queue.isExclusive() && queue.getExclusiveOwningSession() != null && queue.getExclusiveOwningSession() != session)
+ {
+ exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
+ }
else if (method.getIfEmpty() && !queue.isEmpty())
{
exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Queue " + queueName + " not empty");
@@ -1153,7 +1442,7 @@ public class ServerSessionDelegate extends SessionDelegate
queue.delete();
if (queue.isDurable() && !queue.isAutoDelete())
{
- DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+ DurableConfigurationStore store = virtualHost.getMessageStore();
store.removeQueue(queue);
}
}
@@ -1280,8 +1569,9 @@ public class ServerSessionDelegate extends SessionDelegate
ServerSession serverSession = (ServerSession)session;
- serverSession.unregisterSubscriptions();
+ serverSession.stopSubscriptions();
serverSession.onClose();
+ serverSession.unregisterSubscriptions();
}
@Override
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AlreadyKnownDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AlreadyKnownDtxException.java
new file mode 100644
index 0000000000..faa4ec592f
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AlreadyKnownDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class AlreadyKnownDtxException extends DtxException
+{
+ public AlreadyKnownDtxException(Xid id)
+ {
+ super("Xid " + id + " cannot be started as it is already known");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
index a062c6732f..d446434d24 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
@@ -29,7 +29,8 @@ 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.MessageStore.StoreFuture;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.Transaction;
import java.util.Collection;
import java.util.List;
@@ -71,16 +72,16 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
*/
public void addPostTransactionAction(final Action immediateAction)
{
- addFuture(MessageStore.IMMEDIATE_FUTURE, immediateAction);
+ addFuture(StoreFuture.IMMEDIATE_FUTURE, immediateAction);
}
public void dequeue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
{
- MessageStore.Transaction txn = null;
+ Transaction txn = null;
try
{
- MessageStore.StoreFuture future;
+ StoreFuture future;
if(message.isPersistent() && queue.isDurable())
{
if (_logger.isDebugEnabled())
@@ -96,7 +97,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
else
{
- future = MessageStore.IMMEDIATE_FUTURE;
+ future = StoreFuture.IMMEDIATE_FUTURE;
}
addFuture(future, postTransactionAction);
postTransactionAction = null;
@@ -113,7 +114,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
- private void addFuture(final MessageStore.StoreFuture future, final Action action)
+ private void addFuture(final StoreFuture future, final Action action)
{
if(action != null)
{
@@ -130,7 +131,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction)
{
- MessageStore.Transaction txn = null;
+ Transaction txn = null;
try
{
for(QueueEntry entry : queueEntries)
@@ -154,7 +155,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
}
- MessageStore.StoreFuture future;
+ StoreFuture future;
if(txn != null)
{
future = txn.commitTranAsync();
@@ -162,7 +163,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
else
{
- future = MessageStore.IMMEDIATE_FUTURE;
+ future = StoreFuture.IMMEDIATE_FUTURE;
}
addFuture(future, postTransactionAction);
postTransactionAction = null;
@@ -182,10 +183,10 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
public void enqueue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
{
- MessageStore.Transaction txn = null;
+ Transaction txn = null;
try
{
- MessageStore.StoreFuture future;
+ StoreFuture future;
if(message.isPersistent() && queue.isDurable())
{
if (_logger.isDebugEnabled())
@@ -200,7 +201,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
else
{
- future = MessageStore.IMMEDIATE_FUTURE;
+ future = StoreFuture.IMMEDIATE_FUTURE;
}
addFuture(future, postTransactionAction);
postTransactionAction = null;
@@ -220,7 +221,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction, long currentTime)
{
- MessageStore.Transaction txn = null;
+ Transaction txn = null;
try
{
@@ -246,7 +247,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
}
- MessageStore.StoreFuture future;
+ StoreFuture future;
if (txn != null)
{
future = txn.commitTranAsync();
@@ -254,7 +255,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
}
else
{
- future = MessageStore.IMMEDIATE_FUTURE;
+ future = StoreFuture.IMMEDIATE_FUTURE;
}
addFuture(future, postTransactionAction);
postTransactionAction = null;
@@ -278,7 +279,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
{
if(immediatePostTransactionAction != null)
{
- addFuture(MessageStore.IMMEDIATE_FUTURE, new Action()
+ addFuture(StoreFuture.IMMEDIATE_FUTURE, new Action()
{
public void postCommit()
{
@@ -305,7 +306,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction
return false;
}
- private void rollbackIfNecessary(Action postTransactionAction, MessageStore.Transaction txn)
+ private void rollbackIfNecessary(Action postTransactionAction, Transaction txn)
{
if (txn != null)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
index 597797b5f8..e5a7df6880 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
@@ -29,6 +29,7 @@ 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 java.util.Collection;
import java.util.List;
@@ -67,7 +68,7 @@ public class AutoCommitTransaction implements ServerTransaction
public void dequeue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
{
- MessageStore.Transaction txn = null;
+ Transaction txn = null;
try
{
if(message.isPersistent() && queue.isDurable())
@@ -99,7 +100,7 @@ public class AutoCommitTransaction implements ServerTransaction
public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction)
{
- MessageStore.Transaction txn = null;
+ Transaction txn = null;
try
{
for(QueueEntry entry : queueEntries)
@@ -146,7 +147,7 @@ public class AutoCommitTransaction implements ServerTransaction
public void enqueue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
{
- MessageStore.Transaction txn = null;
+ Transaction txn = null;
try
{
if(message.isPersistent() && queue.isDurable())
@@ -179,7 +180,7 @@ public class AutoCommitTransaction implements ServerTransaction
public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction, long currentTime)
{
- MessageStore.Transaction txn = null;
+ Transaction txn = null;
try
{
@@ -247,7 +248,7 @@ public class AutoCommitTransaction implements ServerTransaction
return false;
}
- private void rollbackIfNecessary(Action postTransactionAction, MessageStore.Transaction txn)
+ private void rollbackIfNecessary(Action postTransactionAction, Transaction txn)
{
if (txn != null)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java
new file mode 100644
index 0000000000..05d0110e9b
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java
@@ -0,0 +1,247 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.queue.BaseQueue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.Transaction;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.Xid;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class DistributedTransaction implements ServerTransaction
+{
+
+ private final AutoCommitTransaction _autoCommitTransaction;
+
+ private volatile Transaction _transaction;
+
+ private long _txnStartTime = 0L;
+
+ private DtxBranch _branch;
+ private AMQSessionModel _session;
+ private VirtualHost _vhost;
+
+
+ public DistributedTransaction(AMQSessionModel session, MessageStore store, VirtualHost vhost)
+ {
+ _session = session;
+ _vhost = vhost;
+ _autoCommitTransaction = new AutoCommitTransaction(vhost.getMessageStore());
+ }
+
+ public long getTransactionStartTime()
+ {
+ return _txnStartTime;
+ }
+
+ public void addPostTransactionAction(Action postTransactionAction)
+ {
+ if(_branch != null)
+ {
+ _branch.addPostTransactionAcion(postTransactionAction);
+ }
+ else
+ {
+ _autoCommitTransaction.addPostTransactionAction(postTransactionAction);
+ }
+ }
+
+ public void dequeue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
+ {
+ if(_branch != null)
+ {
+ _branch.dequeue(queue, message);
+ _branch.addPostTransactionAcion(postTransactionAction);
+ }
+ else
+ {
+ _autoCommitTransaction.dequeue(queue, message, postTransactionAction);
+ }
+ }
+
+ public void dequeue(Collection<QueueEntry> messages, Action postTransactionAction)
+ {
+ if(_branch != null)
+ {
+ for(QueueEntry entry : messages)
+ {
+ _branch.dequeue(entry.getQueue(), entry.getMessage());
+ }
+ _branch.addPostTransactionAcion(postTransactionAction);
+ }
+ else
+ {
+ _autoCommitTransaction.dequeue(messages, postTransactionAction);
+ }
+ }
+
+ public void enqueue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction)
+ {
+ if(_branch != null)
+ {
+ _branch.enqueue(queue, message);
+ _branch.addPostTransactionAcion(postTransactionAction);
+ enqueue(Collections.singletonList(queue), message, postTransactionAction, System.currentTimeMillis());
+ }
+ else
+ {
+ _autoCommitTransaction.enqueue(queue, message, postTransactionAction);
+ }
+ }
+
+ public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message,
+ Action postTransactionAction, long currentTime)
+ {
+ if(_branch != null)
+ {
+ for(BaseQueue queue : queues)
+ {
+ _branch.enqueue(queue, message);
+ }
+ _branch.addPostTransactionAcion(postTransactionAction);
+ }
+ else
+ {
+ _autoCommitTransaction.enqueue(queues, message, postTransactionAction, currentTime);
+ }
+ }
+
+ public void commit()
+ {
+ throw new IllegalStateException("Cannot call tx.commit() on a distributed transaction");
+ }
+
+ public void commit(Runnable immediatePostTransactionAction)
+ {
+ throw new IllegalStateException("Cannot call tx.commit() on a distributed transaction");
+ }
+
+ public void rollback()
+ {
+ throw new IllegalStateException("Cannot call tx.rollback() on a distributed transaction");
+ }
+
+ public boolean isTransactional()
+ {
+ return _branch != null;
+ }
+
+ public void start(Xid id, boolean join, boolean resume)
+ throws UnknownDtxBranchException, AlreadyKnownDtxException, JoinAndResumeDtxException
+ {
+ if(join && resume)
+ {
+ throw new JoinAndResumeDtxException(id);
+ }
+
+ DtxBranch branch = _vhost.getDtxRegistry().getBranch(id);
+
+ if(branch == null)
+ {
+ if(join || resume)
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ branch = new DtxBranch(id,_vhost.getMessageStore(), _vhost);
+ if(_vhost.getDtxRegistry().registerBranch(branch))
+ {
+ _branch = branch;
+ branch.associateSession(_session);
+ }
+ else
+ {
+ throw new AlreadyKnownDtxException(id);
+ }
+ }
+ else
+ {
+ if(join)
+ {
+ branch.associateSession(_session);
+ }
+ else if(resume)
+ {
+ branch.resumeSession(_session);
+ }
+ else
+ {
+ throw new AlreadyKnownDtxException(id);
+ }
+ _branch = branch;
+ }
+ }
+
+ public void end(Xid id, boolean fail, boolean suspend)
+ throws UnknownDtxBranchException, NotAssociatedDtxException, SuspendAndFailDtxException, TimeoutDtxException
+ {
+ DtxBranch branch = _vhost.getDtxRegistry().getBranch(id);
+
+ if(suspend && fail)
+ {
+ branch.disassociateSession(_session);
+ _branch = null;
+ throw new SuspendAndFailDtxException(id);
+ }
+
+
+ if(branch == null)
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ else
+ {
+ if(!branch.isAssociated(_session))
+ {
+ throw new NotAssociatedDtxException(id);
+ }
+ if(branch.expired() || branch.getState() == DtxBranch.State.TIMEDOUT)
+ {
+ branch.disassociateSession(_session);
+ throw new TimeoutDtxException(id);
+ }
+
+ if(suspend)
+ {
+ branch.suspendSession(_session);
+ }
+ else
+ {
+ if(fail)
+ {
+ branch.setState(DtxBranch.State.ROLLBACK_ONLY);
+ }
+ branch.disassociateSession(_session);
+ }
+
+ _branch = null;
+
+ }
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
new file mode 100644
index 0000000000..3ac71fc6a6
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java
@@ -0,0 +1,349 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ScheduledFuture;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.queue.BaseQueue;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.Transaction;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.Xid;
+
+public class DtxBranch
+{
+ private static final Logger _logger = Logger.getLogger(DtxBranch.class);
+
+ private final Xid _xid;
+ private final List<ServerTransaction.Action> _postTransactionActions = new ArrayList<ServerTransaction.Action>();
+ private State _state = State.ACTIVE;
+ private long _timeout;
+ private Map<AMQSessionModel, State> _associatedSessions = new HashMap<AMQSessionModel, State>();
+ private final List<Record> _enqueueRecords = new ArrayList<Record>();
+ private final List<Record> _dequeueRecords = new ArrayList<Record>();
+
+ private Transaction _transaction;
+ private long _expiration;
+ private VirtualHost _vhost;
+ private ScheduledFuture<?> _timeoutFuture;
+ private MessageStore _store;
+
+
+ public enum State
+ {
+ ACTIVE,
+ PREPARED,
+ TIMEDOUT,
+ SUSPENDED,
+ FORGOTTEN,
+ HEUR_COM,
+ HEUR_RB,
+ ROLLBACK_ONLY
+ }
+
+
+ public DtxBranch(Xid xid, MessageStore store, VirtualHost vhost)
+ {
+ _xid = xid;
+ _store = store;
+ _vhost = vhost;
+ }
+
+ public Xid getXid()
+ {
+ return _xid;
+ }
+
+ public State getState()
+ {
+ return _state;
+ }
+
+ public void setState(State state)
+ {
+ _state = state;
+ }
+
+ public long getTimeout()
+ {
+ return _timeout;
+ }
+
+ public void setTimeout(long timeout)
+ {
+ if(_timeoutFuture != null)
+ {
+ _timeoutFuture.cancel(false);
+ }
+ _timeout = timeout;
+ _expiration = timeout == 0 ? 0 : System.currentTimeMillis() + timeout;
+
+ if(_timeout == 0)
+ {
+ _timeoutFuture = null;
+ }
+ else
+ {
+ _timeoutFuture = _vhost.scheduleTask(_timeout, new Runnable()
+ {
+ public void run()
+ {
+ setState(State.TIMEDOUT);
+ try
+ {
+ rollback();
+ }
+ catch (AMQStoreException e)
+ {
+ _logger.error("Unexpected error when attempting to rollback XA transaction ("+
+ _xid + ") due to timeout", e);
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ }
+
+ public boolean expired()
+ {
+ return _timeout != 0 && _expiration < System.currentTimeMillis();
+ }
+
+ public synchronized boolean isAssociated(AMQSessionModel session)
+ {
+ return _associatedSessions.containsKey(session);
+ }
+
+ public synchronized boolean hasAssociatedSessions()
+ {
+ return !_associatedSessions.isEmpty();
+ }
+
+
+ public synchronized boolean hasAssociatedActiveSessions()
+ {
+ if(hasAssociatedSessions())
+ {
+ for(State state : _associatedSessions.values())
+ {
+ if(state != State.SUSPENDED)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public synchronized void clearAssociations()
+ {
+ _associatedSessions.clear();
+ }
+
+ synchronized boolean associateSession(AMQSessionModel associatedSession)
+ {
+ return _associatedSessions.put(associatedSession, State.ACTIVE) != null;
+ }
+
+ synchronized boolean disassociateSession(AMQSessionModel associatedSession)
+ {
+ return _associatedSessions.remove(associatedSession) != null;
+ }
+
+ public synchronized boolean resumeSession(AMQSessionModel session)
+ {
+ if(_associatedSessions.containsKey(session) && _associatedSessions.get(session) == State.SUSPENDED)
+ {
+ _associatedSessions.put(session, State.ACTIVE);
+ return true;
+ }
+ return false;
+ }
+
+ public synchronized boolean suspendSession(AMQSessionModel session)
+ {
+ if(_associatedSessions.containsKey(session) && _associatedSessions.get(session) == State.ACTIVE)
+ {
+ _associatedSessions.put(session, State.SUSPENDED);
+ return true;
+ }
+ return false;
+ }
+
+ public void prepare() throws AMQStoreException
+ {
+
+ Transaction txn = _store.newTransaction();
+ txn.recordXid(_xid.getFormat(),
+ _xid.getGlobalId(),
+ _xid.getBranchId(),
+ _enqueueRecords.toArray(new Record[_enqueueRecords.size()]),
+ _dequeueRecords.toArray(new Record[_dequeueRecords.size()]));
+ txn.commitTran();
+
+ prePrepareTransaction();
+ }
+
+ public synchronized void rollback() throws AMQStoreException
+ {
+ if(_timeoutFuture != null)
+ {
+ _timeoutFuture.cancel(false);
+ _timeoutFuture = null;
+ }
+
+
+ if(_transaction != null)
+ {
+ // prepare has previously been called
+
+ Transaction txn = _store.newTransaction();
+ txn.removeXid(_xid.getFormat(), _xid.getGlobalId(), _xid.getBranchId());
+ txn.commitTran();
+
+ _transaction.abortTran();
+ }
+
+ for(ServerTransaction.Action action : _postTransactionActions)
+ {
+ action.onRollback();
+ }
+ _postTransactionActions.clear();
+ }
+
+ public void commit() throws AMQStoreException
+ {
+ if(_timeoutFuture != null)
+ {
+ _timeoutFuture.cancel(false);
+ _timeoutFuture = null;
+ }
+
+ if(_transaction == null)
+ {
+ prePrepareTransaction();
+ }
+ else
+ {
+ _transaction.removeXid(_xid.getFormat(), _xid.getGlobalId(), _xid.getBranchId());
+ }
+ _transaction.commitTran();
+
+ for(ServerTransaction.Action action : _postTransactionActions)
+ {
+ action.postCommit();
+ }
+ _postTransactionActions.clear();
+ }
+
+ public void prePrepareTransaction() throws AMQStoreException
+ {
+ _transaction = _store.newTransaction();
+
+ for(Record enqueue : _enqueueRecords)
+ {
+ if(enqueue.isDurable())
+ {
+ _transaction.enqueueMessage(enqueue.getQueue(), enqueue.getMessage());
+ }
+ }
+
+
+ for(Record enqueue : _dequeueRecords)
+ {
+ if(enqueue.isDurable())
+ {
+ _transaction.dequeueMessage(enqueue.getQueue(), enqueue.getMessage());
+ }
+ }
+ }
+
+
+ public void addPostTransactionAcion(ServerTransaction.Action postTransactionAction)
+ {
+ _postTransactionActions.add(postTransactionAction);
+ }
+
+
+ public void dequeue(BaseQueue queue, EnqueableMessage message)
+ {
+ _dequeueRecords.add(new Record(queue, message));
+ }
+
+
+ public void enqueue(BaseQueue queue, EnqueableMessage message)
+ {
+ _enqueueRecords.add(new Record(queue, message));
+ }
+
+ private static final class Record implements Transaction.Record
+ {
+ private final BaseQueue _queue;
+ private final EnqueableMessage _message;
+
+ public Record(BaseQueue queue, EnqueableMessage message)
+ {
+ _queue = queue;
+ _message = message;
+ }
+
+ public BaseQueue getQueue()
+ {
+ return _queue;
+ }
+
+ public EnqueableMessage getMessage()
+ {
+ return _message;
+ }
+
+ public boolean isDurable()
+ {
+ return _message.isPersistent() && _queue.isDurable();
+ }
+ }
+
+
+ public void close()
+ {
+ if(_transaction != null)
+ {
+ try
+ {
+ _state = null;
+ _transaction.abortTran();
+ }
+ catch(AMQStoreException e)
+ {
+ _logger.error("Error while closing XA branch", e);
+ }
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxException.java
new file mode 100644
index 0000000000..d18d0cb68b
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxException.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.txn;
+
+public class DtxException extends Exception
+{
+ public DtxException()
+ {
+ }
+
+ public DtxException(String message)
+ {
+ super(message);
+ }
+
+ public DtxException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public DtxException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxNotSelectedException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxNotSelectedException.java
new file mode 100644
index 0000000000..c1289b1fdd
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxNotSelectedException.java
@@ -0,0 +1,30 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+public class DtxNotSelectedException extends DtxException
+{
+ public DtxNotSelectedException()
+ {
+ super("Distribution transactions have not been selected on this session");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java
new file mode 100644
index 0000000000..5c54c1164f
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java
@@ -0,0 +1,333 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.transport.Xid;
+
+public class DtxRegistry
+{
+ private final Map<ComparableXid, DtxBranch> _branches = new HashMap<ComparableXid, DtxBranch>();
+
+
+ private static final class ComparableXid
+ {
+ private final Xid _xid;
+
+ private ComparableXid(Xid xid)
+ {
+ _xid = xid;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if(this == o)
+ {
+ return true;
+ }
+ if(o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ ComparableXid that = (ComparableXid) o;
+
+ return compareBytes(_xid.getBranchId(), that._xid.getBranchId())
+ && compareBytes(_xid.getGlobalId(), that._xid.getGlobalId());
+ }
+
+ private static boolean compareBytes(byte[] a, byte[] b)
+ {
+ if(a.length != b.length)
+ {
+ return false;
+ }
+ for(int i = 0; i < a.length; i++)
+ {
+ if(a[i] != b[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ @Override
+ public int hashCode()
+ {
+ int result = 0;
+ for(int i = 0; i < _xid.getGlobalId().length; i++)
+ {
+ result = 31 * result + (int) _xid.getGlobalId()[i];
+ }
+ for(int i = 0; i < _xid.getBranchId().length; i++)
+ {
+ result = 31 * result + (int) _xid.getBranchId()[i];
+ }
+
+ return result;
+ }
+ }
+
+ public synchronized DtxBranch getBranch(Xid xid)
+ {
+ return _branches.get(new ComparableXid(xid));
+ }
+
+ public synchronized boolean registerBranch(DtxBranch branch)
+ {
+ ComparableXid xid = new ComparableXid(branch.getXid());
+ if(!_branches.containsKey(xid))
+ {
+ _branches.put(xid, branch);
+ return true;
+ }
+ return false;
+ }
+
+ synchronized boolean unregisterBranch(DtxBranch branch)
+ {
+ return (_branches.remove(new ComparableXid(branch.getXid())) != null);
+ }
+
+ public void commit(Xid id, boolean onePhase)
+ throws IncorrectDtxStateException, UnknownDtxBranchException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ synchronized (branch)
+ {
+ if(!branch.hasAssociatedActiveSessions())
+ {
+ branch.clearAssociations();
+
+ if(branch.expired() || branch.getState() == DtxBranch.State.TIMEDOUT)
+ {
+ unregisterBranch(branch);
+ throw new TimeoutDtxException(id);
+ }
+ else if(branch.getState() == DtxBranch.State.ROLLBACK_ONLY)
+ {
+ throw new RollbackOnlyDtxException(id);
+ }
+ else if(onePhase && branch.getState() == DtxBranch.State.PREPARED)
+ {
+ throw new IncorrectDtxStateException("Cannot call one-phase commit on a prepared branch", id);
+ }
+ else if(!onePhase && branch.getState() != DtxBranch.State.PREPARED)
+ {
+ throw new IncorrectDtxStateException("Cannot call two-phase commit on a non-prepared branch",
+ id);
+ }
+ branch.commit();
+ branch.setState(DtxBranch.State.FORGOTTEN);
+ unregisterBranch(branch);
+ }
+ else
+ {
+ throw new IncorrectDtxStateException("Branch was still associated with a session", id);
+ }
+ }
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public synchronized void prepare(Xid id)
+ throws UnknownDtxBranchException,
+ IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ synchronized (branch)
+ {
+ if(!branch.hasAssociatedActiveSessions())
+ {
+ branch.clearAssociations();
+
+ if(branch.expired() || branch.getState() == DtxBranch.State.TIMEDOUT)
+ {
+ unregisterBranch(branch);
+ throw new TimeoutDtxException(id);
+ }
+ else if(branch.getState() != DtxBranch.State.ACTIVE
+ && branch.getState() != DtxBranch.State.ROLLBACK_ONLY)
+ {
+ throw new IncorrectDtxStateException("Cannot prepare a transaction in state "
+ + branch.getState(), id);
+ }
+ else
+ {
+ branch.prepare();
+ branch.setState(DtxBranch.State.PREPARED);
+ }
+ }
+ else
+ {
+ throw new IncorrectDtxStateException("Branch still has associated sessions", id);
+ }
+ }
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public void rollback(Xid id)
+ throws IncorrectDtxStateException,
+ UnknownDtxBranchException,
+ AMQStoreException, TimeoutDtxException
+ {
+
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ synchronized (branch)
+ {
+ if(branch.expired() || branch.getState() == DtxBranch.State.TIMEDOUT)
+ {
+ unregisterBranch(branch);
+ throw new TimeoutDtxException(id);
+ }
+ if(!branch.hasAssociatedActiveSessions())
+ {
+ branch.clearAssociations();
+ branch.rollback();
+ branch.setState(DtxBranch.State.FORGOTTEN);
+ unregisterBranch(branch);
+ }
+ else
+ {
+ throw new IncorrectDtxStateException("Branch was still associated with a session", id);
+ }
+ }
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+
+ public void forget(Xid id) throws UnknownDtxBranchException, IncorrectDtxStateException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ synchronized (branch)
+ {
+ if(!branch.hasAssociatedSessions())
+ {
+ if(branch.getState() != DtxBranch.State.HEUR_COM && branch.getState() != DtxBranch.State.HEUR_RB)
+ {
+ throw new IncorrectDtxStateException("Branch should not be forgotten - "
+ + "it is not heuristically complete", id);
+ }
+ branch.setState(DtxBranch.State.FORGOTTEN);
+ unregisterBranch(branch);
+ }
+ else
+ {
+ throw new IncorrectDtxStateException("Branch was still associated with a session", id);
+ }
+ }
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public long getTimeout(Xid id) throws UnknownDtxBranchException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ return branch.getTimeout();
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public void setTimeout(Xid id, long timeout) throws UnknownDtxBranchException
+ {
+ DtxBranch branch = getBranch(id);
+ if(branch != null)
+ {
+ branch.setTimeout(timeout);
+ }
+ else
+ {
+ throw new UnknownDtxBranchException(id);
+ }
+ }
+
+ public synchronized List<Xid> recover()
+ {
+ List<Xid> inDoubt = new ArrayList<Xid>();
+ for(DtxBranch branch : _branches.values())
+ {
+ if(branch.getState() == DtxBranch.State.PREPARED)
+ {
+ inDoubt.add(branch.getXid());
+ }
+ }
+ return inDoubt;
+ }
+
+ public synchronized void endAssociations(AMQSessionModel session)
+ {
+ for(DtxBranch branch : _branches.values())
+ {
+ if(branch.isAssociated(session))
+ {
+ branch.setState(DtxBranch.State.ROLLBACK_ONLY);
+ branch.disassociateSession(session);
+ }
+ }
+ }
+
+
+ public synchronized void close()
+ {
+ for(DtxBranch branch : _branches.values())
+ {
+ branch.close();
+ }
+ _branches.clear();
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/IncorrectDtxStateException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/IncorrectDtxStateException.java
new file mode 100644
index 0000000000..45f094e4b9
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/IncorrectDtxStateException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class IncorrectDtxStateException extends DtxException
+{
+ public IncorrectDtxStateException(String message, Xid id)
+ {
+ super(message + " (xid: " + id + ")");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/JoinAndResumeDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/JoinAndResumeDtxException.java
new file mode 100644
index 0000000000..a25e5a4ed6
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/JoinAndResumeDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class JoinAndResumeDtxException extends DtxException
+{
+ public JoinAndResumeDtxException(Xid id)
+ {
+ super("Cannot start a branch with both join and resume set " + id);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
index 9b61f7543f..11401ebd65 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
@@ -29,6 +29,7 @@ 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 java.util.ArrayList;
import java.util.Collection;
@@ -46,7 +47,7 @@ public class LocalTransaction implements ServerTransaction
private final List<Action> _postTransactionActions = new ArrayList<Action>();
- private volatile MessageStore.Transaction _transaction;
+ private volatile Transaction _transaction;
private MessageStore _transactionLog;
private long _txnStartTime = 0L;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/NotAssociatedDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/NotAssociatedDtxException.java
new file mode 100644
index 0000000000..de070546a7
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/NotAssociatedDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class NotAssociatedDtxException extends DtxException
+{
+ public NotAssociatedDtxException(Xid id)
+ {
+ super("Xid " + id + " not associated with the current session");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/RollbackOnlyDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/RollbackOnlyDtxException.java
new file mode 100644
index 0000000000..6cf12d8631
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/RollbackOnlyDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class RollbackOnlyDtxException extends DtxException
+{
+ public RollbackOnlyDtxException(Xid id)
+ {
+ super("Transaction " + id + " may only be rolled back");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
index 7617544451..c568ae67aa 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
@@ -20,13 +20,12 @@
*/
package org.apache.qpid.server.txn;
+import java.util.Collection;
+import java.util.List;
import org.apache.qpid.server.message.EnqueableMessage;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueEntry;
-import java.util.Collection;
-import java.util.List;
-
/**
* The ServerTransaction interface allows a set enqueue/dequeue operations to be
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/SuspendAndFailDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/SuspendAndFailDtxException.java
new file mode 100644
index 0000000000..228844fd63
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/SuspendAndFailDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class SuspendAndFailDtxException extends DtxException
+{
+public SuspendAndFailDtxException(Xid id)
+{
+ super("Cannot end a branch with both suspend and fail set " + id);
+}
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/TimeoutDtxException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/TimeoutDtxException.java
new file mode 100644
index 0000000000..50f7708d8a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/TimeoutDtxException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class TimeoutDtxException extends DtxException
+{
+ public TimeoutDtxException(Xid id)
+ {
+ super("Transaction " + id + " has timed-out and may only be rolled back");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/UnknownDtxBranchException.java b/java/broker/src/main/java/org/apache/qpid/server/txn/UnknownDtxBranchException.java
new file mode 100644
index 0000000000..c23e518365
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/UnknownDtxBranchException.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.transport.Xid;
+
+public class UnknownDtxBranchException extends DtxException
+{
+ public UnknownDtxBranchException(Xid id)
+ {
+ super("Unknown xid " + id);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/util/MapJsonSerializer.java b/java/broker/src/main/java/org/apache/qpid/server/util/MapJsonSerializer.java
new file mode 100644
index 0000000000..2d9ba38555
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/util/MapJsonSerializer.java
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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;
+
+import java.io.StringWriter;
+import java.util.Map;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+
+public class MapJsonSerializer
+{
+ private static final TypeReference<Map<String, Object>> MAP_TYPE_REFERENCE = new TypeReference<Map<String, Object>>()
+ {
+ };
+
+ private ObjectMapper _mapper;
+
+ public MapJsonSerializer()
+ {
+ _mapper = new ObjectMapper();
+ }
+
+ public String serialize(Map<String, Object> attributeMap)
+ {
+ StringWriter stringWriter = new StringWriter();
+ try
+ {
+ _mapper.writeValue(stringWriter, attributeMap);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Failure to serialize map:" + attributeMap, e);
+ }
+ return stringWriter.toString();
+ }
+
+ public Map<String, Object> deserialize(String json)
+ {
+ Map<String, Object> attributesMap = null;
+ try
+ {
+ attributesMap = _mapper.readValue(json, MAP_TYPE_REFERENCE);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Failure to deserialize json:" + json, e);
+ }
+ return attributesMap;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java
new file mode 100644
index 0000000000..fb50b3e289
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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.virtualhost;
+
+public enum State
+{
+ INITIALISING,
+ ACTIVE,
+ PASSIVE,
+ STOPPED
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
index afded3416e..489b985222 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
@@ -20,6 +20,9 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ScheduledFuture;
import org.apache.qpid.common.Closeable;
import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.configuration.ConfigStore;
@@ -30,16 +33,14 @@ import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.federation.BrokerLink;
import org.apache.qpid.server.management.ManagedObject;
+import org.apache.qpid.server.protocol.v1_0.LinkRegistry;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.stats.StatisticsGatherer;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
-
-import java.util.Map;
-import java.util.UUID;
+import org.apache.qpid.server.txn.DtxRegistry;
public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHostConfig, Closeable, StatisticsGatherer
{
@@ -57,10 +58,6 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo
MessageStore getMessageStore();
- DurableConfigurationStore getDurableConfigurationStore();
-
- AuthenticationManager getAuthenticationManager();
-
SecurityManager getSecurityManager();
void close();
@@ -96,5 +93,13 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo
ConfigStore getConfigStore();
+ DtxRegistry getDtxRegistry();
+
void removeBrokerConnection(BrokerLink brokerLink);
+
+ LinkRegistry getLinkRegistry(String remoteContainerId);
+
+ ScheduledFuture<?> scheduleTask(long delay, Runnable timeoutTask);
+
+ State getState();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
index 266d23af97..e956806823 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
@@ -20,9 +20,17 @@
*/
package org.apache.qpid.server.virtualhost;
-import org.apache.log4j.Logger;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.UUID;
+import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.binding.BindingFactory;
@@ -32,29 +40,27 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.TransactionLogMessages;
import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject;
import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.AbstractServerMessageImpl;
import org.apache.qpid.server.message.EnqueableMessage;
import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.MessageStoreRecoveryHandler;
import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.store.Transaction;
import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.txn.DtxBranch;
+import org.apache.qpid.server.txn.DtxRegistry;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.transport.Xid;
+import org.apache.qpid.transport.util.Functions;
import org.apache.qpid.util.ByteBufferInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.UUID;
-
public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHandler,
ConfigurationRecoveryHandler.QueueRecoveryHandler,
ConfigurationRecoveryHandler.ExchangeRecoveryHandler,
@@ -63,20 +69,19 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
MessageStoreRecoveryHandler,
MessageStoreRecoveryHandler.StoredMessageRecoveryHandler,
TransactionLogRecoveryHandler,
- TransactionLogRecoveryHandler.QueueEntryRecoveryHandler
+ TransactionLogRecoveryHandler.QueueEntryRecoveryHandler,
+ TransactionLogRecoveryHandler.DtxRecordRecoveryHandler
{
private static final Logger _logger = Logger.getLogger(VirtualHostConfigRecoveryHandler.class);
-
private final VirtualHost _virtualHost;
private MessageStoreLogSubject _logSubject;
- private List<ProcessAction> _actions;
private MessageStore _store;
private final Map<String, Integer> _queueRecoveries = new TreeMap<String, Integer>();
- private Map<Long, ServerMessage> _recoveredMessages = new HashMap<Long, ServerMessage>();
+ private Map<Long, AbstractServerMessageImpl> _recoveredMessages = new HashMap<Long, AbstractServerMessageImpl>();
private Map<Long, StoredMessage> _unusedMessages = new HashMap<Long, StoredMessage>();
@@ -88,14 +93,14 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
public VirtualHostConfigRecoveryHandler begin(MessageStore store)
{
- _logSubject = new MessageStoreLogSubject(_virtualHost,store);
+ _logSubject = new MessageStoreLogSubject(_virtualHost,store.getClass().getSimpleName());
_store = store;
CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_START(null, false));
return this;
}
- public void queue(String queueName, String owner, boolean exclusive, FieldTable arguments)
+ public void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments)
{
try
{
@@ -103,7 +108,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
if (q == null)
{
- q = AMQQueueFactory.createAMQQueueImpl(queueName, true, owner, false, exclusive, _virtualHost,
+ q = AMQQueueFactory.createAMQQueueImpl(id, queueName, true, owner, false, exclusive, _virtualHost,
FieldTable.convertToMap(arguments));
_virtualHost.getQueueRegistry().registerQueue(q);
}
@@ -125,7 +130,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
return this;
}
- public void exchange(String exchangeName, String type, boolean autoDelete)
+ public void exchange(UUID id, String exchangeName, String type, boolean autoDelete)
{
try
{
@@ -134,7 +139,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
exchange = _virtualHost.getExchangeRegistry().getExchange(exchangeNameSS);
if (exchange == null)
{
- exchange = _virtualHost.getExchangeFactory().createExchange(exchangeNameSS, new AMQShortString(type), true, autoDelete, 0);
+ exchange = _virtualHost.getExchangeFactory().createExchange(id, exchangeNameSS, new AMQShortString(type), true, autoDelete, 0);
_virtualHost.getExchangeRegistry().registerExchange(exchange);
}
}
@@ -158,7 +163,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
public void message(StoredMessage message)
{
- ServerMessage serverMessage;
+ AbstractServerMessageImpl serverMessage;
switch(message.getMetaData().getType())
{
case META_DATA_0_8:
@@ -193,47 +198,178 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
{
}
- private static final class ProcessAction
+ public void dtxRecord(long format, byte[] globalId, byte[] branchId,
+ Transaction.Record[] enqueues,
+ Transaction.Record[] dequeues)
{
- private final AMQQueue _queue;
- private final AMQMessage _message;
-
- public ProcessAction(AMQQueue queue, AMQMessage message)
+ Xid id = new Xid(format, globalId, branchId);
+ DtxRegistry dtxRegistry = _virtualHost.getDtxRegistry();
+ DtxBranch branch = dtxRegistry.getBranch(id);
+ if(branch == null)
{
- _queue = queue;
- _message = message;
+ branch = new DtxBranch(id, _store, _virtualHost);
+ dtxRegistry.registerBranch(branch);
}
+ for(Transaction.Record record : enqueues)
+ {
+ final AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(record.getQueue().getId());
+ if(queue != null)
+ {
+ final long messageId = record.getMessage().getMessageNumber();
+ final AbstractServerMessageImpl message = _recoveredMessages.get(messageId);
+ _unusedMessages.remove(messageId);
+
+ if(message != null)
+ {
+ message.incrementReference();
- public void process()
+ branch.enqueue(queue,message);
+
+ branch.addPostTransactionAcion(new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ try
+ {
+
+ queue.enqueue(message, true, null);
+ message.decrementReference();
+ }
+ catch (AMQException e)
+ {
+ _logger.error("Unable to enqueue message " + message.getMessageNumber() + " into " +
+ "queue " + queue.getName() + " (from XA transaction)", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void onRollback()
+ {
+ message.decrementReference();
+ }
+ });
+ }
+ else
+ {
+ StringBuilder xidString = xidAsString(id);
+ CurrentActor.get().message(_logSubject,
+ TransactionLogMessages.XA_INCOMPLETE_MESSAGE(xidString.toString(),
+ Long.toString(messageId)));
+
+ }
+
+ }
+ else
+ {
+ StringBuilder xidString = xidAsString(id);
+ CurrentActor.get().message(_logSubject,
+ TransactionLogMessages.XA_INCOMPLETE_QUEUE(xidString.toString(),
+ record.getQueue().getId().toString()));
+
+ }
+ }
+ for(Transaction.Record record : dequeues)
{
- try
+ final AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(record.getQueue().getId());
+ if(queue != null)
{
- _queue.enqueue(_message);
+ final long messageId = record.getMessage().getMessageNumber();
+ final AbstractServerMessageImpl message = _recoveredMessages.get(messageId);
+ _unusedMessages.remove(messageId);
+
+ if(message != null)
+ {
+ final QueueEntry entry = queue.getMessageOnTheQueue(messageId);
+
+ entry.acquire();
+
+ branch.dequeue(queue, message);
+
+ branch.addPostTransactionAcion(new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ entry.discard();
+ }
+
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+ }
+ else
+ {
+ StringBuilder xidString = xidAsString(id);
+ CurrentActor.get().message(_logSubject,
+ TransactionLogMessages.XA_INCOMPLETE_MESSAGE(xidString.toString(),
+ Long.toString(messageId)));
+
+ }
+
}
- catch(AMQException e)
+ else
{
- throw new RuntimeException(e);
+ StringBuilder xidString = xidAsString(id);
+ CurrentActor.get().message(_logSubject,
+ TransactionLogMessages.XA_INCOMPLETE_QUEUE(xidString.toString(),
+ record.getQueue().getId().toString()));
}
+
}
+ try
+ {
+ branch.setState(DtxBranch.State.PREPARED);
+ branch.prePrepareTransaction();
+ }
+ catch (AMQStoreException e)
+ {
+ _logger.error("Unexpected database exception when attempting to prepare a recovered XA transaction " +
+ xidAsString(id), e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static StringBuilder xidAsString(Xid id)
+ {
+ return new StringBuilder("(")
+ .append(id.getFormat())
+ .append(',')
+ .append(Functions.str(id.getGlobalId()))
+ .append(',')
+ .append(Functions.str(id.getBranchId()))
+ .append(')');
}
- public void binding(String exchangeName, String queueName, String bindingKey, ByteBuffer buf)
+ public void completeDtxRecordRecovery()
+ {
+ for(StoredMessage m : _unusedMessages.values())
+ {
+ _logger.warn("Message id " + m.getMessageNumber() + " in store, but not in any queue - removing....");
+ m.remove();
+ }
+ CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_COMPLETE(null, false));
+ }
+
+ @Override
+ public void binding(UUID bindingId, UUID exchangeId, UUID queueId, String bindingKey, ByteBuffer buf)
{
- _actions = new ArrayList<ProcessAction>();
try
{
- Exchange exchange = _virtualHost.getExchangeRegistry().getExchange(exchangeName);
+ Exchange exchange = _virtualHost.getExchangeRegistry().getExchange(exchangeId);
if (exchange == null)
{
- _logger.error("Unknown exchange: " + exchangeName + ", cannot bind queue : " + queueName);
+ _logger.error("Unknown exchange id " + exchangeId + ", cannot bind queue with id " + queueId);
return;
}
-
- AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(new AMQShortString(queueName));
+
+ AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(queueId);
if (queue == null)
{
- _logger.error("Unknown queue: " + queueName + ", cannot be bound to exchange: " + exchangeName);
+ _logger.error("Unknown queue id " + queueId + ", cannot be bound to exchange: " + exchange.getName());
}
else
{
@@ -257,10 +393,10 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
if(bf.getBinding(bindingKey, queue, exchange, argumentMap) == null)
{
- _logger.info("Restoring binding: (Exchange: " + exchange.getNameShortString() + ", Queue: " + queueName
+ _logger.info("Restoring binding: (Exchange: " + exchange.getNameShortString() + ", Queue: " + queue.getName()
+ ", Routing Key: " + bindingKey + ", Arguments: " + argumentsFT + ")");
- bf.restoreBinding(bindingKey, queue, exchange, argumentMap);
+ bf.restoreBinding(bindingId, bindingKey, queue, exchange, argumentMap);
}
}
}
@@ -282,16 +418,14 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
}
- public void queueEntry(final String queueName, long messageId)
+ public void queueEntry(final UUID queueId, long messageId)
{
- AMQShortString queueNameShortString = new AMQShortString(queueName);
-
- AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(queueNameShortString);
-
+ AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(queueId);
try
{
if(queue != null)
{
+ String queueName = queue.getName();
ServerMessage message = _recoveredMessages.get(messageId);
_unusedMessages.remove(messageId);
@@ -301,7 +435,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
if (_logger.isDebugEnabled())
{
- _logger.debug("On recovery, delivering " + message.getMessageNumber() + " to " + queue.getNameShortString());
+ _logger.debug("On recovery, delivering " + message.getMessageNumber() + " to " + queueName);
}
Integer count = _queueRecoveries.get(queueName);
@@ -316,23 +450,23 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
}
else
{
- _logger.warn("Message id " + messageId + " referenced in log as enqueued in queue " + queue.getNameShortString() + " is unknown, entry will be discarded");
- MessageStore.Transaction txn = _store.newTransaction();
+ _logger.warn("Message id " + messageId + " referenced in log as enqueued in queue " + queueName + " is unknown, entry will be discarded");
+ Transaction txn = _store.newTransaction();
txn.dequeueMessage(queue, new DummyMessage(messageId));
txn.commitTranAsync();
}
}
else
{
- _logger.warn("Message id " + messageId + " in log references queue " + queueName + " which is not in the configuration, entry will be discarded");
- MessageStore.Transaction txn = _store.newTransaction();
+ _logger.warn("Message id " + messageId + " in log references queue with id " + queueId + " which is not in the configuration, entry will be discarded");
+ Transaction txn = _store.newTransaction();
TransactionLogResource mockQueue =
new TransactionLogResource()
{
-
- public String getResourceName()
+ @Override
+ public UUID getId()
{
- return queueName;
+ return queueId;
}
};
txn.dequeueMessage(mockQueue, new DummyMessage(messageId));
@@ -344,20 +478,11 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
{
throw new RuntimeException(e);
}
-
-
-
}
- public void completeQueueEntryRecovery()
+ public DtxRecordRecoveryHandler completeQueueEntryRecovery()
{
- for(StoredMessage m : _unusedMessages.values())
- {
- _logger.warn("Message id " + m.getMessageNumber() + " in store, but not in any queue - removing....");
- m.remove();
- }
-
for(Map.Entry<String,Integer> entry : _queueRecoveries.entrySet())
{
CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERED(entry.getValue(), entry.getKey()));
@@ -365,7 +490,9 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_COMPLETE(entry.getKey(), true));
}
- CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_COMPLETE(null, false));
+
+
+ return this;
}
private static class DummyMessage implements EnqueableMessage
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
index 51b60f7980..9b113525d4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
@@ -20,14 +20,11 @@
*/
package org.apache.qpid.server.virtualhost;
-import org.apache.commons.configuration.Configuration;
+
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
-
import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQStoreException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.AMQBrokerManagerMBean;
import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.configuration.BrokerConfig;
@@ -44,225 +41,189 @@ import org.apache.qpid.server.exchange.DefaultExchangeRegistry;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.exchange.ExchangeRegistry;
-import org.apache.qpid.server.federation.Bridge;
import org.apache.qpid.server.federation.BrokerLink;
-import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.VirtualHostMessages;
import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject;
import org.apache.qpid.server.management.AMQManagedObject;
import org.apache.qpid.server.management.ManagedObject;
+import org.apache.qpid.server.protocol.v1_0.LinkRegistry;
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.AMQQueueFactory;
import org.apache.qpid.server.queue.DefaultQueueRegistry;
import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.stats.StatisticsCounter;
-import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
-import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.store.Event;
+import org.apache.qpid.server.store.EventListener;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreFactory;
+import org.apache.qpid.server.store.OperationalLoggingListener;
+import org.apache.qpid.server.txn.DtxRegistry;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPlugin;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory;
+import javax.management.JMException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
-import java.util.LinkedList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+
public class VirtualHostImpl implements VirtualHost
{
private static final Logger _logger = Logger.getLogger(VirtualHostImpl.class);
+ private static final int HOUSEKEEPING_SHUTDOWN_TIMEOUT = 5;
+
+ private final UUID _id;
+
private final String _name;
- private ConnectionRegistry _connectionRegistry;
+ private final long _createTime = System.currentTimeMillis();
- private QueueRegistry _queueRegistry;
+ private final ConcurrentHashMap<BrokerLink,BrokerLink> _links = new ConcurrentHashMap<BrokerLink, BrokerLink>();
- private ExchangeRegistry _exchangeRegistry;
+ private final ScheduledThreadPoolExecutor _houseKeepingTasks;
- private ExchangeFactory _exchangeFactory;
+ private final IApplicationRegistry _appRegistry;
- private MessageStore _messageStore;
+ private final SecurityManager _securityManager;
- private VirtualHostMBean _virtualHostMBean;
+ private final BrokerConfig _brokerConfig;
- private AMQBrokerManagerMBean _brokerMBean;
+ private final VirtualHostConfiguration _vhostConfig;
- private final AuthenticationManager _authenticationManager;
+ private final VirtualHostMBean _virtualHostMBean;
- private SecurityManager _securityManager;
+ private final AMQBrokerManagerMBean _brokerMBean;
- private final ScheduledThreadPoolExecutor _houseKeepingTasks;
- private final IApplicationRegistry _appRegistry;
- private VirtualHostConfiguration _configuration;
- private DurableConfigurationStore _durableConfigurationStore;
- private BindingFactory _bindingFactory;
- private BrokerConfig _broker;
- private UUID _id;
+ private final QueueRegistry _queueRegistry;
- private boolean _statisticsEnabled = false;
- private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
+ private final ExchangeRegistry _exchangeRegistry;
- private final long _createTime = System.currentTimeMillis();
- private final ConcurrentHashMap<BrokerLink,BrokerLink> _links = new ConcurrentHashMap<BrokerLink, BrokerLink>();
- private static final int HOUSEKEEPING_SHUTDOWN_TIMEOUT = 5;
+ private final ExchangeFactory _exchangeFactory;
- public IConnectionRegistry getConnectionRegistry()
- {
- return _connectionRegistry;
- }
+ private final ConnectionRegistry _connectionRegistry;
- public VirtualHostConfiguration getConfiguration()
- {
- return _configuration;
- }
+ private final BindingFactory _bindingFactory;
- public UUID getId()
- {
- return _id;
- }
+ private final DtxRegistry _dtxRegistry;
- public VirtualHostConfigType getConfigType()
- {
- return VirtualHostConfigType.getInstance();
- }
+ private final MessageStore _messageStore;
- public ConfiguredObject getParent()
- {
- return getBroker();
- }
+ private State _state = State.INITIALISING;
- public boolean isDurable()
- {
- return false;
- }
+ private boolean _statisticsEnabled = false;
- /**
- * Virtual host JMX MBean class.
- *
- * This has some of the methods implemented from management intrerface for exchanges. Any
- * implementaion of an Exchange MBean should extend this class.
- */
- public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtualHost
- {
- public VirtualHostMBean() throws NotCompliantMBeanException
- {
- super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE);
- }
+ private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
- public String getObjectInstanceName()
- {
- return ObjectName.quote(_name);
- }
+ private final Map<String, LinkRegistry> _linkRegistry = new HashMap<String, LinkRegistry>();
- public String getName()
+ public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig) throws Exception
+ {
+ if (hostConfig == null)
{
- return _name;
+ throw new IllegalArgumentException("HostConfig cannot be null");
}
- public VirtualHostImpl getVirtualHost()
+ if (hostConfig.getName() == null || hostConfig.getName().length() == 0)
{
- return VirtualHostImpl.this;
+ throw new IllegalArgumentException("Illegal name (" + hostConfig.getName() + ") for virtualhost.");
}
- }
- public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig, MessageStore store) throws Exception
- {
- if (hostConfig == null)
- {
- throw new IllegalArgumentException("HostConfig cannot be null");
- }
-
_appRegistry = appRegistry;
- _broker = _appRegistry.getBroker();
- _configuration = hostConfig;
- _name = _configuration.getName();
+ _brokerConfig = _appRegistry.getBroker();
+ _vhostConfig = hostConfig;
+ _name = _vhostConfig.getName();
+ _dtxRegistry = new DtxRegistry();
_id = _appRegistry.getConfigStore().createId();
CurrentActor.get().message(VirtualHostMessages.CREATED(_name));
- if (_name == null || _name.length() == 0)
- {
- throw new IllegalArgumentException("Illegal name (" + _name + ") for virtualhost.");
- }
-
- _securityManager = new SecurityManager(_appRegistry.getSecurityManager());
- _securityManager.configureHostPlugins(_configuration);
-
_virtualHostMBean = new VirtualHostMBean();
+ _securityManager = new SecurityManager(_appRegistry.getSecurityManager());
+ _securityManager.configureHostPlugins(_vhostConfig);
_connectionRegistry = new ConnectionRegistry();
- _houseKeepingTasks = new ScheduledThreadPoolExecutor(_configuration.getHouseKeepingThreadCount());
+ _houseKeepingTasks = new ScheduledThreadPoolExecutor(_vhostConfig.getHouseKeepingThreadCount());
_queueRegistry = new DefaultQueueRegistry(this);
_exchangeFactory = new DefaultExchangeFactory(this);
- _exchangeFactory.initialise(_configuration);
+ _exchangeFactory.initialise(_vhostConfig);
_exchangeRegistry = new DefaultExchangeRegistry(this);
- StartupRoutingTable configFileRT = new StartupRoutingTable();
+ _bindingFactory = new BindingFactory(this);
- _durableConfigurationStore = configFileRT;
+ _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
- // This needs to be after the RT has been defined as it creates the default durable exchanges.
- _exchangeRegistry.initialise();
+ _messageStore = initialiseMessageStore(hostConfig.getMessageStoreFactoryClass());
- _bindingFactory = new BindingFactory(this);
+ configureMessageStore(hostConfig);
- initialiseModel(_configuration);
+ activateNonHAMessageStore();
- if (store != null)
- {
- _messageStore = store;
- if(store instanceof DurableConfigurationStore)
- {
- _durableConfigurationStore = (DurableConfigurationStore) store;
- }
- }
- else
- {
- initialiseMessageStore(hostConfig);
- }
-
- _authenticationManager = ApplicationRegistry.getInstance().getAuthenticationManager();
-
- _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
- _brokerMBean.register();
- initialiseHouseKeeping(hostConfig.getHousekeepingCheckPeriod());
-
initialiseStatistics();
}
+ public IConnectionRegistry getConnectionRegistry()
+ {
+ return _connectionRegistry;
+ }
+
+ public VirtualHostConfiguration getConfiguration()
+ {
+ return _vhostConfig;
+ }
+
+ public UUID getId()
+ {
+ return _id;
+ }
+
+ public VirtualHostConfigType getConfigType()
+ {
+ return VirtualHostConfigType.getInstance();
+ }
+
+ public ConfiguredObject getParent()
+ {
+ return getBroker();
+ }
+
+ public boolean isDurable()
+ {
+ return false;
+ }
+
/**
* Initialise a housekeeping task to iterate over queues cleaning expired messages with no consumers
* and checking for idle or open transactions that have exceeded the permitted thresholds.
*
* @param period
*/
- private void initialiseHouseKeeping(long period)
+ private void initialiseHouseKeeping(long period)
{
+
if (period != 0L)
{
-
-
scheduleHouseKeepingTask(period, new VirtualHostHouseKeepingTask());
- Map<String, VirtualHostPluginFactory> plugins =
- ApplicationRegistry.getInstance().getPluginManager().getVirtualHostPlugins();
+ Map<String, VirtualHostPluginFactory> plugins = _appRegistry.getPluginManager().getVirtualHostPlugins();
if (plugins != null)
{
@@ -292,50 +253,30 @@ public class VirtualHostImpl implements VirtualHost
}
}
- private class VirtualHostHouseKeepingTask extends HouseKeepingTask
+ private void shutdownHouseKeeping()
{
- public VirtualHostHouseKeepingTask()
- {
- super(VirtualHostImpl.this);
- }
+ _houseKeepingTasks.shutdown();
- public void execute()
+ try
+ {
+ if (!_houseKeepingTasks.awaitTermination(HOUSEKEEPING_SHUTDOWN_TIMEOUT, TimeUnit.SECONDS))
+ {
+ _houseKeepingTasks.shutdownNow();
+ }
+ }
+ catch (InterruptedException e)
+ {
+ _logger.warn("Interrupted during Housekeeping shutdown:", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ private void removeHouseKeepingTasks()
+ {
+ BlockingQueue<Runnable> taskQueue = _houseKeepingTasks.getQueue();
+ for (final Runnable runnable : taskQueue)
{
- for (AMQQueue q : _queueRegistry.getQueues())
- {
- _logger.debug("Checking message status for queue: "
- + q.getName());
- try
- {
- q.checkMessageStatus();
- }
- catch (Exception e)
- {
- _logger.error("Exception in housekeeping for queue: "
- + q.getNameShortString().toString(), e);
- //Don't throw exceptions as this will stop the
- // house keeping task from running.
- }
- }
- for (AMQConnectionModel connection : getConnectionRegistry().getConnections())
- {
- _logger.debug("Checking for long running open transactions on connection " + connection);
- for (AMQSessionModel session : connection.getSessionModels())
- {
- _logger.debug("Checking for long running open transactions on session " + session);
- try
- {
- session.checkTransactionStatus(_configuration.getTransactionTimeoutOpenWarn(),
- _configuration.getTransactionTimeoutOpenClose(),
- _configuration.getTransactionTimeoutIdleWarn(),
- _configuration.getTransactionTimeoutIdleClose());
- }
- catch (Exception e)
- {
- _logger.error("Exception in housekeeping for connection: " + connection.toString(), e);
- }
- }
- }
+ _houseKeepingTasks.remove(runnable);
}
}
@@ -351,6 +292,11 @@ public class VirtualHostImpl implements VirtualHost
TimeUnit.MILLISECONDS);
}
+ public ScheduledFuture<?> scheduleTask(long delay, Runnable task)
+ {
+ return _houseKeepingTasks.schedule(task, delay, TimeUnit.MILLISECONDS);
+ }
+
public long getHouseKeepingTaskCount()
{
return _houseKeepingTasks.getTaskCount();
@@ -378,65 +324,58 @@ public class VirtualHostImpl implements VirtualHost
}
- private void initialiseMessageStore(VirtualHostConfiguration hostConfig) throws Exception
+ private MessageStore initialiseMessageStore(final String messageStoreFactoryClass) throws Exception
{
- String messageStoreClass = hostConfig.getMessageStoreClass();
-
- Class clazz = Class.forName(messageStoreClass);
- Object o = clazz.newInstance();
-
+ final Class<?> clazz = Class.forName(messageStoreFactoryClass);
+ final Object o = clazz.newInstance();
-
- if (!(o instanceof MessageStore))
+ if (!(o instanceof MessageStoreFactory))
{
- throw new ClassCastException("Message store class must implement " + MessageStore.class + ". Class " + clazz +
- " does not.");
+ throw new ClassCastException("Message store factory class must implement " + MessageStoreFactory.class +
+ ". Class " + clazz + " does not.");
}
- MessageStore messageStore = (MessageStore) o;
- VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(this);
- MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, messageStore);
+ final MessageStoreFactory messageStoreFactory = (MessageStoreFactory) o;
+ final MessageStore messageStore = messageStoreFactory.createMessageStore();
+ final MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, messageStoreFactory.getStoreClassName());
+ OperationalLoggingListener.listen(messageStore, storeLogSubject);
+ messageStore.addEventListener(new BeforeActivationListener(), Event.BEFORE_ACTIVATE);
+ messageStore.addEventListener(new AfterActivationListener(), Event.AFTER_ACTIVATE);
+ messageStore.addEventListener(new BeforeCloseListener(), Event.BEFORE_CLOSE);
+ messageStore.addEventListener(new BeforePassivationListener(), Event.BEFORE_PASSIVATE);
- if(messageStore instanceof DurableConfigurationStore)
- {
- DurableConfigurationStore durableConfigurationStore = (DurableConfigurationStore) messageStore;
-
- durableConfigurationStore.configureConfigStore(this.getName(),
- recoveryHandler,
- hostConfig.getStoreConfiguration(),
- storeLogSubject);
+ return messageStore;
+ }
- _durableConfigurationStore = durableConfigurationStore;
- }
+ private void configureMessageStore(VirtualHostConfiguration hostConfig) throws Exception
+ {
- messageStore.configureMessageStore(this.getName(),
- recoveryHandler,
- hostConfig.getStoreConfiguration(),
- storeLogSubject);
- messageStore.configureTransactionLog(this.getName(),
- recoveryHandler,
- hostConfig.getStoreConfiguration(),
- storeLogSubject);
+ VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(this);
- _messageStore = messageStore;
+ // TODO perhaps pass config on construction??
+ _messageStore.configureConfigStore(getName(), recoveryHandler, hostConfig.getStoreConfiguration());
+ _messageStore.configureMessageStore(getName(), recoveryHandler, recoveryHandler, hostConfig.getStoreConfiguration());
+ }
+ private void activateNonHAMessageStore() throws Exception
+ {
+ _messageStore.activate();
}
private void initialiseModel(VirtualHostConfiguration config) throws ConfigurationException, AMQException
{
_logger.debug("Loading configuration for virtualhost: " + config.getName());
- List exchangeNames = config.getExchanges();
+ List<String> exchangeNames = config.getExchanges();
- for (Object exchangeNameObj : exchangeNames)
+ for (String exchangeName : exchangeNames)
{
- String exchangeName = String.valueOf(exchangeNameObj);
configureExchange(config.getExchangeConfiguration(exchangeName));
}
- String[] queueNames = config.getQueueNames();
+ String[] queueNames = config.getQueueNames();
for (Object queueNameObj : queueNames)
{
@@ -447,45 +386,45 @@ public class VirtualHostImpl implements VirtualHost
private void configureExchange(ExchangeConfiguration exchangeConfiguration) throws AMQException
{
- AMQShortString exchangeName = new AMQShortString(exchangeConfiguration.getName());
+ AMQShortString exchangeName = new AMQShortString(exchangeConfiguration.getName());
Exchange exchange;
exchange = _exchangeRegistry.getExchange(exchangeName);
if (exchange == null)
{
- AMQShortString type = new AMQShortString(exchangeConfiguration.getType());
- boolean durable = exchangeConfiguration.getDurable();
- boolean autodelete = exchangeConfiguration.getAutoDelete();
+ AMQShortString type = new AMQShortString(exchangeConfiguration.getType());
+ boolean durable = exchangeConfiguration.getDurable();
+ boolean autodelete = exchangeConfiguration.getAutoDelete();
Exchange newExchange = _exchangeFactory.createExchange(exchangeName, type, durable, autodelete, 0);
_exchangeRegistry.registerExchange(newExchange);
if (newExchange.isDurable())
{
- _durableConfigurationStore.createExchange(newExchange);
+ _messageStore.createExchange(newExchange);
}
}
}
private void configureQueue(QueueConfiguration queueConfiguration) throws AMQException, ConfigurationException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueConfiguration, this);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueConfiguration, this);
String queueName = queue.getName();
- if (queue.isDurable())
- {
- getDurableConfigurationStore().createQueue(queue);
- }
+ if (queue.isDurable())
+ {
+ getMessageStore().createQueue(queue);
+ }
//get the exchange name (returns default exchange name if none was specified)
- String exchangeName = queueConfiguration.getExchange();
+ String exchangeName = queueConfiguration.getExchange();
Exchange exchange = _exchangeRegistry.getExchange(exchangeName);
- if (exchange == null)
- {
+ if (exchange == null)
+ {
throw new ConfigurationException("Attempt to bind queue '" + queueName + "' to unknown exchange:" + exchangeName);
- }
+ }
Exchange defaultExchange = _exchangeRegistry.getDefaultExchange();
@@ -531,17 +470,12 @@ public class VirtualHostImpl implements VirtualHost
public BrokerConfig getBroker()
{
- return _broker;
+ return _brokerConfig;
}
public String getFederationTag()
{
- return _broker.getFederationTag();
- }
-
- public void setBroker(final BrokerConfig broker)
- {
- _broker = broker;
+ return _brokerConfig.getFederationTag();
}
public long getCreateTime()
@@ -569,16 +503,6 @@ public class VirtualHostImpl implements VirtualHost
return _messageStore;
}
- public DurableConfigurationStore getDurableConfigurationStore()
- {
- return _durableConfigurationStore;
- }
-
- public AuthenticationManager getAuthenticationManager()
- {
- return _authenticationManager;
- }
-
public SecurityManager getSecurityManager()
{
return _securityManager;
@@ -588,34 +512,8 @@ public class VirtualHostImpl implements VirtualHost
{
//Stop Connections
_connectionRegistry.close();
-
- //Stop the Queues processing
- if (_queueRegistry != null)
- {
- for (AMQQueue queue : _queueRegistry.getQueues())
- {
- queue.stop();
- }
- }
-
- //Stop Housekeeping
- if (_houseKeepingTasks != null)
- {
- _houseKeepingTasks.shutdown();
-
- try
- {
- if (!_houseKeepingTasks.awaitTermination(HOUSEKEEPING_SHUTDOWN_TIMEOUT, TimeUnit.SECONDS))
- {
- _houseKeepingTasks.shutdownNow();
- }
- }
- catch (InterruptedException e)
- {
- _logger.warn("Interrupted during Housekeeping shutdown:" + e.getMessage());
- // Swallowing InterruptedException ok as we are shutting down.
- }
- }
+ _queueRegistry.stopAllAndUnregisterMBeans();
+ _dtxRegistry.close();
//Close MessageStore
if (_messageStore != null)
@@ -627,10 +525,12 @@ public class VirtualHostImpl implements VirtualHost
}
catch (Exception e)
{
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ _logger.error("Failed to close message store", e);
}
}
+ _state = State.STOPPED;
+
CurrentActor.get().message(VirtualHostMessages.CLOSED());
}
@@ -742,7 +642,6 @@ public class VirtualHostImpl implements VirtualHost
return blink;
}
-
public void createBrokerConnection(final String transport,
final String host,
final int port,
@@ -779,149 +678,182 @@ public class VirtualHostImpl implements VirtualHost
}
}
+ public synchronized LinkRegistry getLinkRegistry(String remoteContainerId)
+ {
+ LinkRegistry linkRegistry = _linkRegistry.get(remoteContainerId);
+ if(linkRegistry == null)
+ {
+ linkRegistry = new LinkRegistry();
+ _linkRegistry.put(remoteContainerId, linkRegistry);
+ }
+ return linkRegistry;
+ }
+
public ConfigStore getConfigStore()
{
return getApplicationRegistry().getConfigStore();
}
+ public DtxRegistry getDtxRegistry()
+ {
+ return _dtxRegistry;
+ }
+
+ @Override
+ public String toString()
+ {
+ return _name;
+ }
+
+ @Override
+ public State getState()
+ {
+ return _state;
+ }
+
+
/**
- * Temporary Startup RT class to record the creation of persistent queues / exchanges.
- *
+ * Virtual host JMX MBean class.
*
- * This is so we can replay the creation of queues/exchanges in to the real _RT after it has been loaded.
- * This should be removed after the _RT has been fully split from the the TL
+ * This has some of the methods implemented from management interface for exchanges. Any
+ * Implementation of an Exchange MBean should extend this class.
*/
- private static class StartupRoutingTable implements DurableConfigurationStore
+ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtualHost
{
- private List<Exchange> exchange = new LinkedList<Exchange>();
- private List<CreateQueueTuple> queue = new LinkedList<CreateQueueTuple>();
- private List<CreateBindingTuple> bindings = new LinkedList<CreateBindingTuple>();
- private List<BrokerLink> links = new LinkedList<BrokerLink>();
- private List<Bridge> bridges = new LinkedList<Bridge>();
-
- public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception
+ public VirtualHostMBean() throws NotCompliantMBeanException
{
+ super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE);
}
- public void close() throws Exception
+ public String getObjectInstanceName()
{
+ return ObjectName.quote(_name);
}
- public void removeMessage(Long messageId) throws AMQException
+ public String getName()
{
- //To change body of implemented methods use File | Settings | File Templates.
+ return _name;
}
- public void configureConfigStore(String name,
- ConfigurationRecoveryHandler recoveryHandler,
- Configuration config,
- LogSubject logSubject) throws Exception
+ public VirtualHostImpl getVirtualHost()
{
- //To change body of implemented methods use File | Settings | File Templates.
+ return VirtualHostImpl.this;
}
+ }
- public void createExchange(Exchange exchange) throws AMQStoreException
+ private final class BeforeActivationListener implements EventListener
+ {
+ @Override
+ public void event(Event event)
{
- if (exchange.isDurable())
+ try
{
- this.exchange.add(exchange);
- }
- }
-
- public void removeExchange(Exchange exchange) throws AMQStoreException
- {
- }
-
- public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException
- {
- if (exchange.isDurable() && queue.isDurable())
+ _exchangeRegistry.initialise();
+ initialiseModel(_vhostConfig);
+ } catch (Exception e)
{
- bindings.add(new CreateBindingTuple(exchange, routingKey, queue, args));
+ throw new RuntimeException("Failed to initialise virtual host after state change", e);
}
}
+ }
- public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException
- {
- }
-
- public void createQueue(AMQQueue queue) throws AMQStoreException
- {
- createQueue(queue, null);
- }
-
- public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQStoreException
+ private final class AfterActivationListener implements EventListener
+ {
+ @Override
+ public void event(Event event)
{
- if (queue.isDurable())
+ initialiseHouseKeeping(_vhostConfig.getHousekeepingCheckPeriod());
+ try
{
- this.queue.add(new CreateQueueTuple(queue, arguments));
+ _brokerMBean.register();
+ } catch (JMException e)
+ {
+ throw new RuntimeException("Failed to register virtual host mbean for virtual host " + getName(), e);
}
- }
- public void removeQueue(AMQQueue queue) throws AMQStoreException
- {
+ _state = State.ACTIVE;
}
+ }
+ public class BeforePassivationListener implements EventListener
+ {
- private static class CreateQueueTuple
+ @Override
+ public void event(Event event)
{
- private AMQQueue queue;
- private FieldTable arguments;
+ _connectionRegistry.close(IConnectionRegistry.VHOST_PASSIVATE_REPLY_TEXT);
+ _brokerMBean.unregister();
+ removeHouseKeepingTasks();
- public CreateQueueTuple(AMQQueue queue, FieldTable arguments)
- {
- this.queue = queue;
- this.arguments = arguments;
- }
+ _queueRegistry.stopAllAndUnregisterMBeans();
+ _exchangeRegistry.clearAndUnregisterMbeans();
+ _dtxRegistry.close();
+
+ _state = State.PASSIVE;
}
+ }
- private static class CreateBindingTuple
+ private final class BeforeCloseListener implements EventListener
+ {
+ @Override
+ public void event(Event event)
{
- private AMQQueue queue;
- private FieldTable arguments;
- private Exchange exchange;
- private AMQShortString routingKey;
-
- public CreateBindingTuple(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args)
- {
- this.exchange = exchange;
- this.routingKey = routingKey;
- this.queue = queue;
- arguments = args;
- }
+ _brokerMBean.unregister();
+ shutdownHouseKeeping();
}
+ }
- public void updateQueue(AMQQueue queue) throws AMQStoreException
+ private class VirtualHostHouseKeepingTask extends HouseKeepingTask
+ {
+ public VirtualHostHouseKeepingTask()
{
+ super(VirtualHostImpl.this);
}
- public void createBrokerLink(final BrokerLink link) throws AMQStoreException
+ public void execute()
{
- if(link.isDurable())
+ for (AMQQueue q : _queueRegistry.getQueues())
{
- links.add(link);
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Checking message status for queue: "
+ + q.getName());
+ }
+ try
+ {
+ q.checkMessageStatus();
+ } catch (Exception e)
+ {
+ _logger.error("Exception in housekeeping for queue: "
+ + q.getNameShortString().toString(), e);
+ //Don't throw exceptions as this will stop the
+ // house keeping task from running.
+ }
}
- }
-
- public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException
- {
- }
-
- public void createBridge(final Bridge bridge) throws AMQStoreException
- {
- if(bridge.isDurable())
+ for (AMQConnectionModel connection : getConnectionRegistry().getConnections())
{
- bridges.add(bridge);
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Checking for long running open transactions on connection " + connection);
+ }
+ for (AMQSessionModel session : connection.getSessionModels())
+ {
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Checking for long running open transactions on session " + session);
+ }
+ try
+ {
+ session.checkTransactionStatus(_vhostConfig.getTransactionTimeoutOpenWarn(),
+ _vhostConfig.getTransactionTimeoutOpenClose(),
+ _vhostConfig.getTransactionTimeoutIdleWarn(),
+ _vhostConfig.getTransactionTimeoutIdleClose());
+ } catch (Exception e)
+ {
+ _logger.error("Exception in housekeeping for connection: " + connection.toString(), e);
+ }
+ }
}
}
-
- public void deleteBridge(final Bridge bridge) throws AMQStoreException
- {
- }
- }
-
- @Override
- public String toString()
- {
- return _name;
}
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
index d34d1bbef3..5c500771c2 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
@@ -37,6 +37,7 @@ import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory;
import org.apache.qpid.server.util.TestApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostImpl;
@@ -165,7 +166,7 @@ public class AMQBrokerManagerMBeanTest extends QpidTestCase
XMLConfiguration configXml = new XMLConfiguration();
configXml.addProperty("virtualhosts.virtualhost(-1).name", "test");
- configXml.addProperty("virtualhosts.virtualhost(-1).test.store.class", TestableMemoryMessageStore.class.getName());
+ configXml.addProperty("virtualhosts.virtualhost(-1).test.store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
ServerConfiguration configuration = new ServerConfiguration(configXml);
diff --git a/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java b/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java
new file mode 100644
index 0000000000..fc6cbcb248
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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;
+
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.protocol.InternalTestProtocolSession;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+public class AMQChannelTest extends InternalBrokerBaseCase
+{
+ private VirtualHost _virtualHost;
+ private AMQProtocolSession _protocolSession;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next();
+ _protocolSession = new InternalTestProtocolSession(_virtualHost);
+ }
+
+ public void testCompareTo() throws Exception
+ {
+ AMQChannel channel1 = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore());
+
+ // create a channel with the same channelId but on a different session
+ AMQChannel channel2 = new AMQChannel(new InternalTestProtocolSession(_virtualHost), 1, _virtualHost.getMessageStore());
+ assertFalse("Unexpected compare result", channel1.compareTo(channel2) == 0);
+ assertEquals("Unexpected compare result", 0, channel1.compareTo(channel1));
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java
index 73e0bc5d27..c0777d2f8f 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java
@@ -1,3 +1,23 @@
+/*
+ *
+ * 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.configuration;
import java.util.UUID;
diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
index 50e7f0588b..c4c93acfb6 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
@@ -27,6 +27,7 @@ import org.apache.qpid.server.queue.AMQPriorityQueue;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -161,7 +162,7 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase
getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues(-1).queue(-1).name", "r2d2");
getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues.queue.r2d2.deadLetterQueues", "true");
getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues(-1).queue(-1).name", "c3p0");
- getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.store.class", TestableMemoryMessageStore.class.getName());
+ getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
// Start the broker now.
super.createBroker();
diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
index 27a0462e09..afd8fd9ed2 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
@@ -20,8 +20,19 @@
*/
package org.apache.qpid.server.exchange;
-import org.apache.log4j.Logger;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
@@ -31,11 +42,11 @@ import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.binding.Binding;
-import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
@@ -44,23 +55,10 @@ import org.apache.qpid.server.queue.MockStoredMessage;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.queue.SimpleAMQQueue;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.store.DurableConfigurationStore;
-import org.apache.qpid.server.store.MemoryMessageStore;
import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicLong;
-
public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
{
private static final Logger _log = Logger.getLogger(AbstractHeadersExchangeTestBase.class);
@@ -68,24 +66,6 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
private final HeadersExchange exchange = new HeadersExchange();
protected final Set<TestQueue> queues = new HashSet<TestQueue>();
-
-
- /**
- * Not used in this test, just there to stub out the routing calls
- */
- private MemoryMessageStore _store = new MemoryMessageStore();
-
-
- private BindingFactory bindingFactory = new BindingFactory(new DurableConfigurationStore.Source()
- {
-
- public DurableConfigurationStore getDurableConfigurationStore()
- {
- return _store;
- }
- },
- exchange);
-
private int count;
public void testDoNothing()
@@ -103,7 +83,6 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
protected void unbind(TestQueue queue, String... bindings) throws AMQException
{
String queueName = queue.getName();
- //TODO - check this
exchange.onUnbind(new Binding(null,queueName, queue, exchange, getHeadersMap(bindings)));
}
@@ -123,7 +102,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
protected int route(Message m) throws AMQException
{
- m.getIncomingMessage().headersReceived();
+ m.getIncomingMessage().headersReceived(System.currentTimeMillis());
m.route(exchange);
if(m.getIncomingMessage().allContentReceived())
{
@@ -297,7 +276,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
public TestQueue(AMQShortString name) throws AMQException
{
- super(name, false, new AMQShortString("test"), true, false,ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"), Collections.EMPTY_MAP);
+ super(UUIDGenerator.generateUUID(), name, false, new AMQShortString("test"), true, false,ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"), Collections.EMPTY_MAP);
ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test").getQueueRegistry().registerQueue(this);
}
@@ -538,12 +517,6 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
}
- public AMQMessage getUnderlyingMessage()
- {
- return Message.this;
- }
-
-
public ContentHeaderBody getContentHeader()
{
try
diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
index 1fac4afe29..9034bf9c3a 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
@@ -26,6 +26,7 @@ import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.management.common.mbeans.ManagedExchange;
import org.apache.qpid.server.management.ManagedObject;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.QueueRegistry;
@@ -52,7 +53,7 @@ public class ExchangeMBeanTest extends InternalBrokerBaseCase
public void testGeneralProperties() throws Exception
{
DirectExchange exchange = new DirectExchange();
- exchange.initialise(_virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
+ exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
ManagedObject managedObj = exchange.getManagedObject();
ManagedExchange mbean = (ManagedExchange)managedObj;
@@ -67,7 +68,7 @@ public class ExchangeMBeanTest extends InternalBrokerBaseCase
public void testDirectExchangeMBean() throws Exception
{
DirectExchange exchange = new DirectExchange();
- exchange.initialise(_virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
+ exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
ManagedObject managedObj = exchange.getManagedObject();
ManagedExchange mbean = (ManagedExchange)managedObj;
@@ -82,7 +83,7 @@ public class ExchangeMBeanTest extends InternalBrokerBaseCase
public void testTopicExchangeMBean() throws Exception
{
TopicExchange exchange = new TopicExchange();
- exchange.initialise(_virtualHost,ExchangeDefaults.TOPIC_EXCHANGE_NAME, false, 0, true);
+ exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.TOPIC_EXCHANGE_NAME, false, 0, true);
ManagedObject managedObj = exchange.getManagedObject();
ManagedExchange mbean = (ManagedExchange)managedObj;
@@ -97,7 +98,7 @@ public class ExchangeMBeanTest extends InternalBrokerBaseCase
public void testHeadersExchangeMBean() throws Exception
{
HeadersExchange exchange = new HeadersExchange();
- exchange.initialise(_virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
+ exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
ManagedObject managedObj = exchange.getManagedObject();
ManagedExchange mbean = (ManagedExchange)managedObj;
@@ -119,7 +120,7 @@ public class ExchangeMBeanTest extends InternalBrokerBaseCase
public void testHeadersExchangeMBeanMatchPropertyNoValue() throws Exception
{
HeadersExchange exchange = new HeadersExchange();
- exchange.initialise(_virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
+ exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
ManagedObject managedObj = exchange.getManagedObject();
ManagedExchange mbean = (ManagedExchange)managedObj;
@@ -137,7 +138,7 @@ public class ExchangeMBeanTest extends InternalBrokerBaseCase
public void testInvalidHeaderBindingMalformed() throws Exception
{
HeadersExchange exchange = new HeadersExchange();
- exchange.initialise(_virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
+ exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
ManagedObject managedObj = exchange.getManagedObject();
ManagedExchange mbean = (ManagedExchange)managedObj;
diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
index dfa31e131f..00c8a18d9f 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
@@ -350,7 +350,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
private int routeMessage(final IncomingMessage message)
throws AMQException
{
- MessageMetaData mmd = message.headersReceived();
+ MessageMetaData mmd = message.headersReceived(System.currentTimeMillis());
message.setStoredMessage(_store.addMessage(mmd));
message.enqueue(_exchange.route(message));
diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java
index cc032a0430..3377573b9d 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java
@@ -29,12 +29,10 @@ public class MessageStoreMessagesTest extends AbstractTestMessages
{
public void testMessageStoreCreated()
{
- String name = "DerbyMessageStore";
-
- _logMessage = MessageStoreMessages.CREATED(name);
+ _logMessage = MessageStoreMessages.CREATED();
List<Object> log = performLog();
- String[] expected = {"Created :", name};
+ String[] expected = {"Created"};
validateLogMessage(log, "MST-1001", expected);
}
@@ -70,56 +68,4 @@ public class MessageStoreMessagesTest extends AbstractTestMessages
validateLogMessage(log, "MST-1004", expected);
}
-/*
- public void testMessageStoreRecoveryStart_withQueue()
- {
- String queueName = "testQueue";
-
- _logMessage = MessageStoreMessages.RECOVERY_START(queueName, true);
- List<Object> log = performLog();
-
- String[] expected = {"Recovery Start :", queueName};
-
- validateLogMessage(log, "MST-1004", expected);
- }
-
- public void testMessageStoreRecovered()
- {
- String queueName = "testQueue";
- Integer messasgeCount = 2000;
-
- _logMessage = MessageStoreMessages.MST_RECOVERED(messasgeCount, queueName);
- List<Object> log = performLog();
-
- // Here we use MessageFormat to ensure the messasgeCount of 2000 is
- // reformated for display as '2,000'
- String[] expected = {"Recovered ",
- MessageFormat.format("{0,number}", messasgeCount),
- "messages for queue", queueName};
-
- validateLogMessage(log, "MST-1005", expected);
- }
-
- public void testMessageStoreRecoveryComplete()
- {
- _logMessage = MessageStoreMessages.MST_RECOVERY_COMPLETE(null,false);
- List<Object> log = performLog();
-
- String[] expected = {"Recovery Complete"};
-
- validateLogMessage(log, "MST-1006", expected);
- }
-
- public void testMessageStoreRecoveryComplete_withQueue()
- {
- String queueName = "testQueue";
-
- _logMessage = MessageStoreMessages.MST_RECOVERY_COMPLETE(queueName, true);
- List<Object> log = performLog();
-
- String[] expected = {"Recovery Complete :", queueName};
-
- validateLogMessage(log, "MST-1006", expected);
- }
- */
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java
index 158fb667a9..c62b24c3b9 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java
@@ -37,13 +37,13 @@ public class MessageStoreLogSubjectTest extends AbstractTestLogSubject
_testVhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().
getVirtualHost("test");
- _subject = new MessageStoreLogSubject(_testVhost, _testVhost.getMessageStore());
+ _subject = new MessageStoreLogSubject(_testVhost, _testVhost.getMessageStore().getClass().getSimpleName());
}
/**
* Validate that the logged Subject message is as expected:
* MESSAGE [Blank][vh(/test)/ms(MemoryMessageStore)] <Log Message>
- * @param message the message whos format needs validation
+ * @param message the message who's format needs validation
*/
@Override
protected void validateLogStatement(String message)
diff --git a/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java b/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java
index d64d1212b0..267545c656 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java
@@ -73,11 +73,11 @@ public class OsgiSystemPackageUtilTest extends QpidTestCase
_map.put("org.apache.qpid.xyz", "1.0.0");
_map.put("org.abc", "1.2.3");
- _util = new OsgiSystemPackageUtil(new Version("0.15"), _map);
+ _util = new OsgiSystemPackageUtil(new Version("0.17"), _map);
final String systemPackageString = _util.getFormattedSystemPackageString();
- assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=0.15.0", systemPackageString);
+ assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=0.17.0", systemPackageString);
}
public void testWithQpidPackageWithoutQpidReleaseNumberSet() throws Exception
diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
index 71d5211470..fe9bcc57a6 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
@@ -30,7 +30,7 @@ import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.SkeletonMessageStore;
+import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -45,7 +45,7 @@ public class AMQProtocolSessionMBeanTest extends InternalBrokerBaseCase
/** Used for debugging. */
private static final Logger log = Logger.getLogger(AMQProtocolSessionMBeanTest.class);
- private MessageStore _messageStore = new SkeletonMessageStore();
+ private MessageStore _messageStore = new TestableMemoryMessageStore();
private AMQProtocolEngine _protocolSession;
private AMQChannel _channel;
private AMQProtocolSessionMBean _mbean;
diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
index db37cc0965..96c67941f9 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
@@ -34,6 +34,7 @@ import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.server.subscription.ClientDeliveryMethod;
import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.subscription.SubscriptionImpl;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.TestNetworkConnection;
@@ -239,12 +240,12 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
_channelDelivers.put(_channelId, consumers);
}
- LinkedList<DeliveryPair> consumerDelivers = consumers.get(sub.getConsumerTag());
+ LinkedList<DeliveryPair> consumerDelivers = consumers.get(((SubscriptionImpl)sub).getConsumerTag());
if (consumerDelivers == null)
{
consumerDelivers = new LinkedList<DeliveryPair>();
- consumers.put(sub.getConsumerTag(), consumerDelivers);
+ consumers.put(((SubscriptionImpl)sub).getConsumerTag(), consumerDelivers);
}
consumerDelivers.add(new DeliveryPair(deliveryTag, (AMQMessage)entry.getMessage()));
diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java
index d8b5cd02cf..6081be8efd 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java
@@ -35,6 +35,7 @@ import java.util.Set;
public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase
{
+
protected void setUp() throws Exception
{
super.setUp();
@@ -93,7 +94,20 @@ public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase
(byte) 0,
(byte) 10
};
-
+
+
+ private static final byte[] AMQP_1_0_0_HEADER =
+ new byte[] {
+ (byte)'A',
+ (byte)'M',
+ (byte)'Q',
+ (byte)'P',
+ (byte) 0,
+ (byte) 1,
+ (byte) 0,
+ (byte) 0
+ };
+
private byte[] getAmqpHeader(final AmqpProtocolVersion version)
{
switch(version)
@@ -106,6 +120,8 @@ public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase
return AMQP_0_9_1_HEADER;
case v0_10:
return AMQP_0_10_HEADER;
+ case v1_0_0:
+ return AMQP_1_0_0_HEADER;
default:
fail("unknown AMQP version, appropriate header must be added for new protocol version");
return null;
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
index 91e35f07de..25d35aab16 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
@@ -35,6 +35,8 @@ import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import javax.management.Notification;
+
+import java.nio.ByteBuffer;
import java.util.ArrayList;
/** This class tests all the alerts an AMQQueue can throw based on threshold values of different parameters */
@@ -300,7 +302,7 @@ public class AMQQueueAlertTest extends InternalBrokerBaseCase
messages[i] = message(false, size);
ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
qs.add(getQueue());
- metaData[i] = messages[i].headersReceived();
+ metaData[i] = messages[i].headersReceived(System.currentTimeMillis());
messages[i].setStoredMessage(getMessageStore().addMessage(metaData[i]));
messages[i].enqueue(qs);
@@ -309,30 +311,29 @@ public class AMQQueueAlertTest extends InternalBrokerBaseCase
for (int i = 0; i < messageCount; i++)
{
- messages[i].addContentBodyFrame(
- new ContentChunk()
- {
-
- private byte[] _data = new byte[(int)size];
+ ContentChunk contentChunk = new ContentChunk()
+ {
+ private byte[] _data = new byte[(int)size];
- public int getSize()
- {
- return (int) size;
- }
+ public int getSize()
+ {
+ return (int) size;
+ }
- public byte[] getData()
- {
- return _data;
- }
+ public byte[] getData()
+ {
+ return _data;
+ }
- public void reduceToFit()
- {
+ public void reduceToFit()
+ {
+ }
+ };
- }
- });
+ messages[i].addContentBodyFrame(contentChunk);
+ messages[i].getStoredMessage().addContent(0, ByteBuffer.wrap(contentChunk.getData()));
getQueue().enqueue(new AMQMessage(messages[i].getStoredMessage()));
-
}
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
index 337ff194c3..e123a968a4 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.queue;
+import java.util.UUID;
+
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.qpid.AMQException;
@@ -35,6 +37,7 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.TestLogActor;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory;
import org.apache.qpid.server.util.TestApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -53,7 +56,7 @@ public class AMQQueueFactoryTest extends QpidTestCase
XMLConfiguration configXml = new XMLConfiguration();
configXml.addProperty("virtualhosts.virtualhost(-1).name", getName());
- configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName());
+ configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
ServerConfiguration configuration = new ServerConfiguration(configXml);
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
index 933eb3b84f..45933e7064 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
@@ -27,6 +27,7 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.management.common.mbeans.ManagedQueue;
import org.apache.qpid.server.AMQChannel;
@@ -45,6 +46,7 @@ import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.TabularData;
import java.io.IOException;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@@ -457,15 +459,16 @@ public class AMQQueueMBeanTest extends InternalBrokerBaseCase
currentMessage.enqueue(qs);
// route header
- MessageMetaData mmd = currentMessage.headersReceived();
- currentMessage.setStoredMessage(getMessageStore().addMessage(mmd));
+ MessageMetaData mmd = currentMessage.headersReceived(System.currentTimeMillis());
- // Add the body so we have something to test later
- currentMessage.addContentBodyFrame(
- getSession().getMethodRegistry()
- .getProtocolVersionMethodConverter()
- .convertToContentChunk(
- new ContentBody(new byte[(int) MESSAGE_SIZE])));
+ // Add the message to the store so we have something to test later
+ currentMessage.setStoredMessage(getMessageStore().addMessage(mmd));
+ ContentChunk chunk = getSession().getMethodRegistry()
+ .getProtocolVersionMethodConverter()
+ .convertToContentChunk(
+ new ContentBody(new byte[(int) MESSAGE_SIZE]));
+ currentMessage.addContentBodyFrame(chunk);
+ currentMessage.getStoredMessage().addContent(0, ByteBuffer.wrap(chunk.getData()));
AMQMessage m = new AMQMessage(currentMessage.getStoredMessage());
for(BaseQueue q : currentMessage.getDestinationQueues())
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java
index 1b35dfe34f..409b9fd92e 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java
@@ -20,7 +20,6 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
@@ -37,7 +36,7 @@ import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.StoredMessage;
-import org.apache.qpid.server.store.TestMemoryMessageStore;
+import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.txn.AutoCommitTransaction;
@@ -53,13 +52,11 @@ import java.util.Set;
*/
public class AckTest extends InternalBrokerBaseCase
{
- private static final Logger _log = Logger.getLogger(AckTest.class);
-
private Subscription _subscription;
private AMQProtocolSession _protocolSession;
- private TestMemoryMessageStore _messageStore;
+ private TestableMemoryMessageStore _messageStore;
private AMQChannel _channel;
@@ -73,7 +70,7 @@ public class AckTest extends InternalBrokerBaseCase
{
super.setUp();
_virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test");
- _messageStore = new TestMemoryMessageStore();
+ _messageStore = new TestableMemoryMessageStore();
_protocolSession = new InternalTestProtocolSession(_virtualHost);
_channel = new AMQChannel(_protocolSession,5, _messageStore /*dont need exchange registry*/);
@@ -143,7 +140,7 @@ public class AckTest extends InternalBrokerBaseCase
ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
qs.add(_queue);
msg.enqueue(qs);
- MessageMetaData mmd = msg.headersReceived();
+ MessageMetaData mmd = msg.headersReceived(System.currentTimeMillis());
final StoredMessage storedMessage = _messageStore.addMessage(mmd);
msg.setStoredMessage(storedMessage);
final AMQMessage message = new AMQMessage(storedMessage);
@@ -180,7 +177,7 @@ public class AckTest extends InternalBrokerBaseCase
}
catch (InterruptedException e)
{
- e.printStackTrace(); //TODO.
+ Thread.currentThread().interrupt();
}
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
index 34dc5b4428..afaa417415 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
@@ -34,7 +34,6 @@ import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.List;
@@ -357,12 +356,12 @@ public class MockAMQQueue implements AMQQueue
return null;
}
- public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction storeContext)
+ public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName)
{
}
- public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction storeContext)
+ public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName)
{
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java b/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java
index fba3851507..950d59bef5 100755
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java
@@ -25,7 +25,7 @@ import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.StoreFuture;
import org.apache.qpid.server.store.StoredMessage;
import java.nio.ByteBuffer;
@@ -105,9 +105,9 @@ public class MockStoredMessage implements StoredMessage<MessageMetaData>
return buf;
}
- public MessageStore.StoreFuture flushToStore()
+ public StoreFuture flushToStore()
{
- return MessageStore.IMMEDIATE_FUTURE;
+ return StoreFuture.IMMEDIATE_FUTURE;
}
public void remove()
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java
new file mode 100644
index 0000000000..e8c0470915
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class PriorityQueueListTest extends QpidTestCase
+{
+ private static final byte[] PRIORITIES = {4, 5, 5, 4};
+ PriorityQueueList _list = new PriorityQueueList(null, 10);
+
+ private QueueEntry _priority4message1;
+ private QueueEntry _priority4message2;
+ private QueueEntry _priority5message1;
+ private QueueEntry _priority5message2;
+
+ protected void setUp()
+ {
+ QueueEntry[] entries = new QueueEntry[PRIORITIES.length];
+
+ for (int i = 0; i < PRIORITIES.length; i++)
+ {
+ ServerMessage<?> message = mock(ServerMessage.class);
+ AMQMessageHeader header = mock(AMQMessageHeader.class);
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ MessageReference<ServerMessage> ref = mock(MessageReference.class);
+
+ when(message.getMessageHeader()).thenReturn(header);
+ when(message.newReference()).thenReturn(ref);
+ when(ref.getMessage()).thenReturn(message);
+ when(header.getPriority()).thenReturn(PRIORITIES[i]);
+
+ entries[i] = _list.add(message);
+ }
+
+ _priority4message1 = entries[0];
+ _priority4message2 = entries[3];
+ _priority5message1 = entries[1];
+ _priority5message2 = entries[2];
+ }
+
+ public void testPriorityQueueEntryCompareToItself()
+ {
+ //check messages compare to themselves properly
+ assertEquals("message should compare 'equal' to itself",
+ 0, _priority4message1.compareTo(_priority4message1));
+
+ assertEquals("message should compare 'equal' to itself",
+ 0, _priority5message2.compareTo(_priority5message2));
+ }
+
+ public void testPriorityQueueEntryCompareToSamePriority()
+ {
+ //check messages with the same priority are ordered properly
+ assertEquals("first message should be 'earlier' than second message of the same priority",
+ -1, _priority4message1.compareTo(_priority4message2));
+
+ assertEquals("first message should be 'earlier' than second message of the same priority",
+ -1, _priority5message1.compareTo(_priority5message2));
+
+ //and in reverse
+ assertEquals("second message should be 'later' than first message of the same priority",
+ 1, _priority4message2.compareTo(_priority4message1));
+
+ assertEquals("second message should be 'later' than first message of the same priority",
+ 1, _priority5message2.compareTo(_priority5message1));
+ }
+
+ public void testPriorityQueueEntryCompareToDifferentPriority()
+ {
+ //check messages with higher priority are ordered 'earlier' than those with lower priority
+ assertEquals("first message with priority 5 should be 'earlier' than first message of priority 4",
+ -1, _priority5message1.compareTo(_priority4message1));
+ assertEquals("first message with priority 5 should be 'earlier' than second message of priority 4",
+ -1, _priority5message1.compareTo(_priority4message2));
+
+ assertEquals("second message with priority 5 should be 'earlier' than first message of priority 4",
+ -1, _priority5message2.compareTo(_priority4message1));
+ assertEquals("second message with priority 5 should be 'earlier' than second message of priority 4",
+ -1, _priority5message2.compareTo(_priority4message2));
+
+ //and in reverse
+ assertEquals("first message with priority 4 should be 'later' than first message of priority 5",
+ 1, _priority4message1.compareTo(_priority5message1));
+ assertEquals("first message with priority 4 should be 'later' than second message of priority 5",
+ 1, _priority4message1.compareTo(_priority5message2));
+
+ assertEquals("second message with priority 4 should be 'later' than first message of priority 5",
+ 1, _priority4message2.compareTo(_priority5message1));
+ assertEquals("second message with priority 4 should be 'later' than second message of priority 5",
+ 1, _priority4message2.compareTo(_priority5message2));
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java b/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java
index 7f81aaed51..4b40c3b552 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java
@@ -31,6 +31,7 @@ public abstract class QueueEntryListTestBase extends TestCase
{
protected static final AMQQueue _testQueue = new MockAMQQueue("test");
public abstract QueueEntryList<QueueEntry> getTestList();
+ public abstract QueueEntryList<QueueEntry> getTestList(boolean newList);
public abstract long getExpectedFirstMsgId();
public abstract int getExpectedListLength();
public abstract ServerMessage getTestMessageToAdd() throws AMQException;
@@ -188,4 +189,36 @@ public abstract class QueueEntryListTestBase extends TestCase
.getMessage().getMessageNumber(), third.getMessage().getMessageNumber());
}
+ /**
+ * Tests that after the last node of the list is marked deleted but has not yet been removed,
+ * the iterator still ignores it and returns that it is 'atTail()' and can't 'advance()'
+ *
+ * @see QueueEntryListTestBase#getTestList()
+ * @see QueueEntryListTestBase#getExpectedListLength()
+ */
+ public void testIteratorIgnoresDeletedFinalNode() throws Exception
+ {
+ QueueEntryList<QueueEntry> list = getTestList(true);
+ int i = 0;
+
+ QueueEntry queueEntry1 = list.add(new MockAMQMessage(i++));
+ QueueEntry queueEntry2 = list.add(new MockAMQMessage(i++));
+
+ assertSame(queueEntry2, list.next(queueEntry1));
+ assertNull(list.next(queueEntry2));
+
+ //'delete' the 2nd QueueEntry
+ assertTrue("Deleting node should have succeeded", queueEntry2.delete());
+
+ QueueEntryIterator<QueueEntry> iter = list.iterator();
+
+ //verify the iterator isn't 'atTail', can advance, and returns the 1st QueueEntry
+ assertFalse("Iterator should not have been 'atTail'", iter.atTail());
+ assertTrue("Iterator should have been able to advance", iter.advance());
+ assertSame("Iterator returned unexpected QueueEntry", queueEntry1, iter.getNode());
+
+ //verify the iterator is atTail() and can't advance
+ assertTrue("Iterator should have been 'atTail'", iter.atTail());
+ assertFalse("Iterator should not have been able to advance", iter.advance());
+ }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
index c345384e28..52ad4a7c5b 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
@@ -37,15 +37,16 @@ import org.apache.qpid.server.exchange.DirectExchange;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.MessageMetaData;
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.registry.ApplicationRegistry;
import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory;
import org.apache.qpid.server.subscription.MockSubscription;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.txn.AutoCommitTransaction;
-import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -62,7 +63,6 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
protected SimpleAMQQueue _queue;
protected VirtualHost _virtualHost;
- protected TestableMemoryMessageStore _store = new TestableMemoryMessageStore();
protected AMQShortString _qname = new AMQShortString("qname");
protected AMQShortString _owner = new AMQShortString("owner");
protected AMQShortString _routingKey = new AMQShortString("routing key");
@@ -107,7 +107,9 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
ApplicationRegistry applicationRegistry = (ApplicationRegistry)ApplicationRegistry.getInstance();
PropertiesConfiguration env = new PropertiesConfiguration();
- _virtualHost = new VirtualHostImpl(ApplicationRegistry.getInstance(), new VirtualHostConfiguration(getClass().getName(), env), _store);
+ final VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration(getClass().getName(), env);
+ vhostConfig.setMessageStoreFactoryClass(TestableMemoryMessageStoreFactory.class.getName());
+ _virtualHost = new VirtualHostImpl(ApplicationRegistry.getInstance(), vhostConfig);
applicationRegistry.getVirtualHostRegistry().registerVirtualHost(_virtualHost);
_queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false, false, _virtualHost, _arguments);
@@ -136,7 +138,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
}
try {
- _queue = new SimpleAMQQueue(_qname, false, _owner, false, false,null, Collections.EMPTY_MAP);
+ _queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), _qname, false, _owner, false,false, null, Collections.EMPTY_MAP);
assertNull("Queue was created", _queue);
}
catch (IllegalArgumentException e)
@@ -478,7 +480,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
public void testAutoDeleteQueue() throws Exception
{
_queue.stop();
- _queue = new SimpleAMQQueue(_qname, false, null, true, false, _virtualHost, Collections.EMPTY_MAP);
+ _queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), _qname, false, null, true, false, _virtualHost, Collections.EMPTY_MAP);
_queue.setDeleteOnNoConsumers(true);
_queue.registerSubscription(_subscription, false);
AMQMessage message = createMessage(new Long(25));
@@ -634,12 +636,13 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
// Send persistent message
qs.add(_queue);
- MessageMetaData metaData = msg.headersReceived();
- StoredMessage handle = _store.addMessage(metaData);
+ MessageMetaData metaData = msg.headersReceived(System.currentTimeMillis());
+ TestableMemoryMessageStore store = (TestableMemoryMessageStore) _virtualHost.getMessageStore();
+ StoredMessage handle = store.addMessage(metaData);
msg.setStoredMessage(handle);
- ServerTransaction txn = new AutoCommitTransaction(_store);
+ ServerTransaction txn = new AutoCommitTransaction(store);
txn.enqueue(qs, msg, new ServerTransaction.Action()
{
@@ -654,7 +657,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
}, 0L);
// Check that it is enqueued
- AMQQueue data = _store.getMessages().get(1L);
+ AMQQueue data = store.getMessages().get(1L);
assertNull(data);
// Dequeue message
@@ -665,7 +668,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
_queue.dequeue(entry,null);
// Check that it is dequeued
- data = _store.getMessages().get(1L);
+ data = store.getMessages().get(1L);
assertNull(data);
}
@@ -689,8 +692,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
public void testProcessQueueWithUniqueSelectors() throws Exception
{
TestSimpleQueueEntryListFactory factory = new TestSimpleQueueEntryListFactory();
- SimpleAMQQueue testQueue = new SimpleAMQQueue("testQueue", false, "testOwner",false,
- false, _virtualHost, factory, null)
+ SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), "testQueue", false,"testOwner",
+ false, false, _virtualHost, factory, null)
{
@Override
public void deliverAsync(Subscription sub)
@@ -839,7 +842,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
/**
* Tests that dequeued message is not copied as part of invocation of
- * {@link SimpleAMQQueue#copyMessagesToAnotherQueue(long, long, String, ServerTransaction)}
+ * {@link SimpleAMQQueue#copyMessagesToAnotherQueue(long, long, String)}
*/
public void testCopyMessagesWithDequeuedEntry()
{
@@ -856,14 +859,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
// create another queue
SimpleAMQQueue queue = createQueue(anotherQueueName);
- // create transaction
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore());
-
// copy messages into another queue
- _queue.copyMessagesToAnotherQueue(0, messageNumber, anotherQueueName, txn);
-
- // commit transaction
- txn.commit();
+ _queue.copyMessagesToAnotherQueue(0, messageNumber, anotherQueueName);
// get messages on another queue
List<QueueEntry> entries = queue.getMessagesOnTheQueue();
@@ -889,7 +886,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
/**
* Tests that dequeued message is not moved as part of invocation of
- * {@link SimpleAMQQueue#moveMessagesToAnotherQueue(long, long, String, ServerTransaction)}
+ * {@link SimpleAMQQueue#moveMessagesToAnotherQueue(long, long, String)}
*/
public void testMovedMessagesWithDequeuedEntry()
{
@@ -906,14 +903,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
// create another queue
SimpleAMQQueue queue = createQueue(anotherQueueName);
- // create transaction
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getMessageStore());
-
// move messages into another queue
- _queue.moveMessagesToAnotherQueue(0, messageNumber, anotherQueueName, txn);
-
- // commit transaction
- txn.commit();
+ _queue.moveMessagesToAnotherQueue(0, messageNumber, anotherQueueName);
// get messages on another queue
List<QueueEntry> entries = queue.getMessagesOnTheQueue();
@@ -1038,8 +1029,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
int dequeueMessageIndex = 1;
// create queue with overridden method deliverAsync
- SimpleAMQQueue testQueue = new SimpleAMQQueue(new AMQShortString("test"), false,
- new AMQShortString("testOwner"), false, false, _virtualHost, null)
+ SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("test"),
+ false, new AMQShortString("testOwner"), false, false, _virtualHost, null)
{
@Override
public void deliverAsync(Subscription sub)
@@ -1109,8 +1100,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
public void testEqueueDequeuedEntry()
{
// create a queue where each even entry is considered a dequeued
- SimpleAMQQueue queue = new SimpleAMQQueue(new AMQShortString("test"), false, new AMQShortString("testOwner"),
- false, false, _virtualHost, new QueueEntryListFactory()
+ SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("test"), false,
+ new AMQShortString("testOwner"), false, false, _virtualHost, new QueueEntryListFactory()
{
public QueueEntryList createQueueEntryList(AMQQueue queue)
{
@@ -1187,8 +1178,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
public void testActiveConsumerCount() throws Exception
{
- final SimpleAMQQueue queue = new SimpleAMQQueue(new AMQShortString("testActiveConsumerCount"), false, new AMQShortString("testOwner"),
- false, false, _virtualHost, new SimpleQueueEntryList.Factory(), null);
+ final SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("testActiveConsumerCount"), false,
+ new AMQShortString("testOwner"), false, false, _virtualHost, new SimpleQueueEntryList.Factory(), null);
//verify adding an active subscription increases the count
final MockSubscription subscription1 = new MockSubscription();
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java
index d8d78bbb84..ac18bbe687 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java
@@ -1,3 +1,23 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java
index 55c6143124..caf1eea09f 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.queue.SimpleQueueEntryList.QueueEntryIteratorImpl;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -59,11 +60,24 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
System.clearProperty(SCAVENGE_PROP);
}
}
-
+
@Override
public QueueEntryList getTestList()
{
- return _sqel;
+ return getTestList(false);
+ }
+
+ @Override
+ public QueueEntryList getTestList(boolean newList)
+ {
+ if(newList)
+ {
+ return new SimpleQueueEntryList(_testQueue);
+ }
+ else
+ {
+ return _sqel;
+ }
}
@Override
@@ -216,5 +230,4 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase
next = next.getNextValidEntry();
assertNull("The next entry after the last should be null", next);
}
-
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java
index 794888f780..38b12f8250 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java
@@ -77,9 +77,23 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase
}
+ @Override
public QueueEntryList getTestList()
{
- return _sqel;
+ return getTestList(false);
+ }
+
+ @Override
+ public QueueEntryList getTestList(boolean newList)
+ {
+ if(newList)
+ {
+ return new SelfValidatingSortedQueueEntryList(_testQueue, "KEY");
+ }
+ else
+ {
+ return _sqel;
+ }
}
public int getExpectedListLength()
diff --git a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java b/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java
index 6a8a6dc2d0..9ff8f0a531 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java
@@ -80,11 +80,10 @@ public class ApplicationRegistryShutdownTest extends InternalBrokerBaseCase
}
}
- // Not using isEmpty as that is not in Java 5
- assertTrue("No new SASL mechanisms added by initialisation.", additions.size() != 0 );
+ assertFalse("No new SASL mechanisms added by initialisation.", additions.isEmpty());
//Close the registry which will perform the close the AuthenticationManager
- getRegistry().close();
+ stopBroker();
//Validate that the SASL plugFins have been removed.
Provider[] providersAfterClose = Security.getProviders();
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
index ba0a715001..bef03057ec 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
@@ -22,13 +22,19 @@ package org.apache.qpid.server.security.auth.rmi;
import junit.framework.TestCase;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
+import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.security.auth.AuthenticationResult;
import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.util.TestApplicationRegistry;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
import java.util.Collections;
@@ -47,7 +53,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
protected void setUp() throws Exception
{
_rmipa = new RMIPasswordAuthenticator();
-
+
_credentials = new String[] {USERNAME, PASSWORD};
}
@@ -114,8 +120,19 @@ public class RMIPasswordAuthenticatorTest extends TestCase
/**
* Tests case where authentication manager is not set.
*/
- public void testNullAuthenticationManager()
+ public void testNullAuthenticationManager() throws Exception
{
+ ServerConfiguration serverConfig = new ServerConfiguration(new XMLConfiguration());
+ TestApplicationRegistry reg = new TestApplicationRegistry(serverConfig)
+ {
+ @Override
+ protected AuthenticationManager createAuthenticationManager() throws ConfigurationException
+ {
+ return null;
+ }
+ };
+ ApplicationRegistry.initialise(reg);
+
try
{
_rmipa.authenticate(_credentials);
@@ -126,6 +143,10 @@ public class RMIPasswordAuthenticatorTest extends TestCase
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.UNABLE_TO_LOOKUP, se.getMessage());
}
+ finally
+ {
+ ApplicationRegistry.remove();
+ }
}
/**
@@ -254,6 +275,11 @@ public class RMIPasswordAuthenticatorTest extends TestCase
return new AuthenticationResult(AuthenticationStatus.CONTINUE);
}
}
+
+ public CallbackHandler getHandler(String mechanism)
+ {
+ return null;
+ }
};
}
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslServerTestCase.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslServerTestCase.java
index c3671d6a87..f5247634ac 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslServerTestCase.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslServerTestCase.java
@@ -54,7 +54,7 @@ public abstract class SaslServerTestCase extends TestCase
}
catch (SaslException e)
{
- assertEquals("Authentication failed", e.getCause().getMessage());
+ assertTrue(e.getMessage().contains("Authentication failed"));
exceptionCaught = true;
}
if (!exceptionCaught)
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java
new file mode 100644
index 0000000000..a1cbb2cbc8
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java
@@ -0,0 +1,377 @@
+package org.apache.qpid.server.store;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.times;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.common.AMQPFilterTypes;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.logging.SystemOutMessageLogger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.TestLogActor;
+import org.apache.qpid.server.logging.subjects.TestBlankSubject;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.MockStoredMessage;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreRecoveryHandler;
+import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BindingRecoveryHandler;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecoveryHandler;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler;
+import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler;
+import org.apache.qpid.server.store.Transaction.Record;
+import org.apache.qpid.server.store.derby.DerbyMessageStoreFactory;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.util.FileUtils;
+
+public class DurableConfigurationStoreTest extends QpidTestCase
+{
+ private static final String EXCHANGE_NAME = "exchangeName";
+ private String _storePath;
+ private String _storeName;
+ private MessageStore _store;
+ private Configuration _configuration;
+
+ private ConfigurationRecoveryHandler _recoveryHandler;
+ private QueueRecoveryHandler _queueRecoveryHandler;
+ private ExchangeRecoveryHandler _exchangeRecoveryHandler;
+ private BindingRecoveryHandler _bindingRecoveryHandler;
+ private ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler _linkRecoveryHandler;
+ private MessageStoreRecoveryHandler _messageStoreRecoveryHandler;
+ private StoredMessageRecoveryHandler _storedMessageRecoveryHandler;
+ private TransactionLogRecoveryHandler _logRecoveryHandler;
+ private TransactionLogRecoveryHandler.QueueEntryRecoveryHandler _queueEntryRecoveryHandler;
+ private TransactionLogRecoveryHandler.DtxRecordRecoveryHandler _dtxRecordRecoveryHandler;
+
+ private Exchange _exchange = mock(Exchange.class);
+ private static final String ROUTING_KEY = "routingKey";
+ private static final String QUEUE_NAME = "queueName";
+ private FieldTable _bindingArgs;
+ private UUID _queueId;
+ private UUID _exchangeId;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ _queueId = UUIDGenerator.generateUUID();
+ _exchangeId = UUIDGenerator.generateUUID();
+
+ _storeName = getName();
+ _storePath = TMP_FOLDER + "/" + _storeName;
+ FileUtils.delete(new File(_storePath), true);
+ setTestSystemProperty("QPID_WORK", TMP_FOLDER);
+ _configuration = mock(Configuration.class);
+ _recoveryHandler = mock(ConfigurationRecoveryHandler.class);
+ _queueRecoveryHandler = mock(QueueRecoveryHandler.class);
+ _exchangeRecoveryHandler = mock(ExchangeRecoveryHandler.class);
+ _bindingRecoveryHandler = mock(BindingRecoveryHandler.class);
+ _storedMessageRecoveryHandler = mock(StoredMessageRecoveryHandler.class);
+ _logRecoveryHandler = mock(TransactionLogRecoveryHandler.class);
+ _messageStoreRecoveryHandler = mock(MessageStoreRecoveryHandler.class);
+ _queueEntryRecoveryHandler = mock(TransactionLogRecoveryHandler.QueueEntryRecoveryHandler.class);
+ _dtxRecordRecoveryHandler = mock(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler.class);
+
+ when(_messageStoreRecoveryHandler.begin()).thenReturn(_storedMessageRecoveryHandler);
+ when(_recoveryHandler.begin(isA(MessageStore.class))).thenReturn(_queueRecoveryHandler);
+ when(_queueRecoveryHandler.completeQueueRecovery()).thenReturn(_exchangeRecoveryHandler);
+ when(_exchangeRecoveryHandler.completeExchangeRecovery()).thenReturn(_bindingRecoveryHandler);
+ when(_bindingRecoveryHandler.completeBindingRecovery()).thenReturn(_linkRecoveryHandler);
+ when(_logRecoveryHandler.begin(any(MessageStore.class))).thenReturn(_queueEntryRecoveryHandler);
+ when(_queueEntryRecoveryHandler.completeQueueEntryRecovery()).thenReturn(_dtxRecordRecoveryHandler);
+ when(_exchange.getNameShortString()).thenReturn(AMQShortString.valueOf(EXCHANGE_NAME));
+ when(_exchange.getId()).thenReturn(_exchangeId);
+ when(_configuration.getString(eq(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY), anyString())).thenReturn(
+ _storePath);
+
+ _bindingArgs = new FieldTable();
+ AMQShortString argKey = AMQPFilterTypes.JMS_SELECTOR.getValue();
+ String argValue = "some selector expression";
+ _bindingArgs.put(argKey, argValue);
+
+ reopenStore();
+ }
+
+ public void tearDown() throws Exception
+ {
+ FileUtils.delete(new File(_storePath), true);
+ super.tearDown();
+ }
+
+ public void testCreateExchange() throws Exception
+ {
+ Exchange exchange = createTestExchange();
+ _store.createExchange(exchange);
+
+ reopenStore();
+ verify(_exchangeRecoveryHandler).exchange(_exchangeId, getName(), getName() + "Type", true);
+ }
+
+ public void testRemoveExchange() throws Exception
+ {
+ Exchange exchange = createTestExchange();
+ _store.createExchange(exchange);
+
+ _store.removeExchange(exchange);
+
+ reopenStore();
+ verify(_exchangeRecoveryHandler, never()).exchange(any(UUID.class), anyString(), anyString(), anyBoolean());
+ }
+
+ public void testBindQueue() throws Exception
+ {
+ AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false);
+ Binding binding = new Binding(UUIDGenerator.generateUUID(), ROUTING_KEY, queue, _exchange,
+ FieldTable.convertToMap(_bindingArgs));
+ _store.bindQueue(binding);
+
+ reopenStore();
+
+ ByteBuffer argsAsBytes = ByteBuffer.wrap(_bindingArgs.getDataAsBytes());
+
+ verify(_bindingRecoveryHandler).binding(binding.getId(), _exchange.getId(), queue.getId(), ROUTING_KEY, argsAsBytes);
+ }
+
+ public void testUnbindQueue() throws Exception
+ {
+ AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false);
+ Binding binding = new Binding(UUIDGenerator.generateUUID(), ROUTING_KEY, queue, _exchange,
+ FieldTable.convertToMap(_bindingArgs));
+ _store.bindQueue(binding);
+
+ _store.unbindQueue(binding);
+ reopenStore();
+
+ verify(_bindingRecoveryHandler, never()).binding(any(UUID.class), any(UUID.class), any(UUID.class), anyString(),
+ isA(ByteBuffer.class));
+ }
+
+ public void testCreateQueueAMQQueue() throws Exception
+ {
+ AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true);
+ _store.createQueue(queue);
+
+ reopenStore();
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null);
+ }
+
+ public void testCreateQueueAMQQueueFieldTable() throws Exception
+ {
+ AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true);
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put("x-qpid-dlq-enabled", Boolean.TRUE);
+ attributes.put("x-qpid-maximum-delivery-count", new Integer(10));
+
+ FieldTable arguments = FieldTable.convertToFieldTable(attributes);
+ _store.createQueue(queue, arguments);
+
+ reopenStore();
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, arguments);
+ }
+
+ public void testUpdateQueue() throws Exception
+ {
+ // create queue
+ AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true);
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put("x-qpid-dlq-enabled", Boolean.TRUE);
+ attributes.put("x-qpid-maximum-delivery-count", new Integer(10));
+ FieldTable arguments = FieldTable.convertToFieldTable(attributes);
+ _store.createQueue(queue, arguments);
+
+ // update the queue to have exclusive=false
+ queue = createTestQueue(getName(), getName() + "Owner", false);
+ _store.updateQueue(queue);
+
+ reopenStore();
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments);
+ }
+
+ public void testRemoveQueue() throws Exception
+ {
+ // create queue
+ AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true);
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put("x-qpid-dlq-enabled", Boolean.TRUE);
+ attributes.put("x-qpid-maximum-delivery-count", new Integer(10));
+ FieldTable arguments = FieldTable.convertToFieldTable(attributes);
+ _store.createQueue(queue, arguments);
+
+ // remove queue
+ _store.removeQueue(queue);
+ reopenStore();
+ verify(_queueRecoveryHandler, never()).queue(any(UUID.class), anyString(), anyString(), anyBoolean(),
+ any(FieldTable.class));
+ }
+
+ private AMQQueue createTestQueue(String queueName, String queueOwner, boolean exclusive) throws AMQStoreException
+ {
+ AMQQueue queue = mock(AMQQueue.class);
+ when(queue.getName()).thenReturn(queueName);
+ when(queue.getNameShortString()).thenReturn(AMQShortString.valueOf(queueName));
+ when(queue.getOwner()).thenReturn(AMQShortString.valueOf(queueOwner));
+ when(queue.isExclusive()).thenReturn(exclusive);
+ when(queue.getId()).thenReturn(_queueId);
+ return queue;
+ }
+
+ private Exchange createTestExchange()
+ {
+ Exchange exchange = mock(Exchange.class);
+ when(exchange.getNameShortString()).thenReturn(AMQShortString.valueOf(getName()));
+ when(exchange.getName()).thenReturn(getName());
+ when(exchange.getTypeShortString()).thenReturn(AMQShortString.valueOf(getName() + "Type"));
+ when(exchange.isAutoDelete()).thenReturn(true);
+ when(exchange.getId()).thenReturn(_exchangeId);
+ return exchange;
+ }
+
+ private void reopenStore() throws Exception
+ {
+ if (_store != null)
+ {
+ _store.close();
+ }
+ _store = createStore();
+
+ _store.configureConfigStore(_storeName, _recoveryHandler, _configuration);
+ _store.configureMessageStore(_storeName, _messageStoreRecoveryHandler, _logRecoveryHandler, _configuration);
+ _store.activate();
+ }
+
+ protected MessageStore createStore() throws Exception
+ {
+ String storeFactoryClass = System.getProperty(MS_FACTORY_CLASS_NAME_KEY);
+ if (storeFactoryClass == null)
+ {
+ storeFactoryClass = DerbyMessageStoreFactory.class.getName();
+ }
+ CurrentActor.set(new TestLogActor(new SystemOutMessageLogger()));
+ MessageStoreFactory factory = (MessageStoreFactory) Class.forName(storeFactoryClass).newInstance();
+ return factory.createMessageStore();
+ }
+
+ public void testRecordXid() throws Exception
+ {
+ Record enqueueRecord = getTestRecord(1);
+ Record dequeueRecord = getTestRecord(2);
+ Record[] enqueues = { enqueueRecord };
+ Record[] dequeues = { dequeueRecord };
+ byte[] globalId = new byte[] { 1 };
+ byte[] branchId = new byte[] { 2 };
+
+ Transaction transaction = _store.newTransaction();
+ transaction.recordXid(1l, globalId, branchId, enqueues, dequeues);
+ transaction.commitTran();
+ reopenStore();
+ verify(_dtxRecordRecoveryHandler).dtxRecord(1l, globalId, branchId, enqueues, dequeues);
+
+ transaction = _store.newTransaction();
+ transaction.removeXid(1l, globalId, branchId);
+ transaction.commitTran();
+
+ reopenStore();
+ verify(_dtxRecordRecoveryHandler, times(1)).dtxRecord(1l, globalId, branchId, enqueues, dequeues);
+ }
+
+ private Record getTestRecord(long messageNumber)
+ {
+ UUID queueId1 = UUIDGenerator.generateUUID();
+ TransactionLogResource queue1 = mock(TransactionLogResource.class);
+ when(queue1.getId()).thenReturn(queueId1);
+ EnqueableMessage message1 = mock(EnqueableMessage.class);
+ when(message1.isPersistent()).thenReturn(true);
+ when(message1.getMessageNumber()).thenReturn(messageNumber);
+ when(message1.getStoredMessage()).thenReturn(new MockStoredMessage(messageNumber));
+ Record enqueueRecord = new TestRecord(queue1, message1);
+ return enqueueRecord;
+ }
+
+ private static class TestRecord implements Record
+ {
+ private TransactionLogResource _queue;
+ private EnqueableMessage _message;
+
+ public TestRecord(TransactionLogResource queue, EnqueableMessage message)
+ {
+ super();
+ _queue = queue;
+ _message = message;
+ }
+
+ @Override
+ public TransactionLogResource getQueue()
+ {
+ return _queue;
+ }
+
+ @Override
+ public EnqueableMessage getMessage()
+ {
+ return _message;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_message == null) ? 0 : new Long(_message.getMessageNumber()).hashCode());
+ result = prime * result + ((_queue == null) ? 0 : _queue.getId().hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof Record))
+ {
+ return false;
+ }
+ Record other = (Record) obj;
+ if (_message == null && other.getMessage() != null)
+ {
+ return false;
+ }
+ if (_queue == null && other.getQueue() != null)
+ {
+ return false;
+ }
+ if (_message.getMessageNumber() != other.getMessage().getMessageNumber())
+ {
+ return false;
+ }
+ return _queue.getId().equals(other.getQueue().getId());
+ }
+
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/EventManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/EventManagerTest.java
new file mode 100644
index 0000000000..2be79c5839
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/EventManagerTest.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.apache.qpid.server.store.Event.AFTER_ACTIVATE;
+import static org.apache.qpid.server.store.Event.BEFORE_ACTIVATE;
+import junit.framework.TestCase;
+
+public class EventManagerTest extends TestCase
+{
+ private EventManager _eventManager = new EventManager();
+ private EventListener _mockListener = mock(EventListener.class);
+
+ public void testEventListenerFires()
+ {
+ _eventManager.addEventListener(_mockListener, BEFORE_ACTIVATE);
+ _eventManager.notifyEvent(BEFORE_ACTIVATE);
+ verify(_mockListener).event(BEFORE_ACTIVATE);
+ }
+
+ public void testEventListenerDoesntFire()
+ {
+ _eventManager.addEventListener(_mockListener, BEFORE_ACTIVATE);
+ _eventManager.notifyEvent(AFTER_ACTIVATE);
+ verifyZeroInteractions(_mockListener);
+ }
+
+ public void testEventListenerFiresMulitpleTimes()
+ {
+ _eventManager.addEventListener(_mockListener, BEFORE_ACTIVATE);
+ _eventManager.addEventListener(_mockListener, AFTER_ACTIVATE);
+
+ _eventManager.notifyEvent(BEFORE_ACTIVATE);
+ verify(_mockListener).event(BEFORE_ACTIVATE);
+
+ _eventManager.notifyEvent(AFTER_ACTIVATE);
+ verify(_mockListener).event(AFTER_ACTIVATE);
+ }
+
+ public void testMultipleListenersFireForSameEvent()
+ {
+ final EventListener mockListener1 = mock(EventListener.class);
+ final EventListener mockListener2 = mock(EventListener.class);
+
+ _eventManager.addEventListener(mockListener1, BEFORE_ACTIVATE);
+ _eventManager.addEventListener(mockListener2, BEFORE_ACTIVATE);
+ _eventManager.notifyEvent(BEFORE_ACTIVATE);
+
+ verify(mockListener1).event(BEFORE_ACTIVATE);
+ verify(mockListener2).event(BEFORE_ACTIVATE);
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
index 5fc074d877..3fb0776083 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
@@ -39,6 +39,7 @@ import org.apache.qpid.server.exchange.ExchangeType;
import org.apache.qpid.server.exchange.TopicExchange;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.MessageMetaData;
+import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.AMQPriorityQueue;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
@@ -58,6 +59,7 @@ import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
/**
* This tests the MessageStores by using the available interfaces.
@@ -101,7 +103,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
String storePath = System.getProperty("QPID_WORK") + "/" + getName();
_config = new PropertiesConfiguration();
- _config.addProperty("store.class", getTestProfileMessageStoreClassName());
+ _config.addProperty("store.factoryclass", getTestProfileMessageStoreFactoryClassName());
_config.addProperty("store.environment-path", storePath);
cleanup(new File(storePath));
@@ -298,7 +300,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
1, queueRegistry.getQueues().size());
//test that removing the queue means it is not recovered next time
- getVirtualHost().getDurableConfigurationStore().removeQueue(queueRegistry.getQueue(durableQueueName));
+ getVirtualHost().getMessageStore().removeQueue(queueRegistry.getQueue(durableQueueName));
reloadVirtualHost();
@@ -351,7 +353,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
origExchangeCount + 1, exchangeRegistry.getExchangeNames().size());
//test that removing the exchange means it is not recovered next time
- getVirtualHost().getDurableConfigurationStore().removeExchange(exchangeRegistry.getExchange(directExchangeName));
+ getVirtualHost().getMessageStore().removeExchange(exchangeRegistry.getExchange(directExchangeName));
reloadVirtualHost();
@@ -600,7 +602,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
currentMessage.setExpiration();
- MessageMetaData mmd = currentMessage.headersReceived();
+ MessageMetaData mmd = currentMessage.headersReceived(System.currentTimeMillis());
currentMessage.setStoredMessage(getVirtualHost().getMessageStore().addMessage(mmd));
currentMessage.getStoredMessage().flushToStore();
currentMessage.route();
@@ -707,7 +709,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
if (queue.isDurable() && !queue.isAutoDelete())
{
- getVirtualHost().getDurableConfigurationStore().createQueue(queue, queueArguments);
+ getVirtualHost().getMessageStore().createQueue(queue, queueArguments);
}
}
catch (AMQException e)
@@ -739,7 +741,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
try
{
- exchange = type.newInstance(getVirtualHost(), name, durable, 0, false);
+ exchange = type.newInstance(UUIDGenerator.generateUUID(), getVirtualHost(), name, durable, 0, false);
}
catch (AMQException e)
{
@@ -751,7 +753,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
getVirtualHost().getExchangeRegistry().registerExchange(exchange);
if (durable)
{
- getVirtualHost().getDurableConfigurationStore().createExchange(exchange);
+ getVirtualHost().getMessageStore().createExchange(exchange);
}
}
catch (AMQException e)
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java
new file mode 100644
index 0000000000..42746f9119
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java
@@ -0,0 +1,181 @@
+package org.apache.qpid.server.store;
+
+import java.util.ArrayList;
+import java.util.List;
+import junit.framework.TestCase;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.LogMessage;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
+import org.apache.qpid.server.logging.messages.MessageStoreMessages;
+import org.apache.qpid.server.logging.messages.TransactionLogMessages;
+
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.
+ */
+public class OperationalLoggingListenerTest extends TestCase
+{
+
+
+ public static final String STORE_LOCATION = "The moon!";
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ }
+
+ public void testOperationalLoggingWithStoreLocation() throws Exception
+ {
+ TestMessageStore messageStore = new TestMessageStore();
+ LogSubject logSubject = LOG_SUBJECT;
+
+ OperationalLoggingListener.listen(messageStore, logSubject);
+
+ performTests(messageStore, true);
+
+ }
+
+ public void testOperationalLogging() throws Exception
+ {
+ TestMessageStore messageStore = new TestMessageStore();
+ LogSubject logSubject = LOG_SUBJECT;
+
+ OperationalLoggingListener.listen(messageStore, logSubject);
+
+ performTests(messageStore, false);
+ }
+
+ private void performTests(TestMessageStore messageStore, boolean setStoreLocation)
+ {
+ final List<LogMessage> messages = new ArrayList<LogMessage>();
+
+ CurrentActor.set(new TestActor(messages));
+
+ if(setStoreLocation)
+ {
+ messageStore.setStoreLocation(STORE_LOCATION);
+ }
+
+
+ messageStore.attainState(State.CONFIGURING);
+ assertEquals("Unexpected number of operational log messages on configuring", 1, messages.size());
+ assertEquals(messages.remove(0).toString(), ConfigStoreMessages.CREATED().toString());
+
+ messageStore.attainState(State.CONFIGURED);
+ assertEquals("Unexpected number of operational log messages on CONFIGURED", setStoreLocation ? 3 : 2, messages.size());
+ assertEquals(messages.remove(0).toString(), MessageStoreMessages.CREATED().toString());
+ assertEquals(messages.remove(0).toString(), TransactionLogMessages.CREATED().toString());
+ if(setStoreLocation)
+ {
+ assertEquals(messages.remove(0).toString(), MessageStoreMessages.STORE_LOCATION(STORE_LOCATION).toString());
+ }
+
+ messageStore.attainState(State.RECOVERING);
+ assertEquals("Unexpected number of operational log messages on RECOVERING", 1, messages.size());
+ assertEquals(messages.remove(0).toString(), MessageStoreMessages.RECOVERY_START().toString());
+
+
+ messageStore.attainState(State.ACTIVE);
+ assertEquals("Unexpected number of operational log messages on ACTIVE", 1, messages.size());
+ assertEquals(messages.remove(0).toString(), MessageStoreMessages.RECOVERY_COMPLETE().toString());
+
+ messageStore.attainState(State.CLOSING);
+ assertEquals("Unexpected number of operational log messages on CLOSING", 0, messages.size());
+
+ messageStore.attainState(State.CLOSED);
+ assertEquals("Unexpected number of operational log messages on CLOSED", 1, messages.size());
+ assertEquals(messages.remove(0).toString(), MessageStoreMessages.CLOSED().toString());
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ CurrentActor.remove();
+ }
+
+
+ private static final LogSubject LOG_SUBJECT = new LogSubject()
+ {
+ public String toLogString()
+ {
+ return "";
+ }
+ };
+
+ private static final class TestMessageStore extends NullMessageStore
+ {
+
+ private final EventManager _eventManager = new EventManager();
+ private final StateManager _stateManager = new StateManager(_eventManager);
+ private String _storeLocation;
+
+ public void attainState(State state)
+ {
+ _stateManager.attainState(state);
+ }
+
+ @Override
+ public String getStoreLocation()
+ {
+ return _storeLocation;
+ }
+
+ public void setStoreLocation(String storeLocation)
+ {
+ _storeLocation = storeLocation;
+ }
+
+ @Override
+ public void addEventListener(EventListener eventListener, Event... events)
+ {
+ _eventManager.addEventListener(eventListener, events);
+ }
+ }
+
+ private static class TestActor implements LogActor
+ {
+ private final List<LogMessage> _messages;
+
+ public TestActor(List<LogMessage> messages)
+ {
+ _messages = messages;
+ }
+
+ public void message(LogSubject subject, LogMessage message)
+ {
+ _messages.add(message);
+ }
+
+ public void message(LogMessage message)
+ {
+ _messages.add(message);
+ }
+
+ public RootMessageLogger getRootMessageLogger()
+ {
+ return null;
+ }
+
+ public String getLogMessage()
+ {
+ return null;
+ }
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java
index 2ffa157ca8..4aa023a25c 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java
@@ -34,12 +34,12 @@ import org.apache.qpid.test.utils.QpidTestCase;
*/
public class ReferenceCountingTest extends QpidTestCase
{
- private TestMemoryMessageStore _store;
+ private TestableMemoryMessageStore _store;
protected void setUp() throws Exception
{
- _store = new TestMemoryMessageStore();
+ _store = new TestableMemoryMessageStore();
}
/**
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java b/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java
deleted file mode 100644
index 88b9acffe0..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java
+++ /dev/null
@@ -1,157 +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.store;
-
-import org.apache.commons.configuration.Configuration;
-
-import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.message.EnqueableMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-
-/**
- * A message store that does nothing. Designed to be used in tests that do not want to use any message store
- * functionality.
- */
-public class SkeletonMessageStore implements MessageStore
-{
- public void configureConfigStore(String name,
- ConfigurationRecoveryHandler recoveryHandler,
- Configuration config,
- LogSubject logSubject) throws Exception
- {
- }
-
- public void configureMessageStore(String name,
- MessageStoreRecoveryHandler recoveryHandler,
- Configuration config,
- LogSubject logSubject) throws Exception
- {
- }
-
- public void close() throws Exception
- {
- }
-
- public <M extends StorableMessageMetaData> StoredMessage<M> addMessage(M metaData)
- {
- return null;
- }
-
-
- public void createExchange(Exchange exchange) throws AMQStoreException
- {
-
- }
-
- public void removeExchange(Exchange exchange) throws AMQStoreException
- {
-
- }
-
- public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException
- {
-
- }
-
- public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException
- {
-
- }
-
- public void createQueue(AMQQueue queue) throws AMQStoreException
- {
- }
-
- public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQStoreException
- {
- }
-
- public boolean isPersistent()
- {
- return false;
- }
-
- public void removeQueue(final AMQQueue queue) throws AMQStoreException
- {
-
- }
-
- public void configureTransactionLog(String name,
- TransactionLogRecoveryHandler recoveryHandler,
- Configuration storeConfiguration,
- LogSubject logSubject) throws Exception
- {
-
- }
-
- public Transaction newTransaction()
- {
- return new Transaction()
- {
-
- public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
- {
-
- }
-
- public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
- {
-
- }
-
- public void commitTran() throws AMQStoreException
- {
-
- }
-
- public StoreFuture commitTranAsync() throws AMQStoreException
- {
- return new StoreFuture()
- {
- public boolean isComplete()
- {
- return true;
- }
-
- public void waitForCompletion()
- {
-
- }
- };
- }
-
- public void abortTran() throws AMQStoreException
- {
-
- }
- };
- }
-
- public void updateQueue(AMQQueue queue) throws AMQStoreException
- {
-
- }
-
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java
new file mode 100644
index 0000000000..97c88ca1d3
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java
@@ -0,0 +1,195 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+
+import java.util.EnumSet;
+import junit.framework.TestCase;
+
+public class StateManagerTest extends TestCase implements EventListener
+{
+
+ private StateManager _manager;
+ private Event _event;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _manager = new StateManager(this);
+ }
+
+ public void testInitialState()
+ {
+ assertEquals(State.INITIAL, _manager.getState());
+ }
+
+ public void testStateTransitionAllowed()
+ {
+ assertEquals(State.INITIAL, _manager.getState());
+
+ _manager.stateTransition(State.INITIAL, State.CONFIGURING);
+ assertEquals(State.CONFIGURING, _manager.getState());
+ }
+
+ public void testStateTransitionDisallowed()
+ {
+ assertEquals(State.INITIAL, _manager.getState());
+
+ try
+ {
+ _manager.stateTransition(State.ACTIVE, State.CLOSING);
+ fail("Exception not thrown");
+ }
+ catch (IllegalStateException e)
+ {
+ // PASS
+ }
+ assertEquals(State.INITIAL, _manager.getState());
+ }
+
+ public void testIsInState()
+ {
+ assertEquals(State.INITIAL, _manager.getState());
+ assertFalse(_manager.isInState(State.ACTIVE));
+ assertTrue(_manager.isInState(State.INITIAL));
+ }
+
+ public void testIsNotInState()
+ {
+ assertEquals(State.INITIAL, _manager.getState());
+ assertTrue(_manager.isNotInState(State.ACTIVE));
+ assertFalse(_manager.isNotInState(State.INITIAL));
+ }
+
+ public void testCheckInState()
+ {
+ assertEquals(State.INITIAL, _manager.getState());
+
+ try
+ {
+ _manager.checkInState(State.ACTIVE);
+ fail("Exception not thrown");
+ }
+ catch (IllegalStateException e)
+ {
+ // PASS
+ }
+ assertEquals(State.INITIAL, _manager.getState());
+ }
+
+ public void testValidStateTransitions()
+ {
+ assertEquals(State.INITIAL, _manager.getState());
+ performValidTransition(StateManager.CONFIGURE);
+ performValidTransition(StateManager.CONFIGURE_COMPLETE);
+ performValidTransition(StateManager.RECOVER);
+ performValidTransition(StateManager.ACTIVATE);
+ performValidTransition(StateManager.QUIESCE);
+ performValidTransition(StateManager.QUIESCE_COMPLETE);
+ performValidTransition(StateManager.RESTART);
+ performValidTransition(StateManager.ACTIVATE);
+ performValidTransition(StateManager.CLOSE_ACTIVE);
+ performValidTransition(StateManager.CLOSE_COMPLETE);
+
+ _manager = new StateManager(this);
+ performValidTransition(StateManager.CONFIGURE);
+ performValidTransition(StateManager.CONFIGURE_COMPLETE);
+ performValidTransition(StateManager.RECOVER);
+ performValidTransition(StateManager.ACTIVATE);
+ performValidTransition(StateManager.QUIESCE);
+ performValidTransition(StateManager.QUIESCE_COMPLETE);
+ performValidTransition(StateManager.CLOSE_QUIESCED);
+ performValidTransition(StateManager.CLOSE_COMPLETE);
+ }
+
+ private void performValidTransition(StateManager.Transition transition)
+ {
+ _manager.attainState(transition.getEndState());
+ assertEquals("Unexpected end state", transition.getEndState(), _manager.getState());
+ assertEquals("Unexpected event", transition.getEvent(), _event);
+ _event = null;
+ }
+
+ public void testInvalidStateTransitions()
+ {
+ assertEquals(State.INITIAL, _manager.getState());
+
+
+ performInvalidTransitions(StateManager.CONFIGURE, State.CONFIGURED);
+ performInvalidTransitions(StateManager.CONFIGURE_COMPLETE, State.RECOVERING);
+ performInvalidTransitions(StateManager.RECOVER, State.ACTIVE);
+ performInvalidTransitions(StateManager.ACTIVATE, State.QUIESCING, State.CLOSING);
+ performInvalidTransitions(StateManager.QUIESCE, State.QUIESCED);
+ performInvalidTransitions(StateManager.QUIESCE_COMPLETE, State.RECOVERING, State.CLOSING);
+ performInvalidTransitions(StateManager.CLOSE_QUIESCED, State.CLOSED);
+ performInvalidTransitions(StateManager.CLOSE_COMPLETE);
+
+
+
+
+ }
+
+ private void performInvalidTransitions(StateManager.Transition preTransition, State... validTransitions)
+ {
+ if(preTransition != null)
+ {
+ performValidTransition(preTransition);
+ }
+
+ EnumSet<State> nextStates = EnumSet.allOf(State.class);
+
+ if(validTransitions != null)
+ {
+ for(State state: validTransitions)
+ {
+ nextStates.remove(state);
+ }
+ }
+
+ for(State nextState : nextStates)
+ {
+ performInvalidStateTransition(nextState);
+ }
+
+
+ }
+
+ private void performInvalidStateTransition(State state)
+ {
+ try
+ {
+ _event = null;
+ State startState = _manager.getState();
+ _manager.attainState(state);
+ fail("Invalid state transition performed: " + startState + " to " + state);
+ }
+ catch(IllegalStateException e)
+ {
+ // pass
+ }
+ assertNull("No event should have be fired", _event);
+ }
+
+ public void event(Event event)
+ {
+ _event = event;
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java b/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java
deleted file mode 100644
index 8a261b3b86..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java
+++ /dev/null
@@ -1,98 +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.store;
-
-import java.nio.ByteBuffer;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Adds some extra methods to the memory message store for testing purposes.
- */
-public class TestMemoryMessageStore extends MemoryMessageStore
-{
- private AtomicInteger _messageCount = new AtomicInteger(0);
-
-
- public TestMemoryMessageStore()
- {
- }
-
- @Override
- public StoredMessage addMessage(StorableMessageMetaData metaData)
- {
- return new TestableStoredMessage(super.addMessage(metaData));
- }
-
- public int getMessageCount()
- {
- return _messageCount.get();
- }
-
- private class TestableStoredMessage implements StoredMessage
- {
- private final StoredMessage _storedMessage;
-
- public TestableStoredMessage(StoredMessage storedMessage)
- {
- _messageCount.incrementAndGet();
- _storedMessage = storedMessage;
- }
-
- public StorableMessageMetaData getMetaData()
- {
- return _storedMessage.getMetaData();
- }
-
- public long getMessageNumber()
- {
- return _storedMessage.getMessageNumber();
- }
-
- public void addContent(int offsetInMessage, ByteBuffer src)
- {
- _storedMessage.addContent(offsetInMessage, src);
- }
-
- public int getContent(int offsetInMessage, ByteBuffer dst)
- {
- return _storedMessage.getContent(offsetInMessage, dst);
- }
-
-
- public ByteBuffer getContent(int offsetInMessage, int size)
- {
- return _storedMessage.getContent(offsetInMessage, size);
- }
-
- public StoreFuture flushToStore()
- {
- return _storedMessage.flushToStore();
- }
-
- public void remove()
- {
- _storedMessage.remove();
- _messageCount.decrementAndGet();
- }
-
- }
-
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java b/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
index e409734a17..210408f490 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
@@ -26,6 +26,7 @@ import org.apache.qpid.server.queue.AMQQueue;
import java.nio.ByteBuffer;
import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -33,26 +34,8 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class TestableMemoryMessageStore extends MemoryMessageStore
{
-
- private MemoryMessageStore _mms = null;
- private HashMap<Long, AMQQueue> _messages = new HashMap<Long, AMQQueue>();
- private AtomicInteger _messageCount = new AtomicInteger(0);
-
- public TestableMemoryMessageStore(MemoryMessageStore mms)
- {
- _mms = mms;
- }
-
- public TestableMemoryMessageStore()
- {
-
- }
-
- @Override
- public void close() throws Exception
- {
- // Not required to do anything
- }
+ private final Map<Long, AMQQueue> _messages = new HashMap<Long, AMQQueue>();
+ private final AtomicInteger _messageCount = new AtomicInteger(0);
@Override
public StoredMessage addMessage(StorableMessageMetaData metaData)
@@ -65,41 +48,47 @@ public class TestableMemoryMessageStore extends MemoryMessageStore
return _messageCount.get();
}
+ public Map<Long, AMQQueue> getMessages()
+ {
+ return _messages;
+ }
+
private class TestableTransaction implements Transaction
{
+ @Override
public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
{
getMessages().put(message.getMessageNumber(), (AMQQueue)queue);
}
+ @Override
public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
{
getMessages().remove(message.getMessageNumber());
}
+ @Override
public void commitTran() throws AMQStoreException
{
}
+ @Override
public StoreFuture commitTranAsync() throws AMQStoreException
{
- return new StoreFuture()
- {
- public boolean isComplete()
- {
- return true;
- }
-
- public void waitForCompletion()
- {
-
- }
- };
+ return StoreFuture.IMMEDIATE_FUTURE;
}
public void abortTran() throws AMQStoreException
{
}
+
+ public void removeXid(long format, byte[] globalId, byte[] branchId)
+ {
+ }
+
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ {
+ }
}
@@ -109,10 +98,6 @@ public class TestableMemoryMessageStore extends MemoryMessageStore
return new TestableTransaction();
}
- public HashMap<Long, AMQQueue> getMessages()
- {
- return _messages;
- }
private class TestableStoredMessage implements StoredMessage
{
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java b/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java
new file mode 100644
index 0000000000..44070f22ad
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+public class TestableMemoryMessageStoreFactory implements MessageStoreFactory
+{
+
+ @Override
+ public MessageStore createMessageStore()
+ {
+ return new TestableMemoryMessageStore();
+ }
+
+ @Override
+ public String getStoreClassName()
+ {
+ return TestableMemoryMessageStore.class.getSimpleName();
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
index 1d6ccfbbc2..5ba9c0c015 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
@@ -277,6 +277,10 @@ public class MockSubscription implements Subscription
return false;
}
+ public void queueEmpty() throws AMQException
+ {
+ }
+
public void setActive(final boolean isActive)
{
_isActive = isActive;
diff --git a/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java b/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java
new file mode 100644
index 0000000000..d775b0f2f8
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.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.transport;
+
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.MockConnectionConfig;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.Binary;
+
+public class ServerSessionTest extends InternalBrokerBaseCase
+{
+
+ private VirtualHost _virtualHost;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next();
+ }
+
+ public void testCompareTo() throws Exception
+ {
+ ServerConnection connection = new ServerConnection(1);
+ connection.setConnectionConfig(createConnectionConfig());
+ ServerSession session1 = new ServerSession(connection, new ServerSessionDelegate(),
+ new Binary(getName().getBytes()), 0 , connection.getConfig());
+
+ // create a session with the same name but on a different connection
+ ServerConnection connection2 = new ServerConnection(2);
+ connection2.setConnectionConfig(createConnectionConfig());
+ ServerSession session2 = new ServerSession(connection2, new ServerSessionDelegate(),
+ new Binary(getName().getBytes()), 0 , connection2.getConfig());
+
+ assertFalse("Unexpected compare result", session1.compareTo(session2) == 0);
+ assertEquals("Unexpected compare result", 0, session1.compareTo(session1));
+ }
+
+ private MockConnectionConfig createConnectionConfig()
+ {
+ return new MockConnectionConfig(UUID.randomUUID(), null, null,
+ false, 1, _virtualHost, "address", Boolean.TRUE, Boolean.TRUE, Boolean.TRUE,
+ "authid", "remoteProcessName", new Integer(1967), new Integer(1970), _virtualHost.getConfigStore(), Boolean.FALSE);
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
index fa0bb5be8b..af49238998 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
@@ -20,19 +20,13 @@
*/
package org.apache.qpid.server.txn;
-import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.NotImplementedException;
-
import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.message.EnqueableMessage;
import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.MessageStore.StoreFuture;
-import org.apache.qpid.server.store.MessageStore.Transaction;
-import org.apache.qpid.server.store.MessageStoreRecoveryHandler;
-import org.apache.qpid.server.store.StorableMessageMetaData;
-import org.apache.qpid.server.store.StoredMessage;
-import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
+import org.apache.qpid.server.store.NullMessageStore;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.Transaction;
import org.apache.qpid.server.store.TransactionLogResource;
/**
@@ -112,44 +106,24 @@ class MockStoreTransaction implements Transaction
_state = TransactionState.ABORTED;
}
- public static MessageStore createTestTransactionLog(final MockStoreTransaction storeTransaction)
+ public void removeXid(long format, byte[] globalId, byte[] branchId)
{
- return new MessageStore()
- {
- public void configureMessageStore(final String name,
- final MessageStoreRecoveryHandler recoveryHandler,
- final Configuration config,
- final LogSubject logSubject) throws Exception
- {
- //TODO.
- }
-
- public void close() throws Exception
- {
- //TODO.
- }
-
- public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(final T metaData)
- {
- return null; //TODO.
- }
-
- public boolean isPersistent()
- {
- return false; //TODO.
- }
+ }
- public void configureTransactionLog(String name, TransactionLogRecoveryHandler recoveryHandler,
- Configuration storeConfiguration, LogSubject logSubject) throws Exception
- {
- }
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ {
+ }
+ public static MessageStore createTestTransactionLog(final MockStoreTransaction storeTransaction)
+ {
+ return new NullMessageStore()
+ {
+ @Override
public Transaction newTransaction()
{
storeTransaction.setState(TransactionState.STARTED);
return storeTransaction;
}
-
- };
+ };
}
} \ No newline at end of file
diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java b/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
index 9df0aec545..8a34e92985 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.util;
+import java.util.UUID;
+
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.qpid.AMQException;
@@ -43,6 +45,7 @@ import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -65,10 +68,10 @@ public class InternalBrokerBaseCase extends QpidTestCase
super.setUp();
_configXml.addProperty("virtualhosts.virtualhost.name", "test");
- _configXml.addProperty("virtualhosts.virtualhost.test.store.class", TestableMemoryMessageStore.class.getName());
+ _configXml.addProperty("virtualhosts.virtualhost.test.store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
_configXml.addProperty("virtualhosts.virtualhost(-1).name", getName());
- _configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName());
+ _configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.factoryclass", TestableMemoryMessageStoreFactory.class.getName());
createBroker();
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/MapJsonSerializerTest.java b/java/broker/src/test/java/org/apache/qpid/server/util/MapJsonSerializerTest.java
new file mode 100644
index 0000000000..56567523df
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/util/MapJsonSerializerTest.java
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+public class MapJsonSerializerTest extends TestCase
+{
+ private MapJsonSerializer _serializer;
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ _serializer = new MapJsonSerializer();
+
+ }
+
+ public void testSerializeDeserialize()
+ {
+ Map<String, Object> testMap = new HashMap<String, Object>();
+ testMap.put("string", "Test String");
+ testMap.put("integer", new Integer(10));
+ testMap.put("long", new Long(Long.MAX_VALUE));
+ testMap.put("boolean", Boolean.TRUE);
+
+ String jsonString = _serializer.serialize(testMap);
+ Map<String, Object> deserializedMap = _serializer.deserialize(jsonString);
+
+ assertEquals(deserializedMap, testMap);
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
index 5fe664acdd..91174c5d10 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.util.concurrent.ScheduledFuture;
import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.configuration.BrokerConfig;
import org.apache.qpid.server.configuration.ConfigStore;
@@ -32,13 +33,14 @@ import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.federation.BrokerLink;
import org.apache.qpid.server.management.ManagedObject;
+import org.apache.qpid.server.protocol.v1_0.LinkRegistry;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.stats.StatisticsCounter;
-import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.txn.DtxRegistry;
import java.util.Map;
import java.util.UUID;
@@ -94,17 +96,17 @@ public class MockVirtualHost implements VirtualHost
return null;
}
- public VirtualHostConfiguration getConfiguration()
+ public DtxRegistry getDtxRegistry()
{
return null;
}
- public IConnectionRegistry getConnectionRegistry()
+ public VirtualHostConfiguration getConfiguration()
{
return null;
}
- public DurableConfigurationStore getDurableConfigurationStore()
+ public IConnectionRegistry getConnectionRegistry()
{
return null;
}
@@ -170,6 +172,16 @@ public class MockVirtualHost implements VirtualHost
}
+ public LinkRegistry getLinkRegistry(String remoteContainerId)
+ {
+ return null;
+ }
+
+ public ScheduledFuture<?> scheduleTask(long delay, Runnable timeoutTask)
+ {
+ return null;
+ }
+
public void scheduleHouseKeepingTask(long period, HouseKeepingTask task)
{
@@ -269,4 +281,10 @@ public class MockVirtualHost implements VirtualHost
{
}
+
+ @Override
+ public State getState()
+ {
+ return State.ACTIVE;
+ }
} \ No newline at end of file
diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java
index df7b4da426..87eb0f9d16 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java
@@ -27,7 +27,7 @@ import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.store.MemoryMessageStoreFactory;
import org.apache.qpid.server.util.TestApplicationRegistry;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -68,31 +68,6 @@ public class VirtualHostImplTest extends QpidTestCase
customBindingTestImpl(new String[0]);
}
- private void customBindingTestImpl(final String[] routingKeys) throws Exception
- {
- String exchangeName = getName() +".direct";
- String vhostName = getName();
- String queueName = getName();
-
- File config = writeConfigFile(vhostName, queueName, exchangeName, false, routingKeys);
- VirtualHost vhost = createVirtualHost(vhostName, config);
- assertNotNull("virtualhost should exist", vhost);
-
- AMQQueue queue = vhost.getQueueRegistry().getQueue(queueName);
- assertNotNull("queue should exist", queue);
-
- Exchange defaultExch = vhost.getExchangeRegistry().getDefaultExchange();
- assertTrue("queue should have been bound to default exchange with its name", defaultExch.isBound(queueName, queue));
-
- Exchange exch = vhost.getExchangeRegistry().getExchange(exchangeName);
- assertTrue("queue should have been bound to " + exchangeName + " with its name", exch.isBound(queueName, queue));
-
- for(String key: routingKeys)
- {
- assertTrue("queue should have been bound to " + exchangeName + " with key " + key, exch.isBound(key, queue));
- }
- }
-
/**
* Tests that specifying custom routing keys for a queue in the configuration file results in failure
* to create the vhost (since this is illegal, only queue names are used with the default exchange)
@@ -106,12 +81,32 @@ public class VirtualHostImplTest extends QpidTestCase
createVirtualHost(getName(), config);
fail("virtualhost creation should have failed due to illegal configuration");
}
- catch (ConfigurationException e)
+ catch (RuntimeException e)
{
+ assertEquals(ConfigurationException.class, e.getCause().getClass());
//expected
}
}
+ public void testVirtualHostBecomesActive() throws Exception
+ {
+ File config = writeConfigFile(getName(), getName(), getName() +".direct", false, new String[0]);
+ VirtualHost vhost = createVirtualHost(getName(), config);
+ assertNotNull(vhost);
+ assertEquals(State.ACTIVE, vhost.getState());
+ }
+
+ public void testVirtualHostBecomesStoppedOnClose() throws Exception
+ {
+ File config = writeConfigFile(getName(), getName(), getName() +".direct", false, new String[0]);
+ VirtualHost vhost = createVirtualHost(getName(), config);
+ assertNotNull(vhost);
+ assertEquals(State.ACTIVE, vhost.getState());
+ vhost.close();
+ assertEquals(State.STOPPED, vhost.getState());
+ assertEquals(0, vhost.getHouseKeepingActiveCount());
+ }
+
/**
* Tests that specifying an unknown exchange to bind the queue to results in failure to create the vhost
*/
@@ -124,12 +119,39 @@ public class VirtualHostImplTest extends QpidTestCase
createVirtualHost(getName(), config);
fail("virtualhost creation should have failed due to illegal configuration");
}
- catch (ConfigurationException e)
+ catch (RuntimeException e)
{
+ assertEquals(ConfigurationException.class, e.getCause().getClass());
//expected
}
}
+ private void customBindingTestImpl(final String[] routingKeys) throws Exception
+ {
+ String exchangeName = getName() +".direct";
+ String vhostName = getName();
+ String queueName = getName();
+
+ File config = writeConfigFile(vhostName, queueName, exchangeName, false, routingKeys);
+ VirtualHost vhost = createVirtualHost(vhostName, config);
+ assertNotNull("virtualhost should exist", vhost);
+
+ AMQQueue queue = vhost.getQueueRegistry().getQueue(queueName);
+ assertNotNull("queue should exist", queue);
+
+ Exchange defaultExch = vhost.getExchangeRegistry().getDefaultExchange();
+ assertTrue("queue should have been bound to default exchange with its name", defaultExch.isBound(queueName, queue));
+
+ Exchange exch = vhost.getExchangeRegistry().getExchange(exchangeName);
+ assertTrue("queue should have been bound to " + exchangeName + " with its name", exch.isBound(queueName, queue));
+
+ for(String key: routingKeys)
+ {
+ assertTrue("queue should have been bound to " + exchangeName + " with key " + key, exch.isBound(key, queue));
+ }
+ }
+
+
private VirtualHost createVirtualHost(String vhostName, File config) throws Exception
{
_configuration = new ServerConfiguration(new XMLConfiguration(config));
@@ -167,11 +189,11 @@ public class VirtualHostImplTest extends QpidTestCase
writer.write("<virtualhosts>");
writer.write(" <default>" + vhostName + "</default>");
writer.write(" <virtualhost>");
- writer.write(" <store>");
- writer.write(" <class>" + TestableMemoryMessageStore.class.getName() + "</class>");
- writer.write(" </store>");
writer.write(" <name>" + vhostName + "</name>");
writer.write(" <" + vhostName + ">");
+ writer.write(" <store>");
+ writer.write(" <factoryclass>" + MemoryMessageStoreFactory.class.getName() + "</factoryclass>");
+ writer.write(" </store>");
if(exchangeName != null && !dontDeclare)
{
writer.write(" <exchanges>");