summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2009-10-25 22:58:57 +0000
committerRobert Godfrey <rgodfrey@apache.org>2009-10-25 22:58:57 +0000
commitafcf8099695253651c73910a243fb29aa520b008 (patch)
treee514bc51797181c567500a8ddbfc20ea9b89b908
parentf315ac548e346ded9ed1d081db4118e703c362b4 (diff)
downloadqpid-python-afcf8099695253651c73910a243fb29aa520b008.tar.gz
Merged from java-broker-0-10 branch
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@829675 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java74
-rw-r--r--qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java2
-rw-r--r--qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java50
-rw-r--r--qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java43
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java672
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java55
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java201
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java79
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java148
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java11
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java67
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java47
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java91
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java16
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java42
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java37
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java29
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ExchangeInitialiser.java)12
-rwxr-xr-x[-rw-r--r--]qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeReferrer.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/ConsumerTagNotUniqueException.java)9
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java31
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java58
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java65
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java15
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java49
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java75
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java16
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java28
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java10
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java14
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java24
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java10
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java117
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java27
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java44
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java9
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java20
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java17
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java24
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java188
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java12
-rwxr-xr-x[-rw-r--r--]qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/util/ConcurrentLinkedQueueNoSize.java)26
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java16
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java25
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java20
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java16
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java213
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java40
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java15
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java1
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java14
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java38
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java25
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPConnectionActor.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java12
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages.properties33
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties198
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java19
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java14
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java329
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java51
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java)36
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java114
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java27
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java (renamed from qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessageHandle.java)24
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.java31
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java309
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java242
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageReference.java57
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java112
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java146
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java47
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java39
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java124
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java11
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java237
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java278
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java147
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java21
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java4
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java366
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java75
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngineFactory_0_10.java46
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java84
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java502
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java79
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java36
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java63
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java37
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java159
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java13
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/Filterable.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java157
-rwxr-xr-x[-rw-r--r--]qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NoConsumersException.java)58
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java283
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageMetaData.java92
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java22
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java23
-rwxr-xr-x[-rw-r--r--]qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/queue/UnauthorizedAccessException.java)32
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java51
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java230
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java9
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java902
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java69
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java68
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/TransientMessageData.java127
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java219
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java14
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java29
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java45
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java30
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java26
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java31
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/DenyAll.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java56
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java26
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java9
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java4
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java57
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java1069
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java116
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java162
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java41
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java251
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreRecoveryHandler.java33
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java36
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java2
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java80
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java38
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java92
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java33
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java26
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java93
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java86
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java57
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java23
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java196
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java658
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java64
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java120
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java398
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java1193
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java170
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java243
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java294
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java215
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java60
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/txn/StoreMessageOperation.java58
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java179
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java109
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnOp.java55
-rwxr-xr-x[-rw-r--r--]qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java644
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java340
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java608
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java10
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java31
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java20
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java43
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java5
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java20
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/ack/TxAckTest.java290
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java22
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java57
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java148
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java1
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java81
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java7
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java (renamed from qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java)325
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java2
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java2
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java10
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java3
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java32
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java13
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java59
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java74
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java28
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java80
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java71
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java14
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java95
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java71
-rwxr-xr-xqpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java92
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java260
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java6
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ACLManagerTest.java18
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java10
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java27
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/QueueDenier.java19
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java101
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java118
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java63
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestReferenceCounting.java46
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java113
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java62
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/txn/TxnBufferTest.java306
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java18
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java11
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java15
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java7
-rw-r--r--qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java4
-rw-r--r--qpid/java/build.deps2
-rw-r--r--qpid/java/client/build.xml3
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java28
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java14
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java2
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java25
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/configuration/ClientProperties.java14
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java10
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java38
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java13
-rw-r--r--qpid/java/common/Composite.tpl7
-rw-r--r--qpid/java/common/genutil.py1
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java2
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java63
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java26
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java4
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java5
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java5
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java48
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/Connection.java28
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/Method.java34
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java5
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java41
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/Session.java59
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java7
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java3
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java2
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java1
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java7
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java4
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java4
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java60
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java7
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java165
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java5
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java12
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java14
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java30
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java2
-rw-r--r--qpid/java/test-profiles/java-derby.testprofile4
-rwxr-xr-xqpid/java/test-profiles/java.0.10.testprofile8
-rw-r--r--qpid/java/test-profiles/java.testprofile4
266 files changed, 13270 insertions, 8185 deletions
diff --git a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java
index aa64fab6cd..637997a947 100644
--- a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java
+++ b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java
@@ -20,10 +20,8 @@
*/
package org.apache.qpid.extras.exchanges.diagnostic;
-import java.util.List;
-import java.util.Map;
import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Map;
import javax.management.JMException;
import javax.management.openmbean.OpenDataException;
@@ -34,27 +32,31 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.exchange.AbstractExchange;
-import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.junit.extensions.util.SizeOf;
import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
+import org.apache.log4j.Logger;
/**
- *
+ *
* This is a special diagnostic exchange type which doesn't actually do anything
* with messages. When it receives a message, it writes information about the
* current memory usage to the "memory" property of the message and places it on the
- * diagnosticqueue for retrieval
- *
+ * diagnosticqueue for retrieval
+ *
* @author Aidan Skinner
- *
+ *
*/
public class DiagnosticExchange extends AbstractExchange
{
-
+
+ private static final Logger _logger = Logger.getLogger(DiagnosticExchange.class);
+
+
public static final AMQShortString DIAGNOSTIC_EXCHANGE_CLASS = new AMQShortString("x-diagnostic");
public static final AMQShortString DIAGNOSTIC_EXCHANGE_NAME = new AMQShortString("diagnostic");
@@ -72,7 +74,7 @@ public class DiagnosticExchange extends AbstractExchange
/**
* Usual constructor.
- *
+ *
* @throws JMException
*/
@MBeanConstructor("Creates an MBean for AMQ Diagnostic exchange")
@@ -85,7 +87,7 @@ public class DiagnosticExchange extends AbstractExchange
/**
* Returns nothing, there can be no tabular data for this...
- *
+ *
* @throws OpenDataException
* @returns null
* @todo ... or can there? Could this actually return all the
@@ -99,7 +101,7 @@ public class DiagnosticExchange extends AbstractExchange
/**
* This exchange type doesn't support queues, so this method does
* nothing.
- *
+ *
* @param queueName
* the queue you'll fail to create
* @param binding
@@ -116,22 +118,20 @@ public class DiagnosticExchange extends AbstractExchange
/**
* Creates a new MBean instance
- *
+ *
* @return the newly created MBean
* @throws AMQException
* if something goes wrong
*/
- protected ExchangeMBean createMBean() throws AMQException
+ protected ExchangeMBean createMBean() throws JMException
{
- try
- {
- return new DiagnosticExchange.DiagnosticExchangeMBean();
- }
- catch (JMException ex)
- {
- // _logger.error("Exception occured in creating the direct exchange mbean", ex);
- throw new AMQException(null, "Exception occured in creating the direct exchange mbean", ex);
- }
+ return new DiagnosticExchange.DiagnosticExchangeMBean();
+
+ }
+
+ public Logger getLogger()
+ {
+ return _logger;
}
public AMQShortString getType()
@@ -141,7 +141,7 @@ public class DiagnosticExchange extends AbstractExchange
/**
* Does nothing.
- *
+ *
* @param routingKey
* pointless
* @param queue
@@ -156,9 +156,15 @@ public class DiagnosticExchange extends AbstractExchange
// No op
}
+ public void registerQueue(String routingKey, AMQQueue queue, Map<String, Object> args) throws AMQException
+ {
+ // No op
+ }
+
+
/**
* Does nothing.
- *
+ *
* @param routingKey
* pointless
* @param queue
@@ -193,27 +199,29 @@ public class DiagnosticExchange extends AbstractExchange
return false;
}
- public void route(IncomingMessage payload) throws AMQException
+ public ArrayList<AMQQueue> route(InboundMessage payload)
{
-
+
Long value = new Long(SizeOf.getUsedMemory());
AMQShortString key = new AMQShortString("memory");
-
- FieldTable headers = ((BasicContentHeaderProperties)payload.getContentHeaderBody().properties).getHeaders();
+
+ //TODO shouldn't modify messages... perhaps put a new message on the queue?
+/* FieldTable headers = ((BasicContentHeaderProperties)payload.getMessageHeader().properties).getHeaders();
headers.put(key, value);
- ((BasicContentHeaderProperties)payload.getContentHeaderBody().properties).setHeaders(headers);
+ ((BasicContentHeaderProperties)payload.getMessageHeader().properties).setHeaders(headers);*/
AMQQueue q = getQueueRegistry().getQueue(new AMQShortString("diagnosticqueue"));
ArrayList<AMQQueue> queues = new ArrayList<AMQQueue>();
queues.add(q);
- payload.enqueue(queues);
-
+ return queues;
+
}
-
+
public boolean isBound(AMQShortString routingKey, FieldTable arguments,
AMQQueue queue) {
// TODO Auto-generated method stub
return false;
}
+
}
diff --git a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java
index d96b4dc99e..b4d0d1aa0d 100644
--- a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java
+++ b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchangeType.java
@@ -31,7 +31,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
*/
public final class DiagnosticExchangeType implements ExchangeType<DiagnosticExchange>
{
-
+
public AMQShortString getName()
{
return DiagnosticExchange.DIAGNOSTIC_EXCHANGE_CLASS;
diff --git a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
index e43bd2ddc0..cb46b9c815 100644
--- a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
+++ b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
@@ -1,6 +1,6 @@
package org.apache.qpid.extras.exchanges.example;
/*
- *
+ *
* 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
@@ -8,29 +8,31 @@ package org.apache.qpid.extras.exchanges.example;
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
+ *
*/
import java.util.List;
import java.util.Map;
+import java.util.ArrayList;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.queue.IncomingMessage;
+import org.apache.qpid.server.exchange.ExchangeReferrer;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.message.InboundMessage;
public class TestExchange implements Exchange
{
@@ -63,6 +65,41 @@ public class TestExchange implements Exchange
return false;
}
+ public boolean isBound(String bindingKey, AMQQueue queue)
+ {
+ return false;
+ }
+
+ public boolean isBound(String bindingKey)
+ {
+ return false;
+ }
+
+ public Exchange getAlternateExchange()
+ {
+ return null;
+ }
+
+ public void setAlternateExchange(Exchange exchange)
+ {
+
+ }
+
+ public void removeReference(ExchangeReferrer exchange)
+ {
+
+ }
+
+ public void addReference(ExchangeReferrer exchange)
+ {
+
+ }
+
+ public boolean hasReferrers()
+ {
+ return false;
+ }
+
public void initialise(VirtualHost host, AMQShortString name, boolean durable, boolean autoDelete)
throws AMQException
{
@@ -102,8 +139,9 @@ public class TestExchange implements Exchange
{
}
- public void route(IncomingMessage message) throws AMQException
+ public ArrayList<AMQQueue> route(InboundMessage message)
{
+ return new ArrayList<AMQQueue>();
}
public int getTicket()
diff --git a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java
index 22833693ca..db02ca13ea 100644
--- a/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java
+++ b/qpid/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchangeType.java
@@ -40,7 +40,7 @@ public class TestExchangeType implements ExchangeType
return null;
}
- public Exchange newInstance(VirtualHost host, AMQShortString name, boolean durable,
+ public Exchange newInstance(VirtualHost host, AMQShortString name, boolean durable,
int token, boolean autoDelete)
throws AMQException
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
index 5cfa8066e5..08b3c08215 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
@@ -63,8 +63,9 @@ 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.MessageStore;
+import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.ManagementActor;
@@ -78,12 +79,12 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
private final QueueRegistry _queueRegistry;
private final ExchangeRegistry _exchangeRegistry;
private final ExchangeFactory _exchangeFactory;
- private final MessageStore _messageStore;
+ private final DurableConfigurationStore _durableConfig;
- private final VirtualHost.VirtualHostMBean _virtualHostMBean;
+ private final VirtualHostImpl.VirtualHostMBean _virtualHostMBean;
@MBeanConstructor("Creates the Broker Manager MBean")
- public AMQBrokerManagerMBean(VirtualHost.VirtualHostMBean virtualHostMBean) throws JMException
+ public AMQBrokerManagerMBean(VirtualHostImpl.VirtualHostMBean virtualHostMBean) throws JMException
{
super(ManagedBroker.class, ManagedBroker.TYPE, ManagedBroker.VERSION);
@@ -92,7 +93,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
_queueRegistry = virtualHost.getQueueRegistry();
_exchangeRegistry = virtualHost.getExchangeRegistry();
- _messageStore = virtualHost.getMessageStore();
+ _durableConfig = virtualHost.getDurableConfigurationStore();
_exchangeFactory = virtualHost.getExchangeFactory();
}
@@ -113,10 +114,10 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
{
exchangeTypes.add(ex.getName().toString());
}
-
+
return exchangeTypes.toArray(new String[0]);
}
-
+
/**
* Returns a list containing the names of the attributes available for the Queue mbeans.
* @since Qpid JMX API 1.3
@@ -129,12 +130,12 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
{
attributeList.add(attr);
}
-
+
Collections.sort(attributeList);
return attributeList;
}
-
+
/**
* Returns a List of Object Lists containing the requested attribute values (in the same sequence requested) for each queue in the virtualhost.
* If a particular attribute cant be found or raises an mbean/reflection exception whilst being gathered its value is substituted with the String "-".
@@ -147,22 +148,22 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
{
return new ArrayList<List<Object>>();
}
-
+
List<List<Object>> queueAttributesList = new ArrayList<List<Object>>(_queueRegistry.getQueues().size());
-
+
int attributesLength = attributes.length;
-
+
for(AMQQueue queue : _queueRegistry.getQueues())
{
AMQQueueMBean mbean = (AMQQueueMBean) queue.getManagedObject();
-
+
if(mbean == null)
{
continue;
}
-
+
List<Object> attributeValues = new ArrayList<Object>(attributesLength);
-
+
for(int i=0; i < attributesLength; i++)
{
try
@@ -174,13 +175,13 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
attributeValues.add(new String("-"));
}
}
-
+
queueAttributesList.add(attributeValues);
}
-
+
return queueAttributesList;
}
-
+
/**
* Creates new exchange and registers it with the registry.
*
@@ -277,7 +278,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
null);
if (queue.isDurable() && !queue.isAutoDelete())
{
- _messageStore.createQueue(queue);
+ _durableConfig.createQueue(queue);
}
_queueRegistry.registerQueue(queue);
@@ -319,7 +320,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
queue.delete();
if (queue.isDurable())
{
- _messageStore.removeQueue(queue);
+ _durableConfig.removeQueue(queue);
}
}
catch (AMQException ex)
@@ -330,7 +331,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
}
finally
{
- CurrentActor.remove();
+ CurrentActor.remove();
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
index 644a33db01..262bb2f226 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
@@ -20,24 +20,20 @@
*/
package org.apache.qpid.server;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.framing.*;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.exchange.NoRouteException;
import org.apache.qpid.server.flow.FlowCreditManager;
import org.apache.qpid.server.flow.Pre0_10CreditManager;
import org.apache.qpid.server.protocol.AMQProtocolSession;
@@ -47,23 +43,30 @@ import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.subscription.ClientDeliveryMethod;
import org.apache.qpid.server.subscription.RecordDeliveryMethod;
import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.txn.LocalTransactionalContext;
-import org.apache.qpid.server.txn.NonTransactionalContext;
-import org.apache.qpid.server.txn.TransactionalContext;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.txn.*;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.MessageMetaData;
+import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.LogMessage;
import org.apache.qpid.server.logging.messages.ChannelMessages;
import org.apache.qpid.server.logging.subjects.ChannelLogSubject;
import org.apache.qpid.server.logging.actors.AMQPChannelActor;
import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.output.ProtocolOutputConverter;
public class AMQChannel
{
public static final int DEFAULT_PREFETCH = 5000;
- private static final Logger _log = Logger.getLogger(AMQChannel.class);
+ private static final Logger _logger = Logger.getLogger(AMQChannel.class);
+
+ private static final boolean MSG_AUTH =
+ ApplicationRegistry.getInstance().getConfiguration().getMsgAuth();
+
private final int _channelId;
@@ -96,19 +99,12 @@ public class AMQChannel
private UnacknowledgedMessageMap _unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(DEFAULT_PREFETCH);
- private final AtomicBoolean _suspended = new AtomicBoolean(false);
+ // Set of messages being acknoweledged in the current transaction
+ private SortedSet<QueueEntry> _acknowledgedMessages = new TreeSet<QueueEntry>();
- private TransactionalContext _txnContext;
-
- /**
- * A context used by the message store enabling it to track context for a given channel even across thread
- * boundaries
- */
- private final StoreContext _storeContext;
-
- private final List<RequiredDeliveryException> _returnMessages = new LinkedList<RequiredDeliveryException>();
+ private final AtomicBoolean _suspended = new AtomicBoolean(false);
- private MessageHandleFactory _messageHandleFactory = new MessageHandleFactory();
+ private ServerTransaction _transaction;
// Why do we need this reference ? - ritchiem
private final AMQProtocolSession _session;
@@ -121,6 +117,12 @@ public class AMQChannel
private LogActor _actor;
private LogSubject _logSubject;
+ private volatile boolean _rollingBack;
+
+ private static final Runnable NULL_TASK = new Runnable() { public void run() {} };
+ private List<QueueEntry> _resendList = new ArrayList<QueueEntry>();
+ private static final
+ AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible.");
public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore)
throws AMQException
@@ -130,22 +132,19 @@ public class AMQChannel
_actor = new AMQPChannelActor(this, session.getLogActor().getRootMessageLogger());
_logSubject = new ChannelLogSubject(this);
-
- _actor.message(ChannelMessages.CHN_1001());
-
- _storeContext = new StoreContext("Session: " + session.getClientIdentifier() + "; channel: " + channelId);
+ _actor.message(ChannelMessages.CHN_1001());
_messageStore = messageStore;
// by default the session is non-transactional
- _txnContext = new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages);
+ _transaction = new AutoCommitTransaction(_messageStore);
}
/** Sets this channel to be part of a local transaction */
public void setLocalTransactional()
{
- _txnContext = new LocalTransactionalContext(this);
+ _transaction = new LocalTransaction(_messageStore);
}
public boolean isTransactional()
@@ -153,7 +152,7 @@ public class AMQChannel
// this does not look great but there should only be one "non-transactional"
// transactional context, while there could be several transactional ones in
// theory
- return !(_txnContext instanceof NonTransactionalContext);
+ return !(_transaction instanceof AutoCommitTransaction);
}
public int getChannelId()
@@ -164,8 +163,7 @@ public class AMQChannel
public void setPublishFrame(MessagePublishInfo info, final Exchange e) throws AMQException
{
- _currentMessage = new IncomingMessage(_messageStore.getNewMessageId(), info, _txnContext, _session);
- _currentMessage.setMessageStore(_messageStore);
+ _currentMessage = new IncomingMessage(info);
_currentMessage.setExchange(e);
}
@@ -178,18 +176,35 @@ public class AMQChannel
}
else
{
- if (_log.isDebugEnabled())
+ if (_logger.isDebugEnabled())
{
- _log.debug("Content header received on channel " + _channelId);
+ _logger.debug("Content header received on channel " + _channelId);
}
_currentMessage.setContentHeaderBody(contentHeaderBody);
_currentMessage.setExpiration();
+
+ MessageMetaData mmd = _currentMessage.headersReceived();
+ final StoredMessage<MessageMetaData> handle = _messageStore.addMessage(mmd);
+ _currentMessage.setStoredMessage(handle);
+
routeCurrentMessage();
- _currentMessage.routingComplete(_messageStore, _messageHandleFactory);
+
+ _transaction.addPostCommitAction(new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ }
+
+ public void onRollback()
+ {
+ handle.remove();
+ }
+ });
deliverCurrentMessageIfComplete();
@@ -204,21 +219,36 @@ public class AMQChannel
{
try
{
- _currentMessage.deliverToQueues();
- }
- catch (NoRouteException e)
- {
- _returnMessages.add(e);
- }
- catch(UnauthorizedAccessException ex)
- {
- _returnMessages.add(ex);
+
+ final ArrayList<AMQQueue> destinationQueues = _currentMessage.getDestinationQueues();
+
+ if(!checkMessageUserId(_currentMessage.getContentHeader()))
+ {
+ _transaction.addPostCommitAction(new WriteReturnAction(AMQConstant.ACCESS_REFUSED, "Access Refused", _currentMessage));
+ }
+ else
+ {
+ if(destinationQueues == null || _currentMessage.getDestinationQueues().isEmpty())
+ {
+ if (_currentMessage.isMandatory() || _currentMessage.isImmediate())
+ {
+ _transaction.addPostCommitAction(new WriteReturnAction(AMQConstant.NO_ROUTE, "No Route for message", _currentMessage));
+ }
+ else
+ {
+ _logger.warn("MESSAGE DISCARDED: No routes for message - " + createAMQMessage(_currentMessage));
+ }
+
+ }
+ else
+ {
+ _transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues));
+
+ }
+ }
}
finally
{
- // callback to allow the context to do any post message processing
- // primary use is to allow message return processing in the non-tx case
- _txnContext.messageProcessed(_session);
_currentMessage = null;
}
}
@@ -232,9 +262,9 @@ public class AMQChannel
throw new AMQException("Received content body without previously receiving a JmsPublishBody");
}
- if (_log.isDebugEnabled())
+ if (_logger.isDebugEnabled())
{
- _log.debug(debugIdentity() + "Content body received on channel " + _channelId);
+ _logger.debug(debugIdentity() + "Content body received on channel " + _channelId);
}
try
@@ -242,9 +272,10 @@ public class AMQChannel
// returns true iff the message was delivered (i.e. if all data was
// received
- _currentMessage.addContentBodyFrame(
- _session.getMethodRegistry().getProtocolVersionMethodConverter().convertToContentChunk(
- contentBody));
+ final ContentChunk contentChunk =
+ _session.getMethodRegistry().getProtocolVersionMethodConverter().convertToContentChunk(contentBody);
+
+ _currentMessage.addContentBodyFrame(contentChunk);
deliverCurrentMessageIfComplete();
}
@@ -259,15 +290,7 @@ public class AMQChannel
protected void routeCurrentMessage() throws AMQException
{
- try
- {
- _currentMessage.route();
- }
- catch (NoRouteException e)
- {
- //_currentMessage.incrementReference();
- _returnMessages.add(e);
- }
+ _currentMessage.route();
}
public long getNextDeliveryTag()
@@ -280,6 +303,12 @@ public class AMQChannel
return ++_consumerTag;
}
+
+ public Subscription getSubscription(AMQShortString subscription)
+ {
+ return _tag2SubscriptionMap.get(subscription);
+ }
+
/**
* Subscribe to a queue. We register all subscriptions in the channel so that if the channel is closed we can clean
* up all subscriptions, even if the client does not explicitly unsubscribe from all queues.
@@ -293,11 +322,10 @@ public class AMQChannel
* @param exclusive Flag requesting exclusive access to the queue
* @return the consumer tag. This is returned to the subscriber and used in subsequent unsubscribe requests
*
- * @throws ConsumerTagNotUniqueException if the tag is not unique
* @throws AMQException if something goes wrong
*/
public AMQShortString subscribeToQueue(AMQShortString tag, AMQQueue queue, boolean acks,
- FieldTable filters, boolean noLocal, boolean exclusive) throws AMQException, ConsumerTagNotUniqueException
+ FieldTable filters, boolean noLocal, boolean exclusive) throws AMQException
{
if (tag == null)
{
@@ -306,7 +334,7 @@ public class AMQChannel
if (_tag2SubscriptionMap.containsKey(tag))
{
- throw new ConsumerTagNotUniqueException();
+ throw new AMQException("Consumer already exists with same tag: " + tag);
}
Subscription subscription =
@@ -344,12 +372,12 @@ public class AMQChannel
Subscription sub = _tag2SubscriptionMap.remove(consumerTag);
if (sub != null)
{
- try
+ try
{
sub.getSendLock();
sub.getQueue().unregisterSubscription(sub);
}
- finally
+ finally
{
sub.releaseSendLock();
}
@@ -357,7 +385,7 @@ public class AMQChannel
}
else
{
- _log.warn("Attempt to unsubscribe consumer with tag '"+consumerTag+"' which is not registered.");
+ _logger.warn("Attempt to unsubscribe consumer with tag '"+consumerTag+"' which is not registered.");
}
return false;
}
@@ -369,18 +397,20 @@ public class AMQChannel
*/
public void close() throws AMQException
{
- _txnContext.rollback();
+ setClosing(true);
+
unsubscribeAllConsumers();
+ _transaction.rollback();
+
try
{
requeue();
}
catch (AMQException e)
{
- _log.error("Caught AMQException whilst attempting to reque:" + e);
+ _logger.error("Caught AMQException whilst attempting to reque:" + e);
}
- setClosing(true);
}
private void setClosing(boolean closing)
@@ -392,23 +422,23 @@ public class AMQChannel
private void unsubscribeAllConsumers() throws AMQException
{
- if (_log.isInfoEnabled())
+ if (_logger.isInfoEnabled())
{
if (!_tag2SubscriptionMap.isEmpty())
{
- _log.info("Unsubscribing all consumers on channel " + toString());
+ _logger.info("Unsubscribing all consumers on channel " + toString());
}
else
{
- _log.info("No consumers to unsubscribe on channel " + toString());
+ _logger.info("No consumers to unsubscribe on channel " + toString());
}
}
for (Map.Entry<AMQShortString, Subscription> me : _tag2SubscriptionMap.entrySet())
{
- if (_log.isInfoEnabled())
+ if (_logger.isInfoEnabled())
{
- _log.info("Unsubscribing consumer '" + me.getKey() + "' on channel " + toString());
+ _logger.info("Unsubscribing consumer '" + me.getKey() + "' on channel " + toString());
}
Subscription sub = me.getValue();
@@ -422,7 +452,7 @@ public class AMQChannel
{
sub.releaseSendLock();
}
-
+
}
_tag2SubscriptionMap.clear();
@@ -438,17 +468,17 @@ public class AMQChannel
*/
public void addUnacknowledgedMessage(QueueEntry entry, long deliveryTag, Subscription subscription)
{
- if (_log.isDebugEnabled())
+ if (_logger.isDebugEnabled())
{
if (entry.getQueue() == null)
{
- _log.debug("Adding unacked message with a null queue:" + entry.debugIdentity());
+ _logger.debug("Adding unacked message with a null queue:" + entry);
}
else
{
- if (_log.isDebugEnabled())
+ if (_logger.isDebugEnabled())
{
- _log.debug(debugIdentity() + " Adding unacked message(" + entry.getMessage().toString() + " DT:" + deliveryTag
+ _logger.debug(debugIdentity() + " Adding unacked message(" + entry.getMessage().toString() + " DT:" + deliveryTag
+ ") with a queue(" + entry.getQueue() + ") for " + subscription);
}
}
@@ -476,27 +506,13 @@ public class AMQChannel
// we must create a new map since all the messages will get a new delivery tag when they are redelivered
Collection<QueueEntry> messagesToBeDelivered = _unacknowledgedMessageMap.cancelAllMessages();
- // Deliver these messages out of the transaction as their delivery was never
- // part of the transaction only the receive.
- TransactionalContext deliveryContext = null;
-
if (!messagesToBeDelivered.isEmpty())
{
- if (_log.isInfoEnabled())
+ if (_logger.isInfoEnabled())
{
- _log.info("Requeuing " + messagesToBeDelivered.size() + " unacked messages. for " + toString());
+ _logger.info("Requeuing " + messagesToBeDelivered.size() + " unacked messages. for " + toString());
}
- if (!(_txnContext instanceof NonTransactionalContext))
- {
-
- deliveryContext =
- new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages);
- }
- else
- {
- deliveryContext = _txnContext;
- }
}
for (QueueEntry unacked : messagesToBeDelivered)
@@ -504,18 +520,15 @@ public class AMQChannel
if (!unacked.isQueueDeleted())
{
// Mark message redelivered
- unacked.getMessage().setRedelivered(true);
+ unacked.setRedelivered();
// Ensure message is released for redelivery
unacked.release();
- // Deliver Message
- deliveryContext.requeue(unacked);
-
}
else
{
- unacked.discard(_storeContext);
+ unacked.discard();
}
}
@@ -535,48 +548,27 @@ public class AMQChannel
if (unacked != null)
{
// Mark message redelivered
- unacked.getMessage().setRedelivered(true);
+ unacked.setRedelivered();
// Ensure message is released for redelivery
if (!unacked.isQueueDeleted())
{
- unacked.release();
- }
-
-
- // Deliver these messages out of the transaction as their delivery was never
- // part of the transaction only the receive.
- TransactionalContext deliveryContext;
- if (!(_txnContext instanceof NonTransactionalContext))
- {
- deliveryContext =
- new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages);
-
- }
- else
- {
- deliveryContext = _txnContext;
- }
+ // Ensure message is released for redelivery
+ unacked.release();
- if (!unacked.isQueueDeleted())
- {
- // Redeliver the messages to the front of the queue
- deliveryContext.requeue(unacked);
- // Deliver increments the message count but we have already deliverted this once so don't increment it again
- // this was because deliver did an increment changed this.
}
else
{
- _log.warn(System.identityHashCode(this) + " Requested requeue of message(" + unacked.getMessage().debugIdentity()
+ _logger.warn(System.identityHashCode(this) + " Requested requeue of message(" + unacked
+ "):" + deliveryTag + " but no queue defined and no DeadLetter queue so DROPPING message.");
- unacked.discard(_storeContext);
+ unacked.discard();
}
}
else
{
- _log.warn("Requested requeue of message:" + deliveryTag + " but no such delivery tag exists."
+ _logger.warn("Requested requeue of message:" + deliveryTag + " but no such delivery tag exists."
+ _unacknowledgedMessageMap.size());
}
@@ -597,28 +589,31 @@ public class AMQChannel
final Map<Long, QueueEntry> msgToRequeue = new LinkedHashMap<Long, QueueEntry>();
final Map<Long, QueueEntry> msgToResend = new LinkedHashMap<Long, QueueEntry>();
- if (_log.isDebugEnabled())
+ if (_logger.isDebugEnabled())
{
- _log.debug("unacked map Size:" + _unacknowledgedMessageMap.size());
+ _logger.debug("unacked map Size:" + _unacknowledgedMessageMap.size());
}
// Process the Unacked-Map.
// Marking messages who still have a consumer for to be resent
// and those that don't to be requeued.
- _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, requeue, _storeContext));
+ _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap,
+ msgToRequeue,
+ msgToResend,
+ requeue,
+ _messageStore));
// Process Messages to Resend
- if (_log.isDebugEnabled())
+ if (_logger.isDebugEnabled())
{
if (!msgToResend.isEmpty())
{
- _log.debug("Preparing (" + msgToResend.size() + ") message to resend.");
+ _logger.debug("Preparing (" + msgToResend.size() + ") message to resend.");
}
else
{
- _log.debug("No message to resend.");
+ _logger.debug("No message to resend.");
}
}
@@ -629,7 +624,7 @@ public class AMQChannel
- AMQMessage msg = message.getMessage();
+ ServerMessage msg = message.getMessage();
AMQQueue queue = message.getQueue();
// Our Java Client will always suspend the channel when resending!
@@ -638,7 +633,7 @@ public class AMQChannel
// i.e. The channel hasn't been server side suspended.
// if (isSuspended())
// {
- // _log.info("Channel is suspended so requeuing");
+ // _logger.info("Channel is suspended so requeuing");
// //move this message to requeue
// msgToRequeue.add(message);
// }
@@ -648,14 +643,14 @@ public class AMQChannel
// Without any details from the client about what has been processed we have to mark
// all messages in the unacked map as redelivered.
- msg.setRedelivered(true);
+ message.setRedelivered();
Subscription sub = message.getDeliveredSubscription();
if (sub != null)
{
-
- if(!queue.resend(message, sub))
+
+ if(!queue.resend(message,sub))
{
msgToRequeue.put(deliveryTag, message);
}
@@ -663,9 +658,9 @@ public class AMQChannel
else
{
- if (_log.isInfoEnabled())
+ if (_logger.isInfoEnabled())
{
- _log.info("DeliveredSubscription not recorded so just requeueing(" + message.toString()
+ _logger.info("DeliveredSubscription not recorded so just requeueing(" + message.toString()
+ ")to prevent loss");
}
// move this message to requeue
@@ -674,91 +669,28 @@ public class AMQChannel
} // for all messages
// } else !isSuspend
- if (_log.isInfoEnabled())
+ if (_logger.isInfoEnabled())
{
if (!msgToRequeue.isEmpty())
{
- _log.info("Preparing (" + msgToRequeue.size() + ") message to requeue to.");
+ _logger.info("Preparing (" + msgToRequeue.size() + ") message to requeue to.");
}
}
- // Deliver these messages out of the transaction as their delivery was never
- // part of the transaction only the receive.
- TransactionalContext deliveryContext;
- if (!(_txnContext instanceof NonTransactionalContext))
- {
-
- deliveryContext =
- new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages);
- }
- else
- {
- deliveryContext = _txnContext;
- }
-
// Process Messages to Requeue at the front of the queue
for (Map.Entry<Long, QueueEntry> entry : msgToRequeue.entrySet())
{
QueueEntry message = entry.getValue();
long deliveryTag = entry.getKey();
-
- message.release();
- message.setRedelivered(true);
+ _unacknowledgedMessageMap.remove(deliveryTag);
- deliveryContext.requeue(message);
+ message.setRedelivered();
+ message.release();
- _unacknowledgedMessageMap.remove(deliveryTag);
}
}
- /**
- * Callback indicating that a queue has been deleted. We must update the structure of unacknowledged messages to
- * remove the queue reference and also decrement any message reference counts, without actually removing the item
- * since we may get an ack for a delivery tag that was generated from the deleted queue.
- *
- * @param queue the queue that has been deleted
- *
- */
- /* public void queueDeleted(final AMQQueue queue)
- {
- try
- {
- _unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor()
- {
- public boolean callback(UnacknowledgedMessage message)
- {
- if (message.getQueue() == queue)
- {
- try
- {
- message.discard(_storeContext);
- message.setQueueDeleted(true);
-
- }
- catch (AMQException e)
- {
- _log.error(
- "Error decrementing ref count on message " + message.getMessage().getMessageId() + ": " + e, e);
- throw new RuntimeException(e);
- }
- }
-
- return false;
- }
-
- public void visitComplete()
- {
- }
- });
- }
- catch (AMQException e)
- {
- _log.error("Unexpected Error while handling deletion of queue", e);
- throw new RuntimeException(e);
- }
- }
-*/
/**
* Acknowledge one or more messages.
*
@@ -770,7 +702,17 @@ public class AMQChannel
*/
public void acknowledgeMessage(long deliveryTag, boolean multiple) throws AMQException
{
- _unacknowledgedMessageMap.acknowledgeMessage(deliveryTag, multiple, _txnContext);
+ Collection<QueueEntry> ackedMessages = getAckedMessages(deliveryTag, multiple);
+ _transaction.dequeue(ackedMessages, new MessageAcknowledgeAction(ackedMessages));
+ }
+
+ private Collection<QueueEntry> getAckedMessages(long deliveryTag, boolean multiple)
+ {
+
+ Map<Long, QueueEntry> ackedMessageMap = new LinkedHashMap<Long,QueueEntry>();
+ _unacknowledgedMessageMap.collect(deliveryTag, multiple, ackedMessageMap);
+ _unacknowledgedMessageMap.remove(ackedMessageMap);
+ return ackedMessageMap.values();
}
/**
@@ -854,7 +796,7 @@ public class AMQChannel
public boolean isSuspended()
{
- return _suspended.get();
+ return _suspended.get() || _closing || _session.isClosing();
}
public void commit() throws AMQException
@@ -864,57 +806,87 @@ public class AMQChannel
throw new AMQException("Fatal error: commit called on non-transactional channel");
}
- _txnContext.commit();
+ _transaction.commit();
+
}
public void rollback() throws AMQException
{
- _txnContext.rollback();
+ rollback(NULL_TASK);
}
- public String toString()
+ public void rollback(Runnable postRollbackTask) throws AMQException
{
- return "["+_session.toString()+":"+_channelId+"]";
- }
+ if (!isTransactional())
+ {
+ throw new AMQException("Fatal error: commit called on non-transactional channel");
+ }
- public void setDefaultQueue(AMQQueue queue)
- {
- _defaultQueue = queue;
- }
+ // stop all subscriptions
+ _rollingBack = true;
+ boolean requiresSuspend = _suspended.compareAndSet(false,true);
- public AMQQueue getDefaultQueue()
- {
- return _defaultQueue;
- }
+ // ensure all subscriptions have seen the change to the channel state
+ for(Subscription sub : _tag2SubscriptionMap.values())
+ {
+ sub.getSendLock();
+ sub.releaseSendLock();
+ }
- public StoreContext getStoreContext()
- {
- return _storeContext;
- }
+ try
+ {
+ _transaction.rollback();
+ }
+ finally
+ {
+ _rollingBack = false;
+ }
- public void processReturns() throws AMQException
- {
- if (!_returnMessages.isEmpty())
+ postRollbackTask.run();
+
+ for(QueueEntry entry : _resendList)
{
- for (RequiredDeliveryException bouncedMessage : _returnMessages)
+ Subscription sub = entry.getDeliveredSubscription();
+ if(sub == null || sub.isClosed())
{
- AMQMessage message = bouncedMessage.getAMQMessage();
- _session.getProtocolOutputConverter().writeReturn(message, _channelId, bouncedMessage.getReplyCode().getCode(),
- new AMQShortString(bouncedMessage.getMessage()));
+ entry.release();
+ }
+ else
+ {
+ sub.getQueue().resend(entry, sub);
+ }
+ }
+ _resendList.clear();
- message.decrementReference(_storeContext);
+ if(requiresSuspend)
+ {
+ _suspended.set(false);
+ for(Subscription sub : _tag2SubscriptionMap.values())
+ {
+ sub.getQueue().deliverAsync(sub);
}
- _returnMessages.clear();
}
+
+
}
+ public String toString()
+ {
+ return "["+_session.toString()+":"+_channelId+"]";
+ }
- public TransactionalContext getTransactionalContext()
+ public void setDefaultQueue(AMQQueue queue)
{
- return _txnContext;
+ _defaultQueue = queue;
}
+ public AMQQueue getDefaultQueue()
+ {
+ return _defaultQueue;
+ }
+
+
public boolean isClosing()
{
return _closing;
@@ -936,11 +908,6 @@ public class AMQChannel
_creditManager.setCreditLimits(prefetchSize, prefetchCount);
}
- public List<RequiredDeliveryException> getReturnMessages()
- {
- return _returnMessages;
- }
-
public MessageStore getMessageStore()
{
return _messageStore;
@@ -952,8 +919,10 @@ public class AMQChannel
public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag)
throws AMQException
{
- getProtocolSession().getProtocolOutputConverter().writeDeliver(entry.getMessage(), getChannelId(), deliveryTag, sub.getConsumerTag());
+ getProtocolSession().getProtocolOutputConverter().writeDeliver(entry, getChannelId(),
+ deliveryTag, sub.getConsumerTag());
}
+
};
public ClientDeliveryMethod getClientDeliveryMethod()
@@ -975,6 +944,213 @@ public class AMQChannel
return _recordDeliveryMethod;
}
+
+ private AMQMessage createAMQMessage(IncomingMessage incomingMessage)
+ throws AMQException
+ {
+
+ AMQMessage message = new AMQMessage(incomingMessage.getStoredMessage());
+
+ message.setExpiration(incomingMessage.getExpiration());
+ message.setClientIdentifier(_session);
+ return message;
+ }
+
+ private boolean checkMessageUserId(ContentHeaderBody header)
+ {
+ AMQShortString userID =
+ header.properties instanceof BasicContentHeaderProperties
+ ? ((BasicContentHeaderProperties) header.properties).getUserId()
+ : null;
+
+ return (!MSG_AUTH || _session.getPrincipal().getName().equals(userID == null? "" : userID.toString()));
+
+ }
+
+ private class MessageDeliveryAction implements ServerTransaction.Action
+ {
+ private IncomingMessage _incommingMessage;
+ private ArrayList<AMQQueue> _destinationQueues;
+
+ public MessageDeliveryAction(IncomingMessage currentMessage,
+ ArrayList<AMQQueue> destinationQueues)
+ {
+ _incommingMessage = currentMessage;
+ _destinationQueues = destinationQueues;
+ }
+
+ public void postCommit()
+ {
+ try
+ {
+ final boolean immediate = _incommingMessage.isImmediate();
+
+ final AMQMessage amqMessage = createAMQMessage(_incommingMessage);
+ MessageReference ref = amqMessage.newReference();
+
+ for(AMQQueue queue : _destinationQueues)
+ {
+
+ QueueEntry entry = queue.enqueue(amqMessage);
+ queue.checkCapacity(AMQChannel.this);
+
+
+ if(immediate && !entry.getDeliveredToConsumer() && entry.acquire())
+ {
+
+
+ ServerTransaction txn = new LocalTransaction(_messageStore);
+ Collection<QueueEntry> entries = new ArrayList<QueueEntry>(1);
+ entries.add(entry);
+ final AMQMessage message = (AMQMessage) entry.getMessage();
+ txn.dequeue(queue, entry.getMessage(),
+ new MessageAcknowledgeAction(entries)
+ {
+ @Override
+ public void postCommit()
+ {
+ try
+ {
+ final
+ ProtocolOutputConverter outputConverter =
+ _session.getProtocolOutputConverter();
+
+ outputConverter.writeReturn(message.getMessagePublishInfo(),
+ message.getContentHeaderBody(),
+ message,
+ _channelId,
+ AMQConstant.NO_CONSUMERS.getCode(),
+ IMMEDIATE_DELIVERY_REPLY_TEXT);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ super.postCommit();
+ }
+ }
+ );
+ txn.commit();
+
+
+
+
+ }
+
+ }
+ ref.release();
+ }
+ catch (AMQException e)
+ {
+ // TODO
+ throw new RuntimeException(e);
+ }
+
+
+
+
+
+ }
+
+ public void onRollback()
+ {
+ // Maybe keep track of entries that were created and then delete them here in case of failure
+ // to in memory enqueue
+ }
+ }
+
+ private class MessageAcknowledgeAction implements ServerTransaction.Action
+ {
+ private final Collection<QueueEntry> _ackedMessages;
+
+
+ public MessageAcknowledgeAction(Collection<QueueEntry> ackedMessages)
+ {
+ _ackedMessages = ackedMessages;
+ }
+
+ public void postCommit()
+ {
+ try
+ {
+ for(QueueEntry entry : _ackedMessages)
+ {
+ entry.discard();
+ }
+ }
+ finally
+ {
+ _acknowledgedMessages.clear();
+ }
+
+ }
+
+ public void onRollback()
+ {
+ // explicit rollbacks resend the message after the rollback-ok is sent
+ if(_rollingBack)
+ {
+ _resendList.addAll(_ackedMessages);
+ }
+ else
+ {
+ try
+ {
+ for(QueueEntry entry : _ackedMessages)
+ {
+ entry.release();
+ }
+ }
+ finally
+ {
+ _acknowledgedMessages.clear();
+ }
+ }
+
+ }
+ }
+
+ private class WriteReturnAction implements ServerTransaction.Action
+ {
+ private final AMQConstant _errorCode;
+ private final IncomingMessage _message;
+ private final String _description;
+
+ public WriteReturnAction(AMQConstant errorCode,
+ String description,
+ IncomingMessage message)
+ {
+ _errorCode = errorCode;
+ _message = message;
+ _description = description;
+ }
+
+ public void postCommit()
+ {
+ try
+ {
+ _session.getProtocolOutputConverter().writeReturn(_message.getMessagePublishInfo(),
+ _message.getContentHeader(),
+ _message,
+ _channelId,
+ _errorCode.getCode(),
+ new AMQShortString(_description));
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public void onRollback()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ }
+
+
public LogActor getLogActor()
{
return _actor;
@@ -993,7 +1169,7 @@ public class AMQChannel
}
}
- public void unblock(AMQQueue queue)
+ public void unblock(AMQQueue queue)
{
if(_blockingQueues.remove(queue))
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java
index 29494c4118..9da02e0600 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java
@@ -21,11 +21,11 @@
package org.apache.qpid.server;
import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
-import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.store.TransactionLog;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.AMQException;
import org.apache.log4j.Logger;
@@ -35,30 +35,29 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor
{
private static final Logger _log = Logger.getLogger(ExtractResendAndRequeue.class);
- private Map<Long, QueueEntry> _msgToRequeue;
- private Map<Long, QueueEntry> _msgToResend;
- private boolean _requeueIfUnabletoResend;
- private StoreContext _storeContext;
- private UnacknowledgedMessageMap _unacknowledgedMessageMap;
+ private final Map<Long, QueueEntry> _msgToRequeue;
+ private final Map<Long, QueueEntry> _msgToResend;
+ private final boolean _requeueIfUnabletoResend;
+ private final UnacknowledgedMessageMap _unacknowledgedMessageMap;
+ private final TransactionLog _transactionLog;
- public ExtractResendAndRequeue(UnacknowledgedMessageMap unacknowledgedMessageMap,
+ public ExtractResendAndRequeue(UnacknowledgedMessageMap unacknowledgedMessageMap,
Map<Long, QueueEntry> msgToRequeue,
Map<Long, QueueEntry> msgToResend,
boolean requeueIfUnabletoResend,
- StoreContext storeContext)
+ TransactionLog txnLog)
{
_unacknowledgedMessageMap = unacknowledgedMessageMap;
_msgToRequeue = msgToRequeue;
_msgToResend = msgToResend;
_requeueIfUnabletoResend = requeueIfUnabletoResend;
- _storeContext = storeContext;
+ _transactionLog = txnLog;
}
public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException
{
- AMQMessage msg = message.getMessage();
- msg.setRedelivered(true);
+ message.setRedelivered();
final Subscription subscription = message.getDeliveredSubscription();
if (subscription != null)
{
@@ -85,13 +84,14 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor
}
else
{
- message.discard(_storeContext);
+
+ dequeueEntry(message);
_log.info("No DeadLetter Queue and requeue not requested so dropping message:" + message);
}
}
else
{
- message.discard(_storeContext);
+ dequeueEntry(message);
_log.warn("Message.queue is null and no DeadLetter Queue so dropping message:" + message);
}
}
@@ -100,6 +100,31 @@ public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor
return false;
}
+
+ private void dequeueEntry(final QueueEntry node)
+ {
+ ServerTransaction txn = new AutoCommitTransaction(_transactionLog);
+ dequeueEntry(node, txn);
+ }
+
+ private void dequeueEntry(final QueueEntry node, ServerTransaction txn)
+ {
+ txn.dequeue(node.getQueue(), node.getMessage(),
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ node.discard();
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ }
+
public void visitComplete()
{
_unacknowledgedMessageMap.clear();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
index c45e794145..0a2bd6e8b0 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
@@ -26,6 +26,11 @@ import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Properties;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Collection;
+import java.util.Arrays;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
@@ -37,7 +42,8 @@ import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.QpidLog4JConfigurator;
-import org.apache.qpid.AMQException;
+import org.apache.qpid.transport.network.ConnectionBinding;
+import org.apache.qpid.transport.*;
import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.server.configuration.ServerConfiguration;
@@ -49,12 +55,16 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.management.LoggingManagementMBean;
import org.apache.qpid.server.logging.messages.BrokerMessages;
import org.apache.qpid.server.protocol.AMQProtocolEngineFactory;
+import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.transport.ServerConnection;
import org.apache.qpid.server.transport.QpidAcceptor;
import org.apache.qpid.ssl.SSLContextFactory;
import org.apache.qpid.transport.NetworkDriver;
import org.apache.qpid.transport.network.mina.MINANetworkDriver;
+import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory.VERSION;
/**
* Main entry point for AMQPD.
@@ -73,6 +83,7 @@ public class Main
private static final int IPV4_ADDRESS_LENGTH = 4;
private static final char IPV4_LITERAL_SEPARATOR = '.';
+ private static final Collection<VERSION> ALL_VERSIONS = Arrays.asList(VERSION.values());
protected static class InitException extends Exception
{
@@ -123,6 +134,24 @@ public class Main
OptionBuilder.withArgName("port").hasArg()
.withDescription("listen on the specified port. Overrides any value in the config file")
.withLongOpt("port").create("p");
+
+ Option exclude0_10 =
+ OptionBuilder.withArgName("exclude-0-10").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")
+ .withLongOpt("exclude-0-10").create();
+
+ Option exclude0_9 =
+ OptionBuilder.withArgName("exclude-0-9").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP0-9 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-0-9").create();
+
+
+ Option exclude0_8 =
+ OptionBuilder.withArgName("exclude-0-8").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP0-8 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-0-8").create();
+
+
Option mport =
OptionBuilder.withArgName("mport").hasArg()
.withDescription("listen on the specified management port. Overrides any value in the config file")
@@ -149,6 +178,9 @@ public class Main
options.addOption(logconfig);
options.addOption(logwatchconfig);
options.addOption(port);
+ options.addOption(exclude0_10);
+ options.addOption(exclude0_9);
+ options.addOption(exclude0_8);
options.addOption(mport);
options.addOption(bind);
}
@@ -239,7 +271,7 @@ public class Main
String logConfig = commandLine.getOptionValue("l");
String logWatchConfig = commandLine.getOptionValue("w", "0");
-
+
int logWatchTime = 0;
try
{
@@ -250,7 +282,7 @@ public class Main
System.err.println("Log watch configuration value of " + logWatchConfig + " is invalid. Must be "
+ "a non-negative integer. Using default of zero (no watching configured");
}
-
+
File logConfigFile;
if (logConfig != null)
{
@@ -276,9 +308,12 @@ public class Main
BrokerMessages.reload();
// AR.initialise() sets its own actor so we now need to set the actor
- // for the remainder of the startup
+ // for the remainder of the startup
CurrentActor.set(new BrokerActor(config.getRootMessageLogger()));
- try{
+ CurrentActor.setDefault(new BrokerActor(config.getRootMessageLogger()));
+
+ try
+ {
configureLoggingManagementMBean(logConfigFile, logWatchTime);
ConfigurationManagementMBean configMBean = new ConfigurationManagementMBean();
@@ -294,20 +329,35 @@ public class Main
_brokerLogger.info("Starting Qpid Broker " + QpidProperties.getReleaseVersion()
+ " build: " + QpidProperties.getBuildVersion());
- int port = serverConfig.getPort();
- String portStr = commandLine.getOptionValue("p");
- if (portStr != null)
+
+ String[] portStr = commandLine.getOptionValues("p");
+
+ Set<Integer> ports = new HashSet<Integer>();
+ Set<Integer> exclude_0_10 = new HashSet<Integer>();
+ Set<Integer> exclude_0_9 = new HashSet<Integer>();
+ Set<Integer> exclude_0_8 = new HashSet<Integer>();
+
+ if(portStr == null || portStr.length == 0)
{
- try
- {
- port = Integer.parseInt(portStr);
- }
- catch (NumberFormatException e)
- {
- throw new InitException("Invalid port: " + portStr, e);
- }
+
+ parsePortList(ports, serverConfig.getPorts());
+ parsePortList(exclude_0_10, serverConfig.getPortExclude010());
+ parsePortList(exclude_0_9, serverConfig.getPortExclude09());
+ parsePortList(exclude_0_8, serverConfig.getPortExclude08());
+
}
+ else
+ {
+ parsePortArray(ports, portStr);
+ parsePortArray(exclude_0_10, commandLine.getOptionValues("exclude-0-10"));
+ parsePortArray(exclude_0_9, commandLine.getOptionValues("exclude-0-9"));
+ parsePortArray(exclude_0_8, commandLine.getOptionValues("exclude-0-8"));
+
+ }
+
+
+
String bindAddr = commandLine.getOptionValue("b");
if (bindAddr == null)
@@ -315,42 +365,75 @@ public class Main
bindAddr = serverConfig.getBind();
}
InetAddress bindAddress = null;
+
+
+
if (bindAddr.equals("wildcard"))
{
- bindAddress = new InetSocketAddress(port).getAddress();
+ bindAddress = new InetSocketAddress(0).getAddress();
}
else
{
bindAddress = InetAddress.getByAddress(parseIP(bindAddr));
}
+ String hostName = bindAddress.getCanonicalHostName();
+
+
String keystorePath = serverConfig.getKeystorePath();
String keystorePassword = serverConfig.getKeystorePassword();
String certType = serverConfig.getCertType();
SSLContextFactory sslFactory = null;
- boolean isSsl = false;
-
+
if (!serverConfig.getSSLOnly())
{
- NetworkDriver driver = new MINANetworkDriver();
- driver.bind(port, new InetAddress[]{bindAddress}, new AMQProtocolEngineFactory(),
- serverConfig.getNetworkConfiguration(), null);
- ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port),
- new QpidAcceptor(driver,"TCP"));
- CurrentActor.get().message(BrokerMessages.BRK_1002("TCP", port));
+
+ for(int port : ports)
+ {
+
+ NetworkDriver driver = new MINANetworkDriver();
+
+ Set<VERSION> supported = new HashSet<VERSION>(ALL_VERSIONS);
+
+ if(exclude_0_10.contains(port))
+ {
+ supported.remove(VERSION.v0_10);
+ }
+ if(exclude_0_9.contains(port))
+ {
+ supported.remove(VERSION.v0_9);
+ }
+ if(exclude_0_8.contains(port))
+ {
+ supported.remove(VERSION.v0_8);
+ }
+
+ MultiVersionProtocolEngineFactory protocolEngineFactory =
+ new MultiVersionProtocolEngineFactory(hostName, supported);
+
+
+
+ driver.bind(port, new InetAddress[]{bindAddress}, protocolEngineFactory,
+ serverConfig.getNetworkConfiguration(), null);
+ ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port),
+ new QpidAcceptor(driver,"TCP"));
+ CurrentActor.get().message(BrokerMessages.BRK_1002("TCP", port));
+
+ }
+
}
-
+
if (serverConfig.getEnableSSL())
{
sslFactory = new SSLContextFactory(keystorePath, keystorePassword, certType);
NetworkDriver driver = new MINANetworkDriver();
- driver.bind(serverConfig.getSSLPort(), new InetAddress[]{bindAddress},
+ driver.bind(serverConfig.getSSLPort(), new InetAddress[]{bindAddress},
new AMQProtocolEngineFactory(), serverConfig.getNetworkConfiguration(), sslFactory);
- ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port),
+ ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, serverConfig.getSSLPort()),
new QpidAcceptor(driver,"TCP"));
CurrentActor.get().message(BrokerMessages.BRK_1002("TCP/SSL", serverConfig.getSSLPort()));
}
-
+
//fixme qpid.AMQP should be using qpidproperties to get value
_brokerLogger.info("Qpid Broker Ready :" + QpidProperties.getReleaseVersion()
+ " build: " + QpidProperties.getBuildVersion());
@@ -363,6 +446,47 @@ public class Main
// Startup is complete so remove the AR initialised Startup actor
CurrentActor.remove();
}
+
+
+
+ }
+
+ private void parsePortArray(Set<Integer> ports, String[] portStr)
+ throws InitException
+ {
+ if(portStr != null)
+ {
+ for(int i = 0; i < portStr.length; i++)
+ {
+ try
+ {
+ ports.add(Integer.parseInt(portStr[i]));
+ }
+ catch (NumberFormatException e)
+ {
+ throw new InitException("Invalid port: " + portStr[i], e);
+ }
+ }
+ }
+ }
+
+ private void parsePortList(Set<Integer> output, List input)
+ throws InitException
+ {
+ if(input != null)
+ {
+ for(Object port : input)
+ {
+ try
+ {
+ output.add(Integer.parseInt(String.valueOf(port)));
+ }
+ catch (NumberFormatException e)
+ {
+ throw new InitException("Invalid port: " + port, e);
+ }
+ }
+ }
}
/**
@@ -394,11 +518,11 @@ public class Main
{
System.setProperty("log4j.defaultInitOverride", "true");
}
-
+
//now that the override status is know, we can instantiate the Loggers
_logger = Logger.getLogger(Main.class);
_brokerLogger = Logger.getLogger("Qpid.Broker");
-
+
new Main(args);
}
@@ -434,7 +558,7 @@ public class Main
{
if (logConfigFile.exists() && logConfigFile.canRead())
{
- CurrentActor.get().message(BrokerMessages.BRK_1007(logConfigFile.getAbsolutePath()));
+ CurrentActor.get().message(BrokerMessages.BRK_1007(logConfigFile.getAbsolutePath()));
System.out.println("Configuring logger using configuration file " + logConfigFile.getAbsolutePath());
if (logWatchTime > 0)
{
@@ -466,7 +590,7 @@ public class Main
{
System.err.println("Logging configuration error: unable to read file " + logConfigFile.getAbsolutePath());
System.err.println("Using the fallback internal log4j.properties configuration");
-
+
InputStream propsFile = this.getClass().getResourceAsStream("/log4j.properties");
if(propsFile == null)
{
@@ -484,14 +608,7 @@ public class Main
private void configureLoggingManagementMBean(File logConfigFile, int logWatchTime) throws Exception
{
LoggingManagementMBean blm = new LoggingManagementMBean(logConfigFile.getPath(),logWatchTime);
-
- try
- {
- blm.register();
- }
- catch (AMQException e)
- {
- throw new InitException("Unable to initialise the Logging Management MBean: ", e);
- }
+
+ blm.register();
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java
deleted file mode 100644
index 3f1947d65a..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java
+++ /dev/null
@@ -1,79 +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;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.queue.AMQMessage;
-
-/**
- * Signals that a required delivery could not be made. This could be bacuse of the immediate flag being set and the
- * queue having no consumers, or the mandatory flag being set and the exchange having no valid bindings.
- *
- * <p/>The failed message is associated with this error condition, by taking a reference to it. This enables the
- * correct compensating action to be taken against the message, for example, bouncing it back to the sender.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represent failure to deliver a message that must be delivered.
- * <tr><td> Associate the failed message with the error condition. <td> {@link AMQMessage}
- * </table>
- */
-public abstract class RequiredDeliveryException extends AMQException
-{
- private AMQMessage _amqMessage;
-
- public RequiredDeliveryException(String message, AMQMessage payload)
- {
- super(message);
-
- setMessage(payload);
- }
-
-
- public RequiredDeliveryException(String message)
- {
- super(message);
- }
-
- public void setMessage(final AMQMessage payload)
- {
-
- // Increment the reference as this message is in the routing phase
- // and so will have the ref decremented as routing fails.
- // we need to keep this message around so we can return it in the
- // handler. So increment here.
- _amqMessage = payload.takeReference();
-
- }
-
- public AMQMessage getAMQMessage()
- {
- return _amqMessage;
- }
-
- public AMQConstant getErrorCode()
- {
- return getReplyCode();
- }
-
- public abstract AMQConstant getReplyCode();
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java
deleted file mode 100644
index db3a05eb52..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java
+++ /dev/null
@@ -1,148 +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.ack;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.ArrayList;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.txn.TxnOp;
-import org.apache.qpid.server.queue.QueueEntry;
-
-/**
- * A TxnOp implementation for handling accumulated acks
- */
-public class TxAck implements TxnOp
-{
- private final UnacknowledgedMessageMap _map;
- private final Map<Long, QueueEntry> _unacked = new HashMap<Long,QueueEntry>();
- private List<Long> _individual;
- private long _deliveryTag;
- private boolean _multiple;
-
- public TxAck(UnacknowledgedMessageMap map)
- {
- _map = map;
- }
-
- public void update(long deliveryTag, boolean multiple)
- {
- _unacked.clear();
- if (!multiple)
- {
- if(_individual == null)
- {
- _individual = new ArrayList<Long>();
- }
- //have acked a single message that is not part of
- //the previously acked region so record
- //individually
- _individual.add(deliveryTag);//_multiple && !multiple
- }
- else if (deliveryTag > _deliveryTag)
- {
- //have simply moved the last acked message on a
- //bit
- _deliveryTag = deliveryTag;
- _multiple = true;
- }
- }
-
- public void consolidate()
- {
- if(_unacked.isEmpty())
- {
- //lookup all the unacked messages that have been acked in this transaction
- if (_multiple)
- {
- //get all the unacked messages for the accumulated
- //multiple acks
- _map.collect(_deliveryTag, true, _unacked);
- }
- if(_individual != null)
- {
- //get any unacked messages for individual acks outside the
- //range covered by multiple acks
- for (long tag : _individual)
- {
- if(_deliveryTag < tag)
- {
- _map.collect(tag, false, _unacked);
- }
- }
- }
- }
- }
-
- public boolean checkPersistent() throws AMQException
- {
- consolidate();
- //if any of the messages in unacked are persistent the txn
- //buffer must be marked as persistent:
- for (QueueEntry msg : _unacked.values())
- {
- if (msg.getMessage().isPersistent())
- {
- return true;
- }
- }
- return false;
- }
-
- public void prepare(StoreContext storeContext) throws AMQException
- {
- //make persistent changes, i.e. dequeue and decrementReference
- for (QueueEntry msg : _unacked.values())
- {
- //Message has been ack so discard it. This will dequeue and decrement the reference.
- msg.discard(storeContext);
-
- }
- }
-
- public void undoPrepare()
- {
- //decrementReference is annoyingly untransactional (due to
- //in memory counter) so if we failed in prepare for full
- //txn, this op will have to compensate by fixing the count
- //in memory (persistent changes will be rolled back by store)
- for (QueueEntry msg : _unacked.values())
- {
- msg.getMessage().takeReference();
- }
- }
-
- public void commit(StoreContext storeContext)
- {
- //remove the unacked messages from the channels map
- _map.remove(_unacked);
- }
-
- public void rollback(StoreContext storeContext)
- {
- }
-}
-
-
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java
index c80a96f967..3bad73d86d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java
@@ -21,14 +21,12 @@
package org.apache.qpid.server.ack;
import java.util.Collection;
-import java.util.List;
import java.util.Set;
import java.util.Map;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.txn.TransactionalContext;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.store.StoreContext;
+
public interface UnacknowledgedMessageMap
{
@@ -50,18 +48,12 @@ public interface UnacknowledgedMessageMap
void collect(long deliveryTag, boolean multiple, Map<Long, QueueEntry> msgs);
- boolean contains(long deliveryTag) throws AMQException;
-
void remove(Map<Long,QueueEntry> msgs);
QueueEntry remove(long deliveryTag);
- public void drainTo(long deliveryTag, StoreContext storeContext) throws AMQException;
-
Collection<QueueEntry> cancelAllMessages();
- void acknowledgeMessage(long deliveryTag, boolean multiple, TransactionalContext txnContext) throws AMQException;
-
int size();
void clear();
@@ -75,7 +67,6 @@ public interface UnacknowledgedMessageMap
*/
Set<Long> getDeliveryTags();
- public long getUnacknowledgeBytes();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java
index c567387662..d920d97c1a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java
@@ -20,20 +20,13 @@
*/
package org.apache.qpid.server.ack;
-import org.apache.qpid.server.store.StoreContext;
import java.util.Collection;
-import java.util.Iterator;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.txn.TransactionalContext;
public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
{
@@ -61,19 +54,15 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
else
{
- msgs.put(deliveryTag, get(deliveryTag));
+ final QueueEntry entry = get(deliveryTag);
+ if(entry != null)
+ {
+ msgs.put(deliveryTag, entry);
+ }
}
}
- public boolean contains(long deliveryTag) throws AMQException
- {
- synchronized (_lock)
- {
- return _map.containsKey(deliveryTag);
- }
- }
-
public void remove(Map<Long,QueueEntry> msgs)
{
synchronized (_lock)
@@ -135,15 +124,6 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public void acknowledgeMessage(long deliveryTag, boolean multiple, TransactionalContext txnContext)
- throws AMQException
- {
- synchronized (_lock)
- {
- txnContext.acknowledgeMessage(deliveryTag, _lastDeliveryTag, multiple, this);
- }
- }
-
public int size()
{
synchronized (_lock)
@@ -161,39 +141,6 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public void drainTo(long deliveryTag, StoreContext storeContext) throws AMQException
-
- {
- synchronized (_lock)
- {
- Iterator<Map.Entry<Long, QueueEntry>> it = _map.entrySet().iterator();
- while (it.hasNext())
- {
- Map.Entry<Long, QueueEntry> unacked = it.next();
-
- if (unacked.getKey() > deliveryTag)
- {
- //This should not occur now.
- throw new AMQException("UnacknowledgedMessageMap is out of order:" + unacked.getKey() +
- " When deliveryTag is:" + deliveryTag + "ES:" + _map.entrySet().toString());
- }
-
- //Message has been ack so discard it. This will dequeue and decrement the reference.
- unacked.getValue().discard(storeContext);
-
- it.remove();
-
- _unackedSize -= unacked.getValue().getMessage().getSize();
-
-
- if (unacked.getKey() == deliveryTag)
- {
- break;
- }
- }
- }
- }
-
public QueueEntry get(long key)
{
synchronized (_lock)
@@ -225,8 +172,4 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public long getUnacknowledgeBytes()
- {
- return _unackedSize;
- }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
index 641b44bb18..7bf28c7560 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
@@ -14,8 +14,8 @@
* "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.
- *
+ * under the License.
+ *
*/
package org.apache.qpid.server.configuration;
@@ -26,6 +26,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Locale;
+import java.util.Collections;
import java.util.Map.Entry;
import org.apache.commons.configuration.CompositeConfiguration;
@@ -124,7 +125,7 @@ public class ServerConfiguration implements SignalHandler
}
catch (IllegalArgumentException e)
{
- // We're on something that doesn't handle SIGHUP, how sad, Windows.
+ // We're on something that doesn't handle SIGHUP, how sad, Windows.
}
}
@@ -221,7 +222,7 @@ public class ServerConfiguration implements SignalHandler
String localeString = getConfig().getString(ADVANCED_LOCALE);
// Expecting locale of format langauge_country_variant
- // If the configuration does not have a defined locale use the JVM default
+ // If the configuration does not have a defined locale use the JVM default
if (localeString == null)
{
return Locale.getDefault();
@@ -524,11 +525,27 @@ public class ServerConfiguration implements SignalHandler
return getConfig().getInt("connector.processors", 4);
}
- public int getPort()
+ public List getPorts()
+ {
+ return getConfig().getList("connector.port", Collections.singletonList(DEFAULT_PORT));
+ }
+
+ public List getPortExclude010()
+ {
+ return getConfig().getList("connector.non010port", Collections.EMPTY_LIST);
+ }
+
+ public List getPortExclude09()
+ {
+ return getConfig().getList("connector.non09port", Collections.EMPTY_LIST);
+ }
+
+ public List getPortExclude08()
{
- return getConfig().getInt("connector.port", DEFAULT_PORT);
+ return getConfig().getList("connector.non08port", Collections.EMPTY_LIST);
}
+
public String getBind()
{
return getConfig().getString("connector.bind", "wildcard");
@@ -625,48 +642,48 @@ public class ServerConfiguration implements SignalHandler
{
return new NetworkDriverConfiguration()
{
-
+
public Integer getTrafficClass()
{
return null;
}
-
+
public Boolean getTcpNoDelay()
{
// Can't call parent getTcpNoDelay since it just calls this one
return getConfig().getBoolean("connector.tcpNoDelay", true);
}
-
+
public Integer getSoTimeout()
{
return null;
}
-
+
public Integer getSoLinger()
{
return null;
}
-
+
public Integer getSendBufferSize()
{
return getBufferWriteLimit();
}
-
+
public Boolean getReuseAddress()
{
return null;
}
-
+
public Integer getReceiveBufferSize()
{
return getBufferReadLimit();
}
-
+
public Boolean getOOBInline()
{
return null;
}
-
+
public Boolean getKeepAlive()
{
return null;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index bb70ce556b..7983c62443 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,6 +23,7 @@ package org.apache.qpid.server.exchange;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
+import javax.management.JMException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.TabularType;
@@ -39,18 +40,23 @@ import org.apache.qpid.server.management.Managable;
import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.management.ManagedObjectRegistry;
import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.logging.subjects.ExchangeLogSubject;
import org.apache.qpid.server.logging.LogSubject;
+import org.apache.log4j.Logger;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
public abstract class AbstractExchange implements Exchange, Managable
{
private AMQShortString _name;
-
+ private Exchange _alternateExchange;
protected boolean _durable;
protected String _exchangeType;
@@ -67,6 +73,7 @@ public abstract class AbstractExchange implements Exchange, Managable
//The logSubject for ths exchange
private LogSubject _logSubject;
+ private Map<ExchangeReferrer,Object> _referrers = new ConcurrentHashMap<ExchangeReferrer,Object>();
/**
* Abstract MBean class. This has some of the methods implemented from
@@ -80,14 +87,14 @@ public abstract class AbstractExchange implements Exchange, Managable
protected CompositeType _bindingDataType;
protected TabularType _bindinglistDataType;
protected TabularDataSupport _bindingList;
-
+
public ExchangeMBean() throws NotCompliantMBeanException
{
super(ManagedExchange.class, ManagedExchange.TYPE, ManagedExchange.VERSION);
}
protected void init() throws OpenDataException
- {
+ {
_bindingItemTypes = new OpenType[2];
_bindingItemTypes[0] = SimpleType.STRING;
_bindingItemTypes[1] = new ArrayType(1, SimpleType.STRING);
@@ -156,23 +163,33 @@ public abstract class AbstractExchange implements Exchange, Managable
* called during initialisation (template method pattern).
* @return the MBean
*/
- protected abstract ExchangeMBean createMBean() throws AMQException;
+ protected abstract ExchangeMBean createMBean() throws JMException;
- public void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) throws AMQException
+ public void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
+ throws AMQException
{
_virtualHost = host;
_name = name;
_durable = durable;
_autoDelete = autoDelete;
_ticket = ticket;
- _exchangeMbean = createMBean();
- _exchangeMbean.register();
+ try
+ {
+ _exchangeMbean = createMBean();
+ _exchangeMbean.register();
+ }
+ catch (JMException e)
+ {
+ getLogger().error(e);
+ }
_logSubject = new ExchangeLogSubject(this, this.getVirtualHost());
// Log Exchange creation
CurrentActor.get().message(ExchangeMessages.EXH_1001(String.valueOf(getType()), String.valueOf(name), durable));
}
+ public abstract Logger getLogger();
+
public boolean isDurable()
{
return _durable;
@@ -194,9 +211,13 @@ public abstract class AbstractExchange implements Exchange, Managable
{
_exchangeMbean.unregister();
}
+ if(_alternateExchange != null)
+ {
+ _alternateExchange.removeReference(this);
+ }
CurrentActor.get().message(_logSubject, ExchangeMessages.EXH_1002());
- }
+ }
public String toString()
{
@@ -217,4 +238,54 @@ public abstract class AbstractExchange implements Exchange, Managable
{
return getVirtualHost().getQueueRegistry();
}
+
+ public boolean isBound(String bindingKey, Map<String,Object> arguments, AMQQueue queue)
+ {
+ return isBound(new AMQShortString(bindingKey), queue);
+ }
+
+
+ public boolean isBound(String bindingKey, AMQQueue queue)
+ {
+ return isBound(new AMQShortString(bindingKey), queue);
+ }
+
+ public boolean isBound(String bindingKey)
+ {
+ return isBound(new AMQShortString(bindingKey));
+ }
+
+ public Exchange getAlternateExchange()
+ {
+ return _alternateExchange;
+ }
+
+ public void setAlternateExchange(Exchange exchange)
+ {
+ if(_alternateExchange != null)
+ {
+ _alternateExchange.removeReference(this);
+ }
+ if(exchange != null)
+ {
+ exchange.addReference(this);
+ }
+ _alternateExchange = exchange;
+
+ }
+
+ public void removeReference(ExchangeReferrer exchange)
+ {
+ _referrers.remove(exchange);
+ }
+
+ public void addReference(ExchangeReferrer exchange)
+ {
+ _referrers.put(exchange, Boolean.TRUE);
+ }
+
+ public boolean hasReferrers()
+ {
+ return !_referrers.isEmpty();
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java
index 620799a81f..6b0cf89b95 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java
@@ -59,6 +59,20 @@ public class DefaultExchangeFactory implements ExchangeFactory
return _exchangeClassMap.values();
}
+ public Exchange createExchange(String exchange, String type, boolean durable, boolean autoDelete)
+ throws AMQException
+ {
+ ExchangeType<? extends Exchange> exchType = _exchangeClassMap.get(new AMQShortString(type));
+ if (exchType == null)
+ {
+
+ throw new AMQUnknownExchangeType("Unknown exchange type: " + type,null);
+ }
+ Exchange e = exchType.newInstance(_host, (new AMQShortString(exchange)).intern(), durable, 0, autoDelete);
+ return e;
+
+ }
+
public Exchange createExchange(AMQShortString exchange, AMQShortString type, boolean durable, boolean autoDelete,
int ticket)
throws AMQException
@@ -92,7 +106,7 @@ public class DefaultExchangeFactory implements ExchangeFactory
return;
}
Class<? extends ExchangeType> exchangeTypeClass = exchangeType.getClass();
- ExchangeType type = exchangeTypeClass.newInstance();
+ ExchangeType<? extends ExchangeType> type = exchangeTypeClass.newInstance();
registerExchangeType(type);
}
catch (ClassCastException classCastEx)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
index 0ab8208d88..2a8a87be7d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,10 +23,9 @@ 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.protocol.ExchangeInitialiser;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.exchange.ExchangeInitialiser;
import org.apache.qpid.server.queue.IncomingMessage;
-import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Collection;
@@ -41,6 +40,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
* Maps from exchange name to exchange instance
*/
private ConcurrentMap<AMQShortString, Exchange> _exchangeMap = new ConcurrentHashMap<AMQShortString, Exchange>();
+ private ConcurrentMap<String, Exchange> _exchangeMapStr = new ConcurrentHashMap<String, Exchange>();
private Exchange _defaultExchange;
private VirtualHost _host;
@@ -57,17 +57,20 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
new ExchangeInitialiser().initialise(_host.getExchangeFactory(), this);
}
- public MessageStore getMessageStore()
+
+
+ public DurableConfigurationStore getDurableConfigurationStore()
{
- return _host.getMessageStore();
+ return _host.getDurableConfigurationStore();
}
public void registerExchange(Exchange exchange) throws AMQException
{
_exchangeMap.put(exchange.getName(), exchange);
+ _exchangeMapStr.put(exchange.getName().toString(), exchange);
if (exchange.isDurable())
{
- getMessageStore().createExchange(exchange);
+ getDurableConfigurationStore().createExchange(exchange);
}
}
@@ -90,11 +93,12 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
{
// TODO: check inUse argument
Exchange e = _exchangeMap.remove(name);
+ _exchangeMapStr.remove(name.toString());
if (e != null)
{
if (e.isDurable())
{
- getMessageStore().removeExchange(e);
+ getDurableConfigurationStore().removeExchange(e);
}
e.close();
}
@@ -104,6 +108,11 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
}
}
+ public void unregisterExchange(String name, boolean inUse) throws AMQException
+ {
+ unregisterExchange(new AMQShortString(name), inUse);
+ }
+
public Exchange getExchange(AMQShortString name)
{
if ((name == null) || name.length() == 0)
@@ -117,6 +126,19 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
}
+ public Exchange getExchange(String name)
+ {
+ if ((name == null) || name.length() == 0)
+ {
+ return getDefaultExchange();
+ }
+ else
+ {
+ return _exchangeMapStr.get(name);
+ }
+ }
+
+
/**
* Routes content through exchanges, delivering it to 1 or more queues.
* @param payload
@@ -134,6 +156,6 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
{
throw new AMQException("Exchange '" + exchange + "' does not exist");
}
- exch.route(payload);
+ payload.enqueue(exch.route(payload));
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
index 3567cdff85..4788f96d6c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
@@ -40,9 +40,9 @@ import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.ManagementActor;
@@ -149,17 +149,14 @@ public class DirectExchange extends AbstractExchange
}// End of MBean class
- protected ExchangeMBean createMBean() throws AMQException
+ protected ExchangeMBean createMBean() throws JMException
{
- try
- {
- return new DirectExchangeMBean();
- }
- catch (JMException ex)
- {
- _logger.error("Exception occured in creating the direct exchange mbean", ex);
- throw new AMQException("Exception occured in creating the direct exchange mbean", ex);
- }
+ return new DirectExchangeMBean();
+ }
+
+ public Logger getLogger()
+ {
+ return _logger;
}
public AMQShortString getType()
@@ -167,8 +164,18 @@ public class DirectExchange extends AbstractExchange
return ExchangeDefaults.DIRECT_EXCHANGE_CLASS;
}
+ public void registerQueue(String routingKey, AMQQueue queue, Map<String,Object> args) throws AMQException
+ {
+ registerQueue(new AMQShortString(routingKey), queue);
+ }
+
public void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
{
+ registerQueue(routingKey, queue);
+ }
+
+ private void registerQueue(AMQShortString routingKey, AMQQueue queue) throws AMQException
+ {
assert queue != null;
assert routingKey != null;
if (!_index.add(routingKey, queue))
@@ -199,10 +206,11 @@ public class DirectExchange extends AbstractExchange
}
}
- public void route(IncomingMessage payload) throws AMQException
+ public ArrayList<AMQQueue> route(InboundMessage payload)
{
- final AMQShortString routingKey = payload.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : payload.getRoutingKey();
+ final String routingKey = payload.getRoutingKey();
+
final ArrayList<AMQQueue> queues = (routingKey == null) ? null : _index.get(routingKey);
@@ -211,7 +219,8 @@ public class DirectExchange extends AbstractExchange
_logger.debug("Publishing message to queue " + queues);
}
- payload.enqueue(queues);
+ return queues;
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
index 06209c5458..4bbdeaef1c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
@@ -24,20 +24,21 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.message.InboundMessage;
-import java.util.List;
-import java.util.Map;
+import javax.management.JMException;
+import java.util.ArrayList;
-public interface Exchange
+public interface Exchange extends ExchangeReferrer
{
AMQShortString getName();
AMQShortString getType();
- void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) throws AMQException;
+ void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
+ throws AMQException, JMException;
boolean isDurable();
@@ -52,9 +53,11 @@ public interface Exchange
void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException;
+
+
void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException;
- void route(IncomingMessage message) throws AMQException;
+ ArrayList<AMQQueue> route(InboundMessage message);
/**
@@ -93,6 +96,18 @@ public interface Exchange
*/
boolean hasBindings();
-
+ boolean isBound(String bindingKey, AMQQueue queue);
+
+ boolean isBound(String bindingKey);
+
+ Exchange getAlternateExchange();
+
+ void setAlternateExchange(Exchange exchange);
+
+ void removeReference(ExchangeReferrer exchange);
+
+ void addReference(ExchangeReferrer exchange);
+
+ boolean hasReferrers();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java
index 2f76d41228..b91bf559f1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java
@@ -38,4 +38,6 @@ public interface ExchangeFactory
void initialise(VirtualHostConfiguration hostConfig);
Collection<ExchangeType<? extends Exchange>> getRegisteredTypes();
+
+ Exchange createExchange(String exchange, String type, boolean durable, boolean autoDelete) throws AMQException;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ExchangeInitialiser.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java
index 2abcecb6de..59fe94ddc0 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ExchangeInitialiser.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,15 +18,11 @@
* under the License.
*
*/
-package org.apache.qpid.server.protocol;
+package org.apache.qpid.server.exchange;
import org.apache.qpid.AMQException;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
-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.exchange.ExchangeType;
public class ExchangeInitialiser
{
@@ -35,7 +31,7 @@ public class ExchangeInitialiser
{
define (registry, factory, type.getDefaultExchangeName(), type.getName());
}
-
+
define(registry, factory, ExchangeDefaults.DEFAULT_EXCHANGE_NAME, ExchangeDefaults.DIRECT_EXCHANGE_CLASS);
registry.setDefaultExchange(registry.getExchange(ExchangeDefaults.DEFAULT_EXCHANGE_NAME));
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ConsumerTagNotUniqueException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeReferrer.java
index 9a98af5689..e41d63d97d 100644..100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ConsumerTagNotUniqueException.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeReferrer.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,8 +18,9 @@
* under the License.
*
*/
-package org.apache.qpid.server;
-public class ConsumerTagNotUniqueException extends Exception
+package org.apache.qpid.server.exchange;
+
+public interface ExchangeReferrer
{
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
index fe3b19e74e..e34ef29d9b 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
@@ -48,4 +48,8 @@ public interface ExchangeRegistry extends MessageRouter
Collection<AMQShortString> getExchangeNames();
void initialise() throws AMQException;
+
+ Exchange getExchange(String exchangeName);
+
+ void unregisterExchange(String exchange, boolean ifUnused) throws ExchangeInUseException, AMQException;;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
index 7fa438587c..00f8ebd856 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
@@ -28,9 +28,9 @@ import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.ManagementActor;
@@ -62,7 +62,7 @@ public class FanoutExchange extends AbstractExchange
private final class FanoutExchangeMBean extends ExchangeMBean
{
private static final String BINDING_KEY_SUBSTITUTE = "*";
-
+
@MBeanConstructor("Creates an MBean for AMQ fanout exchange")
public FanoutExchangeMBean() throws JMException
{
@@ -75,7 +75,7 @@ public class FanoutExchange extends AbstractExchange
{
_bindingList = new TabularDataSupport(_bindinglistDataType);
-
+
if(_queues.isEmpty())
{
return _bindingList;
@@ -88,7 +88,7 @@ public class FanoutExchange extends AbstractExchange
String queueName = queue.getName().toString();
queueNames.add(queueName);
}
-
+
Object[] bindingItemValues = {BINDING_KEY_SUBSTITUTE, queueNames.toArray(new String[0])};
CompositeData bindingData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues);
_bindingList.put(bindingData);
@@ -121,17 +121,14 @@ public class FanoutExchange extends AbstractExchange
} // End of MBean class
- protected ExchangeMBean createMBean() throws AMQException
+ protected ExchangeMBean createMBean() throws JMException
{
- try
- {
- return new FanoutExchange.FanoutExchangeMBean();
- }
- catch (JMException ex)
- {
- _logger.error("Exception occured in creating the direct exchange mbean", ex);
- throw new AMQException("Exception occured in creating the direct exchange mbean", ex);
- }
+ return new FanoutExchange.FanoutExchangeMBean();
+ }
+
+ public Logger getLogger()
+ {
+ return _logger;
}
public static final ExchangeType<FanoutExchange> TYPE = new ExchangeType<FanoutExchange>()
@@ -199,16 +196,16 @@ public class FanoutExchange extends AbstractExchange
}
}
- public void route(IncomingMessage payload) throws AMQException
+ public ArrayList<AMQQueue> route(InboundMessage payload)
{
-
+
if (_logger.isDebugEnabled())
{
_logger.debug("Publishing message to queue " + _queues);
}
- payload.enqueue(new ArrayList(_queues));
+ return new ArrayList(_queues);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
index 2b7df4361a..35c4a8f9b2 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -28,6 +28,7 @@ import java.util.Set;
import org.apache.log4j.Logger;
import org.apache.qpid.framing.AMQTypedValue;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.message.AMQMessageHeader;
/**
* Defines binding and matching based on a set of headers.
@@ -87,7 +88,7 @@ class HeadersBinding
* Creates a binding for a set of mappings. Those mappings whose value is
* null or the empty string are assumed only to be required headers, with
* no constraint on the value. Those with a non-null value are assumed to
- * define a required match of value.
+ * define a required match of value.
* @param mappings the defined mappings this binding should use
*/
@@ -139,7 +140,7 @@ class HeadersBinding
* @return true if the headers define any required keys and match any required
* values
*/
- public boolean matches(FieldTable headers)
+ public boolean matches(AMQMessageHeader headers)
{
if(headers == null)
{
@@ -151,13 +152,13 @@ class HeadersBinding
}
}
- private boolean and(FieldTable headers)
+ private boolean and(AMQMessageHeader headers)
{
- if(headers.keys().containsAll(required))
+ if(headers.containsHeaders(required))
{
for(Map.Entry<String, Object> e : matches.entrySet())
{
- if(!e.getValue().equals(headers.getObject(e.getKey())))
+ if(!e.getValue().equals(headers.getHeader(e.getKey())))
{
return false;
}
@@ -171,17 +172,50 @@ class HeadersBinding
}
- private boolean or(final FieldTable headers)
+ private boolean or(final AMQMessageHeader headers)
{
- if(required.isEmpty() || !(Boolean) headers.processOverElements(new RequiredOrProcessor()))
+ if(required.isEmpty())
{
- return ((!matches.isEmpty()) && (Boolean) headers.processOverElements(new MatchesOrProcessor()))
- || (required.isEmpty() && matches.isEmpty());
+ return matches.isEmpty() || passesMatchesOr(headers);
}
else
{
- return true;
+ if(!passesRequiredOr(headers))
+ {
+ return !matches.isEmpty() && passesMatchesOr(headers);
+ }
+ else
+ {
+ return true;
+ }
+
+ }
+ }
+
+ private boolean passesMatchesOr(AMQMessageHeader headers)
+ {
+ for(Map.Entry<String,Object> entry : matches.entrySet())
+ {
+ if(headers.containsHeader(entry.getKey())
+ && ((entry.getValue() == null && headers.getHeader(entry.getKey()) == null)
+ || (entry.getValue().equals(headers.getHeader(entry.getKey())))))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean passesRequiredOr(AMQMessageHeader headers)
+ {
+ for(String name : required)
+ {
+ if(headers.containsHeader(name))
+ {
+ return true;
+ }
}
+ return false;
}
private void processSpecial(String key, Object value)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
index c5f5cd05e1..5677cc4510 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
@@ -31,9 +31,10 @@ import org.apache.qpid.framing.AMQTypedValue;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.message.InboundMessage;
+import org.apache.qpid.server.message.AMQMessageHeader;
import javax.management.JMException;
import javax.management.openmbean.ArrayType;
@@ -50,8 +51,8 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ConcurrentHashMap;
/**
* An exchange that binds queues based on a set of required headers and header values
@@ -82,6 +83,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
public class HeadersExchange extends AbstractExchange
{
+
private static final Logger _logger = Logger.getLogger(HeadersExchange.class);
public static final ExchangeType<HeadersExchange> TYPE = new ExchangeType<HeadersExchange>()
@@ -101,6 +103,7 @@ public class HeadersExchange extends AbstractExchange
boolean autoDelete) throws AMQException
{
HeadersExchange exch = new HeadersExchange();
+
exch.initialise(host, name, durable, ticket, autoDelete);
return exch;
}
@@ -114,6 +117,7 @@ public class HeadersExchange extends AbstractExchange
private final List<Registration> _bindings = new CopyOnWriteArrayList<Registration>();
+ private Map<AMQShortString, Registration> _bindingByKey = new ConcurrentHashMap<AMQShortString, Registration>();
/**
* HeadersExchangeMBean class implements the management interface for the
@@ -208,7 +212,7 @@ public class HeadersExchange extends AbstractExchange
{
throw new JMException("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\" ");
}
-
+
if(keyAndValue.length ==1)
{
//no value was given, only a key. Use an empty value
@@ -221,7 +225,7 @@ public class HeadersExchange extends AbstractExchange
}
}
- _bindings.add(new Registration(new HeadersBinding(bindingMap), queue));
+ _bindings.add(new Registration(new HeadersBinding(bindingMap), queue, new AMQShortString(binding)));
}
} // End of MBean class
@@ -234,44 +238,48 @@ public class HeadersExchange extends AbstractExchange
public void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
{
_logger.debug("Exchange " + getName() + ": Binding " + queue.getName() + " with " + args);
- _bindings.add(new Registration(new HeadersBinding(args), queue));
+
+ Registration registration = new Registration(new HeadersBinding(args), queue, routingKey);
+ _bindings.add(registration);
+
}
public void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
{
_logger.debug("Exchange " + getName() + ": Unbinding " + queue.getName());
- if(!_bindings.remove(new Registration(new HeadersBinding(args), queue)))
+
+ if(!_bindings.remove(new Registration(args == null ? null : new HeadersBinding(args), queue, routingKey)))
{
throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue + " was not registered with exchange " + this.getName()
- + " with headers args " + args);
+ + " with headers args " + args);
}
}
- public void route(IncomingMessage payload) throws AMQException
+ public ArrayList<AMQQueue> route(InboundMessage payload)
{
- FieldTable headers = getHeaders(payload.getContentHeaderBody());
+ AMQMessageHeader header = payload.getMessageHeader();
if (_logger.isDebugEnabled())
{
- _logger.debug("Exchange " + getName() + ": routing message with headers " + headers);
+ _logger.debug("Exchange " + getName() + ": routing message with headers " + header);
}
boolean routed = false;
ArrayList<AMQQueue> queues = new ArrayList<AMQQueue>();
for (Registration e : _bindings)
{
- if (e.binding.matches(headers))
+ if (e.binding.matches(header))
{
if (_logger.isDebugEnabled())
{
_logger.debug("Exchange " + getName() + ": delivering message with headers " +
- headers + " to " + e.queue.getName());
+ header + " to " + e.queue.getName());
}
queues.add(e.queue);
routed = true;
}
}
- payload.enqueue(queues);
+ return queues;
}
public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
@@ -314,17 +322,9 @@ public class HeadersExchange extends AbstractExchange
return ((BasicContentHeaderProperties) contentHeaderFrame.properties).getHeaders();
}
- protected ExchangeMBean createMBean() throws AMQException
+ protected ExchangeMBean createMBean() throws JMException
{
- try
- {
- return new HeadersExchangeMBean();
- }
- catch (JMException ex)
- {
- _logger.error("Exception occured in creating the HeadersExchangeMBean", ex);
- throw new AMQException("Exception occured in creating the HeadersExchangeMBean", ex);
- }
+ return new HeadersExchangeMBean();
}
public Map<AMQShortString, List<AMQQueue>> getBindings()
@@ -332,25 +332,38 @@ public class HeadersExchange extends AbstractExchange
return null;
}
+ public Logger getLogger()
+ {
+ return _logger;
+ }
+
+
private static class Registration
{
private final HeadersBinding binding;
private final AMQQueue queue;
+ private final AMQShortString routingKey;
- Registration(HeadersBinding binding, AMQQueue queue)
+ Registration(HeadersBinding binding, AMQQueue queue, AMQShortString routingKey)
{
this.binding = binding;
this.queue = queue;
+ this.routingKey = routingKey;
}
public int hashCode()
{
- return queue.hashCode();
+ int queueHash = queue.hashCode();
+ int routingHash = routingKey == null ? 0 : routingKey.hashCode();
+ return queueHash + routingHash;
}
public boolean equals(Object o)
{
- return o instanceof Registration && ((Registration) o).queue.equals(queue);
+ return o instanceof Registration
+ && ((Registration) o).queue.equals(queue)
+ && (routingKey == null ? ((Registration)o).routingKey == null
+ : routingKey.equals(((Registration)o).routingKey));
}
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java
index ec83161029..90d04c814a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java
@@ -39,6 +39,9 @@ class Index
{
private ConcurrentMap<AMQShortString, ArrayList<AMQQueue>> _index
= new ConcurrentHashMap<AMQShortString, ArrayList<AMQQueue>>();
+ private ConcurrentMap<String, ArrayList<AMQQueue>> _stringIndex
+ = new ConcurrentHashMap<String, ArrayList<AMQQueue>>();
+
synchronized boolean add(AMQShortString key, AMQQueue queue)
{
@@ -51,8 +54,10 @@ class Index
{
queues = new ArrayList<AMQQueue>(queues);
}
+
//next call is atomic, so there is no race to create the list
_index.put(key, queues);
+ _stringIndex.put(key.toString(), queues);
if(queues.contains(queue))
{
@@ -64,6 +69,8 @@ class Index
}
}
+
+
synchronized boolean remove(AMQShortString key, AMQQueue queue)
{
ArrayList<AMQQueue> queues = _index.get(key);
@@ -76,10 +83,12 @@ class Index
if (queues.size() == 0)
{
_index.remove(key);
+ _stringIndex.remove(key.toString());
}
else
{
_index.put(key, queues);
+ _stringIndex.put(key.toString(), queues);
}
}
return removed;
@@ -92,6 +101,12 @@ class Index
return _index.get(key);
}
+ ArrayList<AMQQueue> get(String key)
+ {
+ return _stringIndex.get(key);
+ }
+
+
Map<AMQShortString, List<AMQQueue>> getBindingsMap()
{
return new HashMap<AMQShortString, List<AMQQueue>>(_index);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java
index db9beb6da7..025a8014aa 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,7 +21,6 @@
package org.apache.qpid.server.exchange;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.IncomingMessage;
/**
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java
deleted file mode 100644
index d18ad7ab14..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.exchange;
-
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.IncomingMessage;
-
-/**
- * NoRouteException is a {@link RequiredDeliveryException} that represents the failure case where a manadatory message
- * cannot be delivered because there is no route for the message. The AMQP status code, 312, is always used to report
- * this condition.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represent failure to deliver a message that must be delivered.
- * </table>
- */
-public class NoRouteException extends RequiredDeliveryException
-{
- public NoRouteException(String msg, AMQMessage amqMessage)
- {
- super(msg, amqMessage);
- }
-
- public AMQConstant getReplyCode()
- {
- return AMQConstant.NO_ROUTE;
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
index 31db1148c6..d5ca5a8a81 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
@@ -30,13 +30,13 @@ import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.AMQShortStringTokenizer;
-import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.exchange.topic.TopicParser;
import org.apache.qpid.server.exchange.topic.TopicMatcherResult;
import org.apache.qpid.server.filter.MessageFilter;
import org.apache.qpid.server.filter.JMSSelectorFilter;
+import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.ManagementActor;
@@ -111,7 +111,7 @@ public class TopicExchange extends AbstractExchange
private final Map<Binding, FieldTable> _bindings = new HashMap<Binding, FieldTable>();
- private final Map<String, WeakReference<JMSSelectorFilter<RuntimeException>>> _selectorCache = new WeakHashMap<String, WeakReference<JMSSelectorFilter<RuntimeException>>>();
+ private final Map<String, WeakReference<JMSSelectorFilter>> _selectorCache = new WeakHashMap<String, WeakReference<JMSSelectorFilter>>();
public static class Binding
{
@@ -162,7 +162,7 @@ public class TopicExchange extends AbstractExchange
private final class TopicExchangeResult implements TopicMatcherResult
{
private final Map<AMQQueue, Integer> _unfilteredQueues = new ConcurrentHashMap<AMQQueue, Integer>();
- private final ConcurrentHashMap<AMQQueue, Map<MessageFilter<RuntimeException>,Integer>> _filteredQueues = new ConcurrentHashMap<AMQQueue, Map<MessageFilter<RuntimeException>, Integer>>();
+ private final ConcurrentHashMap<AMQQueue, Map<MessageFilter,Integer>> _filteredQueues = new ConcurrentHashMap<AMQQueue, Map<MessageFilter, Integer>>();
public void addUnfilteredQueue(AMQQueue queue)
{
@@ -192,12 +192,12 @@ public class TopicExchange extends AbstractExchange
}
- public void addFilteredQueue(AMQQueue queue, MessageFilter<RuntimeException> filter)
+ public void addFilteredQueue(AMQQueue queue, MessageFilter filter)
{
- Map<MessageFilter<RuntimeException>,Integer> filters = _filteredQueues.get(queue);
+ Map<MessageFilter,Integer> filters = _filteredQueues.get(queue);
if(filters == null)
{
- filters = new ConcurrentHashMap<MessageFilter<RuntimeException>,Integer>();
+ filters = new ConcurrentHashMap<MessageFilter,Integer>();
_filteredQueues.put(queue, filters);
}
Integer instances = filters.get(filter);
@@ -212,9 +212,9 @@ public class TopicExchange extends AbstractExchange
}
- public void removeFilteredQueue(AMQQueue queue, MessageFilter<RuntimeException> filter)
+ public void removeFilteredQueue(AMQQueue queue, MessageFilter filter)
{
- Map<MessageFilter<RuntimeException>,Integer> filters = _filteredQueues.get(queue);
+ Map<MessageFilter,Integer> filters = _filteredQueues.get(queue);
if(filters != null)
{
Integer instances = filters.get(filter);
@@ -228,7 +228,7 @@ public class TopicExchange extends AbstractExchange
_filteredQueues.remove(queue);
}
}
- else
+ else
{
filters.put(filter, instances - 1);
}
@@ -239,11 +239,11 @@ public class TopicExchange extends AbstractExchange
}
public void replaceQueueFilter(AMQQueue queue,
- MessageFilter<RuntimeException> oldFilter,
- MessageFilter<RuntimeException> newFilter)
+ MessageFilter oldFilter,
+ MessageFilter newFilter)
{
- Map<MessageFilter<RuntimeException>,Integer> filters = _filteredQueues.get(queue);
- Map<MessageFilter<RuntimeException>,Integer> newFilters = new ConcurrentHashMap<MessageFilter<RuntimeException>,Integer>(filters);
+ Map<MessageFilter,Integer> filters = _filteredQueues.get(queue);
+ Map<MessageFilter,Integer> newFilters = new ConcurrentHashMap<MessageFilter,Integer>(filters);
Integer oldFilterInstances = filters.get(oldFilter);
if(oldFilterInstances == 1)
{
@@ -265,7 +265,7 @@ public class TopicExchange extends AbstractExchange
_filteredQueues.put(queue,newFilters);
}
- public Collection<AMQQueue> processMessage(IncomingMessage msg, Collection<AMQQueue> queues)
+ public Collection<AMQQueue> processMessage(InboundMessage msg, Collection<AMQQueue> queues)
{
if(queues == null)
{
@@ -286,11 +286,11 @@ public class TopicExchange extends AbstractExchange
queues.addAll(_unfilteredQueues.keySet());
if(!_filteredQueues.isEmpty())
{
- for(Map.Entry<AMQQueue, Map<MessageFilter<RuntimeException>, Integer>> entry : _filteredQueues.entrySet())
+ for(Map.Entry<AMQQueue, Map<MessageFilter, Integer>> entry : _filteredQueues.entrySet())
{
if(!queues.contains(entry.getKey()))
{
- for(MessageFilter<RuntimeException> filter : entry.getValue().keySet())
+ for(MessageFilter filter : entry.getValue().keySet())
{
if(filter.matches(msg))
{
@@ -443,10 +443,10 @@ public class TopicExchange extends AbstractExchange
{
result.addUnfilteredQueue(queue);
}
- _parser.addBinding(routingKey, result);
+ _parser.addBinding(routingKey, result);
_topicExchangeResults.put(routingKey,result);
}
- else
+ else
{
if(argumentsContainSelector(args))
{
@@ -463,18 +463,18 @@ public class TopicExchange extends AbstractExchange
}
- private JMSSelectorFilter<RuntimeException> createSelectorFilter(final FieldTable args)
+ private JMSSelectorFilter createSelectorFilter(final FieldTable args)
throws AMQException
{
final String selectorString = args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue());
- WeakReference<JMSSelectorFilter<RuntimeException>> selectorRef = _selectorCache.get(selectorString);
+ WeakReference<JMSSelectorFilter> selectorRef = _selectorCache.get(selectorString);
JMSSelectorFilter selector = null;
if(selectorRef == null || (selector = selectorRef.get())==null)
{
- selector = new JMSSelectorFilter<RuntimeException>(selectorString);
- _selectorCache.put(selectorString, new WeakReference<JMSSelectorFilter<RuntimeException>>(selector));
+ selector = new JMSSelectorFilter(selectorString);
+ _selectorCache.put(selectorString, new WeakReference<JMSSelectorFilter>(selector));
}
return selector;
}
@@ -490,7 +490,7 @@ public class TopicExchange extends AbstractExchange
{
routingKey = AMQShortString.EMPTY_STRING;
}
-
+
AMQShortStringTokenizer routingTokens = routingKey.tokenize(TOPIC_SEPARATOR);
List<AMQShortString> subscriptionList = new ArrayList<AMQShortString>();
@@ -535,10 +535,12 @@ public class TopicExchange extends AbstractExchange
return normalizedString;
}
- public void route(IncomingMessage payload) throws AMQException
+ public ArrayList<AMQQueue> route(InboundMessage payload)
{
- final AMQShortString routingKey = payload.getRoutingKey();
+ final AMQShortString routingKey = payload.getRoutingKey() == null
+ ? AMQShortString.EMPTY_STRING
+ : new AMQShortString(payload.getRoutingKey());
// The copy here is unfortunate, but not too bad relevant to the amount of
// things created and copied in getMatchedQueues
@@ -550,7 +552,7 @@ public class TopicExchange extends AbstractExchange
_logger.info("Message routing key: " + payload.getRoutingKey() + " No routes.");
}
- payload.enqueue(queues);
+ return queues;
}
@@ -572,7 +574,7 @@ public class TopicExchange extends AbstractExchange
{
return false;
}
-
+
}
}
@@ -640,20 +642,17 @@ public class TopicExchange extends AbstractExchange
}
- protected ExchangeMBean createMBean() throws AMQException
+ protected ExchangeMBean createMBean() throws JMException
{
- try
- {
- return new TopicExchangeMBean();
- }
- catch (JMException ex)
- {
- _logger.error("Exception occured in creating the topic exchenge mbean", ex);
- throw new AMQException("Exception occured in creating the topic exchenge mbean", ex);
- }
+ return new TopicExchangeMBean();
+ }
+
+ public Logger getLogger()
+ {
+ return _logger;
}
- private Collection<AMQQueue> getMatchedQueues(IncomingMessage message, AMQShortString routingKey)
+ private Collection<AMQQueue> getMatchedQueues(InboundMessage message, AMQShortString routingKey)
{
Collection<TopicMatcherResult> results = _parser.parse(routingKey);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java
index a964bce306..2ead9e57af 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java
@@ -26,7 +26,7 @@ import org.apache.qpid.server.queue.Filterable;
/**
* An expression which performs an operation on two expression values
*/
-public abstract class ArithmeticExpression<E extends Exception> extends BinaryExpression<E>
+public abstract class ArithmeticExpression extends BinaryExpression
{
protected static final int INTEGER = 1;
@@ -248,7 +248,7 @@ public abstract class ArithmeticExpression<E extends Exception> extends BinaryEx
}
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Object lvalue = left.evaluate(message);
if (lvalue == null)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java
index 7308de80d6..024257bea9 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java
@@ -23,23 +23,23 @@ package org.apache.qpid.server.filter;
/**
* An expression which performs an operation on two expression values.
*/
-public abstract class BinaryExpression<E extends Exception> implements Expression<E>
+public abstract class BinaryExpression implements Expression
{
- protected Expression<E> left;
- protected Expression<E> right;
+ protected Expression left;
+ protected Expression right;
- public BinaryExpression(Expression<E> left, Expression<E> right)
+ public BinaryExpression(Expression left, Expression right)
{
this.left = left;
this.right = right;
}
- public Expression<E> getLeft()
+ public Expression getLeft()
{
return left;
}
- public Expression<E> getRight()
+ public Expression getRight()
{
return right;
}
@@ -90,7 +90,7 @@ public abstract class BinaryExpression<E extends Exception> implements Expressio
/**
* @param expression
*/
- public void setRight(Expression<E> expression)
+ public void setRight(Expression expression)
{
right = expression;
}
@@ -98,7 +98,7 @@ public abstract class BinaryExpression<E extends Exception> implements Expressio
/**
* @param expression
*/
- public void setLeft(Expression<E> expression)
+ public void setLeft(Expression expression)
{
left = expression;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java
index 9beb9798d0..06e8664470 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java
@@ -20,22 +20,19 @@ package org.apache.qpid.server.filter;
// Based on like named file from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html>
//
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
/**
* A BooleanExpression is an expression that always
* produces a Boolean result.
*/
-public interface BooleanExpression<E extends Exception> extends Expression<E>
+public interface BooleanExpression extends Expression
{
/**
* @param message
* @return true if the expression evaluates to Boolean.TRUE.
- * @throws E
*/
- public boolean matches(Filterable<E> message) throws E;
+ public boolean matches(Filterable message);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java
index 921005c462..f0650cb642 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java
@@ -27,22 +27,20 @@ import java.util.HashSet;
import java.util.List;
import java.util.regex.Pattern;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
/**
* A filter performing a comparison of two objects
*/
-public abstract class ComparisonExpression<E extends Exception> extends BinaryExpression<E> implements BooleanExpression<E>
+public abstract class ComparisonExpression extends BinaryExpression implements BooleanExpression
{
- public static<E extends Exception> BooleanExpression<E> createBetween(Expression<E> value, Expression left, Expression<E> right)
+ public static BooleanExpression createBetween(Expression value, Expression left, Expression right)
{
return LogicExpression.createAND(createGreaterThanEqual(value, left), createLessThanEqual(value, right));
}
- public static<E extends Exception> BooleanExpression<E> createNotBetween(Expression<E> value, Expression<E> left, Expression<E> right)
+ public static BooleanExpression createNotBetween(Expression value, Expression left, Expression right)
{
return LogicExpression.createOR(createLessThan(value, left), createGreaterThan(value, right));
}
@@ -73,7 +71,7 @@ public abstract class ComparisonExpression<E extends Exception> extends BinaryEx
REGEXP_CONTROL_CHARS.add(new Character('!'));
}
- static class LikeExpression<E extends Exception> extends UnaryExpression<E> implements BooleanExpression<E>
+ static class LikeExpression extends UnaryExpression implements BooleanExpression
{
Pattern likePattern;
@@ -81,7 +79,7 @@ public abstract class ComparisonExpression<E extends Exception> extends BinaryEx
/**
* @param right
*/
- public LikeExpression(Expression<E> right, String like, int escape)
+ public LikeExpression(Expression right, String like, int escape)
{
super(right);
@@ -138,7 +136,7 @@ public abstract class ComparisonExpression<E extends Exception> extends BinaryEx
/**
* org.apache.activemq.filter.Expression#evaluate(MessageEvaluationContext)
*/
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Object rv = this.getRight().evaluate(message);
@@ -158,7 +156,7 @@ public abstract class ComparisonExpression<E extends Exception> extends BinaryEx
return likePattern.matcher((String) rv).matches() ? Boolean.TRUE : Boolean.FALSE;
}
- public boolean matches(Filterable<E> message) throws E
+ public boolean matches(Filterable message)
{
Object object = evaluate(message);
@@ -236,7 +234,7 @@ public abstract class ComparisonExpression<E extends Exception> extends BinaryEx
return doCreateEqual(left, right);
}
- private static<E extends Exception> BooleanExpression<E> doCreateEqual(Expression<E> left, Expression<E> right)
+ private static BooleanExpression doCreateEqual(Expression left, Expression right)
{
return new EqualExpression(left, right);
}
@@ -388,7 +386,7 @@ public abstract class ComparisonExpression<E extends Exception> extends BinaryEx
super(left, right);
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Comparable lv = (Comparable) left.evaluate(message);
if (lv == null)
@@ -550,21 +548,21 @@ public abstract class ComparisonExpression<E extends Exception> extends BinaryEx
protected abstract boolean asBoolean(int answer);
- public boolean matches(Filterable<E> message) throws E
+ public boolean matches(Filterable message)
{
Object object = evaluate(message);
return (object != null) && (object == Boolean.TRUE);
}
- private static class EqualExpression<E extends Exception> extends ComparisonExpression<E>
+ private static class EqualExpression extends ComparisonExpression
{
- public EqualExpression(final Expression<E> left, final Expression<E> right)
+ public EqualExpression(final Expression left, final Expression right)
{
super(left, right);
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Object lv = left.evaluate(message);
Object rv = right.evaluate(message);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java
index 3ed2286f2e..15cb770216 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java
@@ -25,24 +25,22 @@ package org.apache.qpid.server.filter;
import java.math.BigDecimal;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
/**
* Represents a constant expression
*/
-public class ConstantExpression<E extends Exception> implements Expression<E>
+public class ConstantExpression implements Expression
{
- static class BooleanConstantExpression<E extends Exception> extends ConstantExpression<E> implements BooleanExpression<E>
+ static class BooleanConstantExpression extends ConstantExpression implements BooleanExpression
{
public BooleanConstantExpression(Object value)
{
super(value);
}
- public boolean matches(Filterable<E> message) throws E
+ public boolean matches(Filterable message)
{
Object object = evaluate(message);
@@ -121,7 +119,7 @@ public class ConstantExpression<E extends Exception> implements Expression<E>
this.value = value;
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
return value;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java
index f2ebe41d26..97e9915271 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java
@@ -20,19 +20,17 @@ package org.apache.qpid.server.filter;
// Based on like named file from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html>
//
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
/**
* Represents an expression
*/
-public interface Expression<E extends Exception>
+public interface Expression
{
/**
* @return the value of this expression
*/
- public Object evaluate(Filterable<E> message) throws E;
+ public Object evaluate(Filterable message);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java
index dd3c126ee5..b5e282038b 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java
@@ -14,26 +14,24 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.server.filter;
//
// Based on like named file from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html>
//
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
-import org.apache.qpid.AMQException;
-public interface FilterManager<E extends Exception>
+public interface FilterManager
{
- void add(MessageFilter<E> filter);
+ void add(MessageFilter filter);
- void remove(MessageFilter<E> filter);
+ void remove(MessageFilter filter);
- boolean allAllow(Filterable<E> msg);
+ boolean allAllow(Filterable msg);
boolean hasFilters();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java
index 4adf5eb9ee..dacd047fea 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java
@@ -26,12 +26,12 @@ import org.apache.qpid.server.filter.jms.selector.SelectorParser;
import org.apache.qpid.server.queue.Filterable;
-public class JMSSelectorFilter<E extends Exception> implements MessageFilter<E>
+public class JMSSelectorFilter implements MessageFilter
{
private final static Logger _logger = org.apache.log4j.Logger.getLogger(JMSSelectorFilter.class);
private String _selector;
- private BooleanExpression<E> _matcher;
+ private BooleanExpression _matcher;
public JMSSelectorFilter(String selector) throws AMQException
{
@@ -39,7 +39,7 @@ public class JMSSelectorFilter<E extends Exception> implements MessageFilter<E>
_matcher = new SelectorParser().parse(selector);
}
- public boolean matches(Filterable<E> message) throws E
+ public boolean matches(Filterable message)
{
boolean match = _matcher.matches(message);
if(_logger.isDebugEnabled())
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java
index 094363ed9a..fdba184da4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java
@@ -20,22 +20,20 @@ package org.apache.qpid.server.filter;
// Based on like named file from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html>
//
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
/**
* A filter performing a comparison of two objects
*/
-public abstract class LogicExpression<E extends Exception> extends BinaryExpression<E> implements BooleanExpression<E>
+public abstract class LogicExpression extends BinaryExpression implements BooleanExpression
{
- public static<E extends Exception> BooleanExpression createOR(BooleanExpression<E> lvalue, BooleanExpression<E> rvalue)
+ public static BooleanExpression createOR(BooleanExpression lvalue, BooleanExpression rvalue)
{
return new OrExpression(lvalue, rvalue);
}
- public static<E extends Exception> BooleanExpression createAND(BooleanExpression<E> lvalue, BooleanExpression<E> rvalue)
+ public static BooleanExpression createAND(BooleanExpression lvalue, BooleanExpression rvalue)
{
return new AndExpression(lvalue, rvalue);
}
@@ -49,23 +47,23 @@ public abstract class LogicExpression<E extends Exception> extends BinaryExpress
super(left, right);
}
- public abstract Object evaluate(Filterable<E> message) throws E;
+ public abstract Object evaluate(Filterable message);
- public boolean matches(Filterable<E> message) throws E
+ public boolean matches(Filterable message)
{
Object object = evaluate(message);
return (object != null) && (object == Boolean.TRUE);
}
- private static class OrExpression<E extends Exception> extends LogicExpression<E>
+ private static class OrExpression extends LogicExpression
{
- public OrExpression(final BooleanExpression<E> lvalue, final BooleanExpression<E> rvalue)
+ public OrExpression(final BooleanExpression lvalue, final BooleanExpression rvalue)
{
super(lvalue, rvalue);
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Boolean lv = (Boolean) left.evaluate(message);
@@ -86,14 +84,14 @@ public abstract class LogicExpression<E extends Exception> extends BinaryExpress
}
}
- private static class AndExpression<E extends Exception> extends LogicExpression<E>
+ private static class AndExpression extends LogicExpression
{
- public AndExpression(final BooleanExpression<E> lvalue, final BooleanExpression<E> rvalue)
+ public AndExpression(final BooleanExpression lvalue, final BooleanExpression rvalue)
{
super(lvalue, rvalue);
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Boolean lv = (Boolean) left.evaluate(message);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java
index 58fc55f8e6..f5416af09a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java
@@ -14,17 +14,15 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.server.filter;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
-public interface MessageFilter<E extends Exception>
+public interface MessageFilter
{
- boolean matches(Filterable<E> message) throws E;
+ boolean matches(Filterable message);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
index 946274f936..11fdeae2b1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
@@ -27,7 +27,6 @@ import java.util.HashMap;
import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.CommonContentHeaderProperties;
import org.apache.qpid.server.queue.Filterable;
@@ -35,7 +34,7 @@ import org.apache.qpid.server.queue.Filterable;
/**
* Represents a property expression
*/
-public class PropertyExpression<E extends Exception> implements Expression<E>
+public class PropertyExpression implements Expression
{
// Constants - defined the same as JMS
private static final int NON_PERSISTENT = 1;
@@ -44,12 +43,12 @@ public class PropertyExpression<E extends Exception> implements Expression<E>
private static final Logger _logger = org.apache.log4j.Logger.getLogger(PropertyExpression.class);
- private static final HashMap<String, Expression<? extends Exception>> JMS_PROPERTY_EXPRESSIONS = new HashMap<String, Expression<? extends Exception>>();
+ private static final HashMap<String, Expression> JMS_PROPERTY_EXPRESSIONS = new HashMap<String, Expression>();
{
- JMS_PROPERTY_EXPRESSIONS.put("JMSDestination", new Expression<E>()
+ JMS_PROPERTY_EXPRESSIONS.put("JMSDestination", new Expression()
{
- public Object evaluate(Filterable<E> message)
+ public Object evaluate(Filterable message)
{
//TODO
return null;
@@ -73,9 +72,9 @@ public class PropertyExpression<E extends Exception> implements Expression<E>
JMS_PROPERTY_EXPRESSIONS.put("JMSExpiration", new ExpirationExpression());
- JMS_PROPERTY_EXPRESSIONS.put("JMSRedelivered", new Expression<E>()
+ JMS_PROPERTY_EXPRESSIONS.put("JMSRedelivered", new Expression()
{
- public Object evaluate(Filterable message) throws E
+ public Object evaluate(Filterable message)
{
return message.isRedelivered();
}
@@ -83,7 +82,7 @@ public class PropertyExpression<E extends Exception> implements Expression<E>
}
private final String name;
- private final Expression<E> jmsPropertyExpression;
+ private final Expression jmsPropertyExpression;
public boolean outerTest()
{
@@ -96,10 +95,10 @@ public class PropertyExpression<E extends Exception> implements Expression<E>
- jmsPropertyExpression = (Expression<E>) JMS_PROPERTY_EXPRESSIONS.get(name);
+ jmsPropertyExpression = (Expression) JMS_PROPERTY_EXPRESSIONS.get(name);
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
if (jmsPropertyExpression != null)
@@ -108,17 +107,7 @@ public class PropertyExpression<E extends Exception> implements Expression<E>
}
else
{
-
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties) message.getContentHeaderBody().properties;
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Looking up property:" + name);
- _logger.debug("Properties are:" + _properties.getHeaders().keySet());
- }
-
- return _properties.getHeaders().getObject(name);
+ return message.getMessageHeader().getHeader(name);
}
}
@@ -158,39 +147,30 @@ public class PropertyExpression<E extends Exception> implements Expression<E>
}
- private static class ReplyToExpression<E extends Exception> implements Expression<E>
+ private static class ReplyToExpression implements Expression
{
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
-
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
- AMQShortString replyTo = _properties.getReplyTo();
-
- return (replyTo == null) ? null : replyTo.toString();
-
+ String replyTo = message.getMessageHeader().getReplyTo();
+ return replyTo;
}
}
- private static class TypeExpression<E extends Exception> implements Expression<E>
+ private static class TypeExpression implements Expression
{
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
- AMQShortString type = _properties.getType();
- return (type == null) ? null : type.toString();
+ String type = message.getMessageHeader().getType();
+ return type;
}
}
- private static class DeliveryModeExpression<E extends Exception> implements Expression<E>
+ private static class DeliveryModeExpression implements Expression
{
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
int mode = message.isPersistent() ? PERSISTENT : NON_PERSISTENT;
if (_logger.isDebugEnabled())
@@ -202,68 +182,53 @@ public class PropertyExpression<E extends Exception> implements Expression<E>
}
}
- private static class PriorityExpression<E extends Exception> implements Expression<E>
+ private static class PriorityExpression implements Expression
{
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
-
- return (int) _properties.getPriority();
+ byte priority = message.getMessageHeader().getPriority();
+ return (int) priority;
}
}
- private static class MessageIDExpression<E extends Exception> implements Expression<E>
+ private static class MessageIDExpression implements Expression
{
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
- AMQShortString messageId = _properties.getMessageId();
+ String messageId = message.getMessageHeader().getMessageId();
- return (messageId == null) ? null : messageId;
+ return messageId;
}
}
- private static class TimestampExpression<E extends Exception> implements Expression<E>
+ private static class TimestampExpression implements Expression
{
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
-
- return _properties.getTimestamp();
+ long timestamp = message.getMessageHeader().getTimestamp();
+ return timestamp;
}
}
- private static class CorrelationIdExpression<E extends Exception> implements Expression<E>
+ private static class CorrelationIdExpression implements Expression
{
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
- AMQShortString correlationId = _properties.getCorrelationId();
- return (correlationId == null) ? null : correlationId.toString();
+ String correlationId = message.getMessageHeader().getCorrelationId();
+
+ return correlationId;
}
}
- private static class ExpirationExpression<E extends Exception> implements Expression<E>
+ private static class ExpirationExpression implements Expression
{
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
-
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
-
- return _properties.getExpiration();
+ long expiration = message.getMessageHeader().getExpiration();
+ return expiration;
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java
index b037f57787..c563569cb4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java
@@ -26,46 +26,37 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.Filterable;
-public class SimpleFilterManager implements FilterManager<AMQException>
+public class SimpleFilterManager implements FilterManager
{
private final Logger _logger = Logger.getLogger(SimpleFilterManager.class);
- private final ConcurrentLinkedQueue<MessageFilter<AMQException>> _filters;
+ private final ConcurrentLinkedQueue<MessageFilter> _filters;
private String _toString = "";
public SimpleFilterManager()
{
_logger.debug("Creating SimpleFilterManager");
- _filters = new ConcurrentLinkedQueue<MessageFilter<AMQException>>();
+ _filters = new ConcurrentLinkedQueue<MessageFilter>();
}
- public void add(MessageFilter<AMQException> filter)
+ public void add(MessageFilter filter)
{
_filters.add(filter);
updateStringValue();
}
- public void remove(MessageFilter<AMQException> filter)
+ public void remove(MessageFilter filter)
{
_filters.remove(filter);
updateStringValue();
}
- public boolean allAllow(Filterable<AMQException> msg)
+ public boolean allAllow(Filterable msg)
{
- for (MessageFilter<AMQException> filter : _filters)
+ for (MessageFilter filter : _filters)
{
- try
+ if (!filter.matches(msg))
{
- if (!filter.matches(msg))
- {
- return false;
- }
- }
- catch (AMQException e)
- {
- //fixme
- e.printStackTrace();
return false;
}
}
@@ -87,7 +78,7 @@ public class SimpleFilterManager implements FilterManager<AMQException>
private void updateStringValue()
{
StringBuilder toString = new StringBuilder();
- for (MessageFilter<AMQException> filter : _filters)
+ for (MessageFilter filter : _filters)
{
toString.append(filter.toString());
toString.append(",");
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java
index 799a38af5a..9e03ecd8bd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java
@@ -35,18 +35,18 @@ import org.apache.qpid.server.queue.Filterable;
/**
* An expression which performs an operation on two expression values
*/
-public abstract class UnaryExpression<E extends Exception> implements Expression<E>
+public abstract class UnaryExpression implements Expression
{
private static final BigDecimal BD_LONG_MIN_VALUE = BigDecimal.valueOf(Long.MIN_VALUE);
- protected Expression<E> right;
+ protected Expression right;
- public static<E extends Exception> Expression<E> createNegate(Expression<E> left)
+ public static Expression createNegate(Expression left)
{
return new NegativeExpression(left);
}
- public static<E extends Exception> BooleanExpression createInExpression(PropertyExpression<E> right, List elements, final boolean not)
+ public static BooleanExpression createInExpression(PropertyExpression right, List elements, final boolean not)
{
// Use a HashSet if there are many elements.
@@ -69,14 +69,14 @@ public abstract class UnaryExpression<E extends Exception> implements Expression
return new InExpression(right, inList, not);
}
- abstract static class BooleanUnaryExpression<E extends Exception> extends UnaryExpression<E> implements BooleanExpression<E>
+ abstract static class BooleanUnaryExpression extends UnaryExpression implements BooleanExpression
{
- public BooleanUnaryExpression(Expression<E> left)
+ public BooleanUnaryExpression(Expression left)
{
super(left);
}
- public boolean matches(Filterable<E> message) throws E
+ public boolean matches(Filterable message)
{
Object object = evaluate(message);
@@ -85,7 +85,7 @@ public abstract class UnaryExpression<E extends Exception> implements Expression
}
;
- public static<E extends Exception> BooleanExpression<E> createNOT(BooleanExpression<E> left)
+ public static<E extends Exception> BooleanExpression createNOT(BooleanExpression left)
{
return new NotExpression(left);
}
@@ -100,7 +100,7 @@ public abstract class UnaryExpression<E extends Exception> implements Expression
return new XQueryExpression(xpath);
}
- public static<E extends Exception> BooleanExpression createBooleanCast(Expression<E> left)
+ public static<E extends Exception> BooleanExpression createBooleanCast(Expression left)
{
return new BooleanCastExpression(left);
}
@@ -151,7 +151,7 @@ public abstract class UnaryExpression<E extends Exception> implements Expression
this.right = left;
}
- public Expression<E> getRight()
+ public Expression getRight()
{
return right;
}
@@ -204,14 +204,14 @@ public abstract class UnaryExpression<E extends Exception> implements Expression
*/
public abstract String getExpressionSymbol();
- private static class NegativeExpression<E extends Exception> extends UnaryExpression<E>
+ private static class NegativeExpression extends UnaryExpression
{
- public NegativeExpression(final Expression<E> left)
+ public NegativeExpression(final Expression left)
{
super(left);
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Object rvalue = right.evaluate(message);
if (rvalue == null)
@@ -233,19 +233,19 @@ public abstract class UnaryExpression<E extends Exception> implements Expression
}
}
- private static class InExpression<E extends Exception> extends BooleanUnaryExpression<E>
+ private static class InExpression extends BooleanUnaryExpression
{
private final Collection _inList;
private final boolean _not;
- public InExpression(final PropertyExpression<E> right, final Collection inList, final boolean not)
+ public InExpression(final PropertyExpression right, final Collection inList, final boolean not)
{
super(right);
_inList = inList;
_not = not;
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Object rvalue = right.evaluate(message);
@@ -309,14 +309,14 @@ public abstract class UnaryExpression<E extends Exception> implements Expression
}
}
- private static class NotExpression<E extends Exception> extends BooleanUnaryExpression<E>
+ private static class NotExpression extends BooleanUnaryExpression
{
- public NotExpression(final BooleanExpression<E> left)
+ public NotExpression(final BooleanExpression left)
{
super(left);
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Boolean lvalue = (Boolean) right.evaluate(message);
if (lvalue == null)
@@ -333,14 +333,14 @@ public abstract class UnaryExpression<E extends Exception> implements Expression
}
}
- private static class BooleanCastExpression<E extends Exception> extends BooleanUnaryExpression<E>
+ private static class BooleanCastExpression extends BooleanUnaryExpression
{
- public BooleanCastExpression(final Expression<E> left)
+ public BooleanCastExpression(final Expression left)
{
super(left);
}
- public Object evaluate(Filterable<E> message) throws E
+ public Object evaluate(Filterable message)
{
Object rvalue = right.evaluate(message);
if (rvalue == null)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java
index 1311178fb1..aa35cb5a76 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java
@@ -22,7 +22,6 @@ package org.apache.qpid.server.filter;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
import java.lang.reflect.Constructor;
@@ -71,7 +70,7 @@ public final class XPathExpression implements BooleanExpression {
private final XPathEvaluator evaluator;
static public interface XPathEvaluator {
- public boolean evaluate(Filterable message) throws AMQException;
+ public boolean evaluate(Filterable message);
}
XPathExpression(String xpath) {
@@ -93,7 +92,7 @@ public final class XPathExpression implements BooleanExpression {
}
}
- public Object evaluate(Filterable message) throws AMQException {
+ public Object evaluate(Filterable message) {
// try {
//FIXME this is flow to disk work
// if( message.isDropped() )
@@ -118,7 +117,7 @@ public final class XPathExpression implements BooleanExpression {
* @return true if the expression evaluates to Boolean.TRUE.
* @throws AMQException
*/
- public boolean matches(Filterable message) throws AMQException
+ public boolean matches(Filterable message)
{
Object object = evaluate(message);
return object!=null && object==Boolean.TRUE;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java
index c13f81cd08..ae22f17413 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java
@@ -18,7 +18,6 @@
package org.apache.qpid.server.filter;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
//
@@ -36,23 +35,23 @@ public final class XQueryExpression implements BooleanExpression {
this.xpath = xpath;
}
- public Object evaluate(Filterable message) throws AMQException {
+ public Object evaluate(Filterable message) {
return Boolean.FALSE;
}
public String toString() {
return "XQUERY "+ConstantExpression.encodeString(xpath);
}
-
+
/**
* @param message
* @return true if the expression evaluates to Boolean.TRUE.
* @throws AMQException
*/
- public boolean matches(Filterable message) throws AMQException
+ public boolean matches(Filterable message)
{
Object object = evaluate(message);
- return object!=null && object==Boolean.TRUE;
+ return object!=null && object==Boolean.TRUE;
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java
index cc67776682..f83eb63ac5 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java
@@ -27,8 +27,6 @@ import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.Filterable;
import org.apache.xpath.CachedXPathAPI;
import org.w3c.dom.Document;
@@ -36,14 +34,14 @@ import org.w3c.dom.traversal.NodeIterator;
import org.xml.sax.InputSource;
public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
-
+
private final String xpath;
public XalanXPathEvaluator(String xpath) {
this.xpath = xpath;
}
-
- public boolean evaluate(Filterable m) throws AMQException
+
+ public boolean evaluate(Filterable m)
{
// TODO - we would have to check the content type and then evaluate the content
// here... is this really a feature we wish to implement? - RobG
@@ -65,18 +63,18 @@ public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
private boolean evaluate(byte[] data) {
try {
-
+
InputSource inputSource = new InputSource(new ByteArrayInputStream(data));
-
+
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder dbuilder = factory.newDocumentBuilder();
Document doc = dbuilder.parse(inputSource);
-
+
CachedXPathAPI cachedXPathAPI = new CachedXPathAPI();
NodeIterator iterator = cachedXPathAPI.selectNodeIterator(doc,xpath);
return iterator.nextNode()!=null;
-
+
} catch (Throwable e) {
return false;
}
@@ -85,12 +83,12 @@ public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
private boolean evaluate(String text) {
try {
InputSource inputSource = new InputSource(new StringReader(text));
-
+
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder dbuilder = factory.newDocumentBuilder();
Document doc = dbuilder.parse(inputSource);
-
+
// We should associated the cachedXPathAPI object with the message being evaluated
// since that should speedup subsequent xpath expressions.
CachedXPathAPI cachedXPathAPI = new CachedXPathAPI();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java
index 895db7b15b..cfe5aedd61 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java
@@ -31,19 +31,28 @@ public abstract class AbstractFlowCreditManager implements FlowCreditManager
public final void addStateListener(FlowCreditManagerListener listener)
{
- _listeners.add(listener);
+ synchronized(_listeners)
+ {
+ _listeners.add(listener);
+ }
}
public final boolean removeListener(FlowCreditManagerListener listener)
{
- return _listeners.remove(listener);
+ synchronized(_listeners)
+ {
+ return _listeners.remove(listener);
+ }
}
private void notifyListeners(final boolean suspended)
{
- for(FlowCreditManagerListener listener : _listeners)
+ synchronized(_listeners)
{
- listener.creditStateChanged(!suspended);
+ for(FlowCreditManagerListener listener : _listeners)
+ {
+ listener.creditStateChanged(!suspended);
+ }
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
index 96a1071135..c5f2d1e808 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
@@ -1,11 +1,8 @@
package org.apache.qpid.server.flow;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.message.ServerMessage;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.Set;
-import java.util.HashSet;
/*
*
@@ -36,7 +33,17 @@ public class BytesOnlyCreditManager extends AbstractFlowCreditManager
_bytesCredit = new AtomicLong(initialCredit);
}
- public void addCredit(long messageCredit, long bytesCredit)
+ public long getMessageCredit()
+ {
+ return -1L;
+ }
+
+ public long getBytesCredit()
+ {
+ return _bytesCredit.get();
+ }
+
+ public void restoreCredit(long messageCredit, long bytesCredit)
{
_bytesCredit.addAndGet(bytesCredit);
setSuspended(false);
@@ -52,7 +59,7 @@ public class BytesOnlyCreditManager extends AbstractFlowCreditManager
return _bytesCredit.get() > 0L;
}
- public boolean useCreditForMessage(AMQMessage msg)
+ public boolean useCreditForMessage(ServerMessage msg)
{
final long msgSize = msg.getSize();
if(hasCredit())
@@ -74,4 +81,9 @@ public class BytesOnlyCreditManager extends AbstractFlowCreditManager
}
}
+
+ public void setBytesCredit(long bytesCredit)
+ {
+ _bytesCredit.set( bytesCredit );
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java
new file mode 100644
index 0000000000..b47f986155
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java
@@ -0,0 +1,188 @@
+/*
+ *
+ * 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.flow;
+
+import org.apache.qpid.server.message.ServerMessage;
+
+public class CreditCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10
+{
+ private volatile long _bytesCredit;
+ private volatile long _messageCredit;
+
+
+ public CreditCreditManager()
+ {
+ this(0L, 0L);
+ }
+
+ public CreditCreditManager(long bytesCredit, long messageCredit)
+ {
+ _bytesCredit = bytesCredit;
+ _messageCredit = messageCredit;
+ setSuspended(!hasCredit());
+
+ }
+
+
+ public synchronized void setCreditLimits(final long bytesCredit, final long messageCredit)
+ {
+ _bytesCredit = bytesCredit;
+ _messageCredit = messageCredit;
+
+ setSuspended(!hasCredit());
+
+ }
+
+
+ public long getMessageCredit()
+ {
+ return _messageCredit == -1L
+ ? Long.MAX_VALUE
+ : _messageCredit;
+ }
+
+ public long getBytesCredit()
+ {
+ return _bytesCredit == -1L
+ ? Long.MAX_VALUE
+ : _bytesCredit;
+ }
+
+ public synchronized void restoreCredit(final long messageCredit, final long bytesCredit)
+ {
+ /*_bytesCredit = 0l;
+ _messageCredit = 0l;
+ setSuspended(true);*/
+ }
+
+
+ public synchronized void addCredit(final long messageCredit, final long bytesCredit)
+ {
+ boolean notifyIncrease = true;
+ if(_messageCredit >= 0L && messageCredit > 0L)
+ {
+ notifyIncrease = _messageCredit != 0L;
+ _messageCredit += messageCredit;
+ }
+
+
+
+ if(_bytesCredit >= 0L && bytesCredit > 0L)
+ {
+ notifyIncrease = notifyIncrease && bytesCredit>0;
+ _bytesCredit += bytesCredit;
+
+
+
+ if(notifyIncrease)
+ {
+ notifyIncreaseBytesCredit();
+ }
+ }
+
+
+
+ setSuspended(!hasCredit());
+
+ }
+
+ public void clearCredit()
+ {
+ _bytesCredit = 0l;
+ _messageCredit = 0l;
+ setSuspended(true);
+ }
+
+
+ public synchronized boolean hasCredit()
+ {
+ // Note !=, if credit is < 0 that indicates infinite credit
+ return (_bytesCredit != 0L && _messageCredit != 0L);
+ }
+
+ public synchronized boolean useCreditForMessage(final ServerMessage msg)
+ {
+ if(_messageCredit >= 0L)
+ {
+ if(_messageCredit > 0)
+ {
+ if(_bytesCredit < 0L)
+ {
+ _messageCredit--;
+
+ return true;
+ }
+ else if(msg.getSize() <= _bytesCredit)
+ {
+ _messageCredit--;
+ _bytesCredit -= msg.getSize();
+
+ return true;
+ }
+ else
+ {
+ //setSuspended(true);
+ return false;
+ }
+ }
+ else
+ {
+ setSuspended(true);
+ return false;
+ }
+ }
+ else if(_bytesCredit >= 0L)
+ {
+ if(msg.getSize() <= _bytesCredit)
+ {
+ _bytesCredit -= msg.getSize();
+
+ return true;
+ }
+ else
+ {
+ //setSuspended(true);
+ return false;
+ }
+
+ }
+ else
+ {
+ return true;
+ }
+
+ }
+
+ public synchronized void stop()
+ {
+ if(_bytesCredit > 0)
+ {
+ _bytesCredit = 0;
+ }
+ if(_messageCredit > 0)
+ {
+ _messageCredit = 0;
+ }
+
+ }
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
index a249a6e63a..bec51d361d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
@@ -1,6 +1,6 @@
package org.apache.qpid.server.flow;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.message.ServerMessage;
/*
*
@@ -24,6 +24,9 @@ import org.apache.qpid.server.queue.AMQMessage;
*/
public interface FlowCreditManager
{
+ long getMessageCredit();
+
+ long getBytesCredit();
public static interface FlowCreditManagerListener
{
@@ -34,11 +37,10 @@ public interface FlowCreditManager
boolean removeListener(FlowCreditManagerListener listener);
- public void addCredit(long messageCredit, long bytesCredit);
-
- public void removeAllCredit();
+ public void restoreCredit(long messageCredit, long bytesCredit);
public boolean hasCredit();
- public boolean useCreditForMessage(AMQMessage msg);
+ public boolean useCreditForMessage(ServerMessage msg);
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/ConcurrentLinkedQueueNoSize.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java
index cf5e71a6e2..48c336c0b1 100644..100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/ConcurrentLinkedQueueNoSize.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java
@@ -1,3 +1,5 @@
+package org.apache.qpid.server.flow;
+
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -7,9 +9,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,21 +20,9 @@
* under the License.
*
*/
-package org.apache.qpid.server.util;
-
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-public class ConcurrentLinkedQueueNoSize<E> extends ConcurrentLinkedQueue<E>
+public interface FlowCreditManager_0_10 extends FlowCreditManager
{
- public int size()
- {
- if (isEmpty())
- {
- return 0;
- }
- else
- {
- return 1;
- }
- }
+ public void addCredit(long count, long bytes);
+
+ void clearCredit();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
index d63431c3eb..901b71fd1f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
@@ -1,6 +1,6 @@
package org.apache.qpid.server.flow;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.message.ServerMessage;
/*
*
@@ -24,7 +24,17 @@ import org.apache.qpid.server.queue.AMQMessage;
*/
public class LimitlessCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
{
- public void addCredit(long messageCredit, long bytesCredit)
+ public long getMessageCredit()
+ {
+ return -1L;
+ }
+
+ public long getBytesCredit()
+ {
+ return -1L;
+ }
+
+ public void restoreCredit(long messageCredit, long bytesCredit)
{
}
@@ -37,7 +47,7 @@ public class LimitlessCreditManager extends AbstractFlowCreditManager implements
return true;
}
- public boolean useCreditForMessage(AMQMessage msg)
+ public boolean useCreditForMessage(ServerMessage msg)
{
return true;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
index 9c377481de..19a9ac1d23 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
@@ -1,8 +1,6 @@
package org.apache.qpid.server.flow;
-import org.apache.qpid.server.queue.AMQMessage;
-
-import java.util.concurrent.atomic.AtomicLong;
+import org.apache.qpid.server.message.ServerMessage;
/*
*
@@ -29,14 +27,24 @@ public class MessageAndBytesCreditManager extends AbstractFlowCreditManager impl
private long _messageCredit;
private long _bytesCredit;
- MessageAndBytesCreditManager(final long messageCredit, final long bytesCredit)
+ public MessageAndBytesCreditManager(final long messageCredit, final long bytesCredit)
{
_messageCredit = messageCredit;
_bytesCredit = bytesCredit;
}
- public synchronized void addCredit(long messageCredit, long bytesCredit)
+ public synchronized long getMessageCredit()
{
+ return _messageCredit;
+ }
+
+ public synchronized long getBytesCredit()
+ {
+ return _bytesCredit;
+ }
+
+ public synchronized void restoreCredit(long messageCredit, long bytesCredit)
+ {
_messageCredit += messageCredit;
_bytesCredit += bytesCredit;
setSuspended(hasCredit());
@@ -54,7 +62,7 @@ public class MessageAndBytesCreditManager extends AbstractFlowCreditManager impl
return (_messageCredit > 0L) && ( _bytesCredit > 0L );
}
- public synchronized boolean useCreditForMessage(AMQMessage msg)
+ public synchronized boolean useCreditForMessage(ServerMessage msg)
{
if(_messageCredit == 0L)
{
@@ -76,4 +84,9 @@ public class MessageAndBytesCreditManager extends AbstractFlowCreditManager impl
}
}
+
+ public synchronized void setBytesCredit(long bytesCredit)
+ {
+ _bytesCredit = bytesCredit;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
index c1b3a09006..a386f66b11 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
@@ -1,6 +1,6 @@
package org.apache.qpid.server.flow;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.message.ServerMessage;
import java.util.concurrent.atomic.AtomicLong;
@@ -33,10 +33,21 @@ public class MessageOnlyCreditManager extends AbstractFlowCreditManager implemen
_messageCredit = new AtomicLong(initialCredit);
}
- public void addCredit(long messageCredit, long bytesCredit)
+ public long getMessageCredit()
+ {
+ return _messageCredit.get();
+ }
+
+ public long getBytesCredit()
+ {
+ return -1L;
+ }
+
+ public void restoreCredit(long messageCredit, long bytesCredit)
{
- setSuspended(false);
_messageCredit.addAndGet(messageCredit);
+ setSuspended(false);
+
}
public void removeAllCredit()
@@ -50,7 +61,7 @@ public class MessageOnlyCreditManager extends AbstractFlowCreditManager implemen
return _messageCredit.get() > 0L;
}
- public boolean useCreditForMessage(AMQMessage msg)
+ public boolean useCreditForMessage(ServerMessage msg)
{
if(hasCredit())
{
@@ -73,4 +84,5 @@ public class MessageOnlyCreditManager extends AbstractFlowCreditManager implemen
}
}
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java
index be0300f2c1..026804439c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java
@@ -20,7 +20,7 @@
*/
package org.apache.qpid.server.flow;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.message.ServerMessage;
public class Pre0_10CreditManager extends AbstractFlowCreditManager implements FlowCreditManager
{
@@ -81,7 +81,17 @@ public class Pre0_10CreditManager extends AbstractFlowCreditManager implements F
}
- public synchronized void addCredit(final long messageCredit, final long bytesCredit)
+ public long getMessageCredit()
+ {
+ return _messageCredit;
+ }
+
+ public long getBytesCredit()
+ {
+ return _bytesCredit;
+ }
+
+ public synchronized void restoreCredit(final long messageCredit, final long bytesCredit)
{
final long messageCreditLimit = _messageCreditLimit;
boolean notifyIncrease = true;
@@ -123,7 +133,7 @@ public class Pre0_10CreditManager extends AbstractFlowCreditManager implements F
&& (_messageCreditLimit == 0L || _messageCredit > 0);
}
- public synchronized boolean useCreditForMessage(final AMQMessage msg)
+ public synchronized boolean useCreditForMessage(final ServerMessage msg)
{
if(_messageCreditLimit != 0L)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java
new file mode 100644
index 0000000000..10f578551a
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java
@@ -0,0 +1,213 @@
+/*
+ *
+ * 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.flow;
+
+import org.apache.qpid.server.message.ServerMessage;
+
+public class WindowCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10
+{
+ private volatile long _bytesCreditLimit;
+ private volatile long _messageCreditLimit;
+
+ private volatile long _bytesUsed;
+ private volatile long _messageUsed;
+
+ public WindowCreditManager()
+ {
+ this(0L, 0L);
+ }
+
+ public WindowCreditManager(long bytesCreditLimit, long messageCreditLimit)
+ {
+ _bytesCreditLimit = bytesCreditLimit;
+ _messageCreditLimit = messageCreditLimit;
+ setSuspended(!hasCredit());
+
+ }
+
+
+ public synchronized void setCreditLimits(final long bytesCreditLimit, final long messageCreditLimit)
+ {
+ _bytesCreditLimit = bytesCreditLimit;
+ _messageCreditLimit = messageCreditLimit;
+
+ setSuspended(!hasCredit());
+
+ }
+
+
+ public long getMessageCredit()
+ {
+ return _messageCreditLimit == -1L
+ ? Long.MAX_VALUE
+ : _messageUsed < _messageCreditLimit ? _messageCreditLimit - _messageUsed : 0L;
+ }
+
+ public long getBytesCredit()
+ {
+ return _bytesCreditLimit == -1L
+ ? Long.MAX_VALUE
+ : _bytesUsed < _bytesCreditLimit ? _bytesCreditLimit - _bytesUsed : 0L;
+ }
+
+ public synchronized void restoreCredit(final long messageCredit, final long bytesCredit)
+ {
+ boolean notifyIncrease = true;
+ if(_messageCreditLimit > 0L)
+ {
+ notifyIncrease = (_messageUsed != _messageCreditLimit);
+ _messageUsed -= messageCredit;
+
+ //TODO log warning
+ if(_messageUsed < 0L)
+ {
+ _messageUsed = 0;
+ }
+ }
+
+
+
+ if(_bytesCreditLimit > 0L)
+ {
+ notifyIncrease = notifyIncrease && bytesCredit>0;
+ _bytesUsed -= bytesCredit;
+
+ //TODO log warning
+ if(_bytesUsed < 0L)
+ {
+ _bytesUsed = 0;
+ }
+
+ if(notifyIncrease)
+ {
+ notifyIncreaseBytesCredit();
+ }
+ }
+
+
+
+ setSuspended(!hasCredit());
+
+ }
+
+
+
+ public synchronized boolean hasCredit()
+ {
+ return (_bytesCreditLimit < 0L || _bytesCreditLimit > _bytesUsed)
+ && (_messageCreditLimit < 0L || _messageCreditLimit > _messageUsed);
+ }
+
+ public synchronized boolean useCreditForMessage(final ServerMessage msg)
+ {
+ if(_messageCreditLimit >= 0L)
+ {
+ if(_messageUsed < _messageCreditLimit)
+ {
+ if(_bytesCreditLimit < 0L)
+ {
+ _messageUsed++;
+
+ return true;
+ }
+ else if(_bytesUsed + msg.getSize() <= _bytesCreditLimit)
+ {
+ _messageUsed++;
+ _bytesUsed += msg.getSize();
+
+ return true;
+ }
+ else
+ {
+ //setSuspended(true);
+ return false;
+ }
+ }
+ else
+ {
+ setSuspended(true);
+ return false;
+ }
+ }
+ else if(_bytesCreditLimit >= 0L)
+ {
+ if(_bytesUsed + msg.getSize() <= _bytesCreditLimit)
+ {
+ _bytesUsed += msg.getSize();
+
+ return true;
+ }
+ else
+ {
+ //setSuspended(true);
+ return false;
+ }
+
+ }
+ else
+ {
+ return true;
+ }
+
+ }
+
+ public void stop()
+ {
+ if(_bytesCreditLimit > 0)
+ {
+ _bytesCreditLimit = 0;
+ }
+ if(_messageCreditLimit > 0)
+ {
+ _messageCreditLimit = 0;
+ }
+
+ }
+
+ public synchronized void addCredit(long count, long bytes)
+ {
+ if(bytes > 0)
+ {
+ _bytesCreditLimit += bytes;
+ }
+ else if(bytes == -1)
+ {
+ _bytesCreditLimit = -1;
+ }
+
+
+ if(count > 0)
+ {
+ _messageCreditLimit += count;
+ }
+ else if(count == -1)
+ {
+ _messageCreditLimit = -1;
+ }
+ }
+
+ public void clearCredit()
+ {
+ _bytesCreditLimit = 0l;
+ _messageCreditLimit = 0l;
+ setSuspended(true);
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
index 08610f24cd..859a3477e6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
@@ -25,7 +25,6 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.*;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.ConsumerTagNotUniqueException;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.security.access.Permission;
@@ -116,17 +115,31 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
try
{
- AMQShortString consumerTag = channel.subscribeToQueue(consumerTagName, queue, !body.getNoAck(),
- body.getArguments(), body.getNoLocal(), body.getExclusive());
- if (!body.getNowait())
+ if(consumerTagName == null || channel.getSubscription(consumerTagName) == null)
{
- MethodRegistry methodRegistry = session.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag);
- session.writeFrame(responseBody.generateFrame(channelId));
+ AMQShortString consumerTag = channel.subscribeToQueue(consumerTagName, queue, !body.getNoAck(),
+ body.getArguments(), body.getNoLocal(), body.getExclusive());
+ if (!body.getNowait())
+ {
+ MethodRegistry methodRegistry = session.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag);
+ session.writeFrame(responseBody.generateFrame(channelId));
+
+ }
+ }
+ else
+ {
+ AMQShortString msg = new AMQShortString("Non-unique consumer tag, '" + body.getConsumerTag() + "'");
+
+ MethodRegistry methodRegistry = session.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode
+ msg, // replytext
+ body.getClazz(),
+ body.getMethod());
+ session.writeFrame(responseBody.generateFrame(0));
}
-
}
catch (org.apache.qpid.AMQInvalidArgumentException ise)
{
@@ -141,17 +154,6 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
}
- catch (ConsumerTagNotUniqueException e)
- {
- AMQShortString msg = new AMQShortString("Non-unique consumer tag, '" + body.getConsumerTag() + "'");
-
- MethodRegistry methodRegistry = session.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode
- msg, // replytext
- body.getClazz(),
- body.getMethod());
- session.writeFrame(responseBody.generateFrame(0));
- }
catch (AMQQueue.ExistingExclusiveSubscription e)
{
throw body.getChannelException(AMQConstant.ACCESS_REFUSED,
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
index 001b7858ec..a473184efb 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
@@ -30,6 +30,7 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.flow.FlowCreditManager;
import org.apache.qpid.server.flow.MessageOnlyCreditManager;
import org.apache.qpid.server.subscription.SubscriptionImpl;
@@ -40,8 +41,6 @@ import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
-import org.apache.qpid.server.security.access.Permission;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -130,8 +129,16 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB
throws AMQException
{
singleMessageCredit.useCreditForMessage(entry.getMessage());
- session.getProtocolOutputConverter().writeGetOk(entry.getMessage(), channel.getChannelId(),
- deliveryTag, queue.getMessageCount());
+ if(entry.getMessage() instanceof AMQMessage)
+ {
+ session.getProtocolOutputConverter().writeGetOk(entry, channel.getChannelId(),
+ deliveryTag, queue.getMessageCount());
+ }
+ else
+ {
+ //TODO Convert AMQP 0-10 message
+ throw new RuntimeException("Not implemented conversion of 0-10 message");
+ }
}
};
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java
index fcf3fd4337..62dd76f832 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java
@@ -81,13 +81,13 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
message = channel.getUnacknowledgedMessageMap().remove(deliveryTag);
if(message != null)
{
- message.discard(channel.getStoreContext());
+ message.discard();
}
//sendtoDeadLetterQueue(msg)
return;
}
- if (!message.getMessage().isReferenced())
+ if (message.getMessage() == null)
{
_logger.warn("Message as already been purged, unable to Reject.");
return;
@@ -96,7 +96,7 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
if (_logger.isDebugEnabled())
{
- _logger.debug("Rejecting: DT:" + deliveryTag + "-" + message.getMessage().debugIdentity() +
+ _logger.debug("Rejecting: DT:" + deliveryTag + "-" + message.getMessage() +
": Requeue:" + body.getRequeue() +
//": Resend:" + evt.getMethod().resend +
" on channel:" + channel.debugIdentity());
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java
index 824f084f57..31bafac0a2 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java
@@ -24,7 +24,6 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.*;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.security.access.Permission;
import org.apache.qpid.server.state.AMQState;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
@@ -96,7 +95,7 @@ public class ConnectionOpenMethodHandler implements StateAwareMethodListener<Con
session.writeFrame(responseBody.generateFrame(channelId));
-
+
}
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java
index 0fe8c5dc92..9f392ffc44 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java
@@ -50,5 +50,6 @@ public class ConnectionTuneOkMethodHandler implements StateAwareMethodListener<C
}
stateManager.changeState(AMQState.CONNECTION_NOT_OPENED);
session.initHeartbeats(body.getHeartbeat());
+ session.setMaxFrameSize(body.getFrameMax());
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
index ba60808492..b0ee5fff08 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -92,11 +92,11 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange
try
{
- exchange = exchangeFactory.createExchange(body.getExchange() == null ? null : body.getExchange().intern(),
- body.getType() == null ? null : body.getType().intern(),
- body.getDurable(),
- body.getPassive(), body.getTicket());
- exchangeRegistry.registerExchange(exchange);
+ exchange = exchangeFactory.createExchange(body.getExchange() == null ? null : body.getExchange().intern(),
+ body.getType() == null ? null : body.getType().intern(),
+ body.getDurable(),
+ body.getPassive(), body.getTicket());
+ exchangeRegistry.registerExchange(exchange);
}
catch(AMQUnknownExchangeType e)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
index b705ea7dba..4f69afe755 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
@@ -40,7 +40,7 @@ import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
-import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclareBody>
@@ -60,11 +60,11 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
public void methodReceived(AMQStateManager stateManager, QueueDeclareBody body, int channelId) throws AMQException
{
- AMQProtocolSession session = stateManager.getProtocolSession();
+ final AMQProtocolSession session = stateManager.getProtocolSession();
VirtualHost virtualHost = session.getVirtualHost();
ExchangeRegistry exchangeRegistry = virtualHost.getExchangeRegistry();
QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
- MessageStore store = virtualHost.getMessageStore();
+ DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
if (!body.getPassive())
@@ -109,11 +109,31 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
else
{
queue = createQueue(queueName, body, virtualHost, session);
+ queue.setPrincipalHolder(session);
if (queue.isDurable() && !queue.isAutoDelete())
{
store.createQueue(queue, body.getArguments());
}
queueRegistry.registerQueue(queue);
+ if(queue.isExclusive() && !queue.isAutoDelete())
+ {
+ final AMQQueue q = queue;
+ queue.setExclusiveOwner(session);
+ final AMQProtocolSession.Task sessionCloseTask = new AMQProtocolSession.Task()
+ {
+ public void doTask(AMQProtocolSession session) throws AMQException
+ {
+ q.setExclusiveOwner(null);
+ }
+ };
+ session.addSessionCloseTask(sessionCloseTask);
+ queue.addQueueDeleteTask(new AMQQueue.Task() {
+ public void doTask(AMQQueue queue) throws AMQException
+ {
+ session.removeSessionCloseTask(sessionCloseTask);
+ }
+ });
+ }
if (autoRegister)
{
Exchange defaultExchange = exchangeRegistry.getDefaultExchange();
@@ -123,14 +143,18 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
}
}
}
- else if (queue.getOwner() != null && !session.getContextKey().equals(queue.getOwner()))
+ else if (queue.getPrincipalHolder() != null
+ && queue.getPrincipalHolder().getPrincipal() != null
+ && queue.getPrincipalHolder().getPrincipal().getName() != null
+ && (!queue.getPrincipalHolder().getPrincipal().getName().equals(session.getPrincipal().getName())
+ || ((!body.getPassive() && queue.getExclusiveOwner() != null && queue.getExclusiveOwner() != session))))
{
throw body.getChannelException(AMQConstant.ALREADY_EXISTS, "Cannot declare queue('" + queueName + "'),"
+ " as exclusive queue with same name "
+ "declared on another client ID('"
- + queue.getOwner() + "')");
- }
+ + queue.getPrincipalHolder().getPrincipal().getName() + "')");
+ }
AMQChannel channel = session.getChannel(channelId);
if (channel == null)
@@ -197,7 +221,7 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
}
});
}// if exclusive and not durable
-
+
return queue;
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java
index b397db9246..8417492171 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java
@@ -31,6 +31,7 @@ import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.security.access.Permission;
@@ -62,7 +63,7 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB
AMQProtocolSession session = stateManager.getProtocolSession();
VirtualHost virtualHost = session.getVirtualHost();
QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
- MessageStore store = virtualHost.getMessageStore();
+ DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
AMQQueue queue;
if (body.getQueue() == null)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java
index 2768518f53..3e0f2182b7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java
@@ -33,7 +33,6 @@ import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.security.access.Permission;
public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBody>
{
@@ -106,7 +105,7 @@ public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBod
throw body.getConnectionException(AMQConstant.ACCESS_REFUSED, "Permission denied");
}
- long purged = queue.clearQueue(channel.getStoreContext());
+ long purged = queue.clearQueue();
if(!body.getNowait())
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java
index 9b23d88838..abd2bccc8d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java
@@ -61,14 +61,12 @@ public class TxCommitHandler implements StateAwareMethodListener<TxCommitBody>
{
throw body.getChannelNotFoundException(channelId);
}
-
channel.commit();
MethodRegistry methodRegistry = session.getMethodRegistry();
AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody();
session.writeFrame(responseBody.generateFrame(channelId));
-
- channel.processReturns();
+
}
catch (AMQException e)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java
index 5f402f3fda..4643dee0a3 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java
@@ -44,9 +44,9 @@ public class TxRollbackHandler implements StateAwareMethodListener<TxRollbackBod
{
}
- public void methodReceived(AMQStateManager stateManager, TxRollbackBody body, int channelId) throws AMQException
+ public void methodReceived(AMQStateManager stateManager, TxRollbackBody body, final int channelId) throws AMQException
{
- AMQProtocolSession session = stateManager.getProtocolSession();
+ final AMQProtocolSession session = stateManager.getProtocolSession();
try
{
@@ -57,17 +57,22 @@ public class TxRollbackHandler implements StateAwareMethodListener<TxRollbackBod
throw body.getChannelNotFoundException(channelId);
}
- channel.rollback();
- MethodRegistry methodRegistry = session.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody();
- session.writeFrame(responseBody.generateFrame(channelId));
+ final MethodRegistry methodRegistry = session.getMethodRegistry();
+ final AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody();
+
+ Runnable task = new Runnable()
+ {
+
+ public void run()
+ {
+ session.writeFrame(responseBody.generateFrame(channelId));
+ }
+ };
+
+ channel.rollback(task);
- //Now resend all the unacknowledged messages back to the original subscribers.
- //(Must be done after the TxnRollback-ok response).
- // Why, are we not allowed to send messages back to client before the ok method?
- channel.resend(false);
}
catch (AMQException e)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java
index 4a486ae17e..d4d41bc1d4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java
@@ -68,7 +68,7 @@ public class AMQPChannelActor extends AbstractActor
*/
_logString = "[" + MessageFormat.format(ChannelLogSubject.CHANNEL_FORMAT,
session.getSessionID(),
- session.getAuthorizedID().getName(),
+ session.getPrincipal().getName(),
session.getRemoteAddress(),
session.getVirtualHost().getName(),
channel.getChannelId())
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPConnectionActor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPConnectionActor.java
index 432b1d8203..d459fc0f06 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPConnectionActor.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPConnectionActor.java
@@ -75,7 +75,7 @@ public class AMQPConnectionActor extends AbstractActor
{
_logString = "[" + MessageFormat.format(USER_FORMAT,
session.getSessionID(),
- session.getAuthorizedID().getName(),
+ session.getPrincipal().getName(),
session.getRemoteAddress())
+ "] ";
@@ -105,7 +105,7 @@ public class AMQPConnectionActor extends AbstractActor
*/
_logString = "[" + MessageFormat.format(ConnectionLogSubject.CONNECTION_FORMAT,
session.getSessionID(),
- session.getAuthorizedID().getName(),
+ session.getPrincipal().getName(),
session.getRemoteAddress(),
session.getVirtualHost().getName())
+ "] ";
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java
index df4da2a79e..3d31a705fe 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java
@@ -21,6 +21,9 @@
package org.apache.qpid.server.logging.actors;
import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.logging.LogMessage;
+import org.apache.qpid.server.logging.RootMessageLogger;
import java.util.EmptyStackException;
import java.util.Stack;
@@ -66,6 +69,8 @@ public class CurrentActor
}
};
+ private static LogActor _defaultActor;
+
/**
* Set a new LogActor to be the Current Actor
* <p/>
@@ -105,7 +110,12 @@ public class CurrentActor
}
catch (EmptyStackException ese)
{
- return null;
+ return _defaultActor;
}
}
+
+ public static void setDefault(LogActor defaultActor)
+ {
+ _defaultActor = defaultActor;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages.properties
index eafcb43cc0..1a2cb7251c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages.properties
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages.properties
@@ -61,13 +61,32 @@ MST-1001 = Created : {0}
# 0 - path
MST-1002 = Store location : {0}
MST-1003 = Closed
+MST-1004 = Recovery Start
+MST-1005 = Recovered {0,number} messages
+MST-1006 = Recovery Complete
+
+#ConfigStore
+# 0 - name
+CFG-1001 = Created : {0}
+# 0 - path
+CFG-1002 = Store location : {0}
+CFG-1003 = Closed
+CFG-1004 = Recovery Start
+CFG-1005 = Recovery Complete
+
+#TransactionLog
+# 0 - name
+TXN-1001 = Created : {0}
+# 0 - path
+TXN-1002 = Store location : {0}
+TXN-1003 = Closed
# 0 - queue name
-MST-1004 = Recovery Start[ : {0}]
+TXN-1004 = Recovery Start[ : {0}]
# 0 - count
# 1 - queue count
-MST-1005 = Recovered {0,number} messages for queue {1}
+TXN-1005 = Recovered {0,number} messages for queue {1}
# 0 - queue name
-MST-1006 = Recovery Complete[ : {0}]
+TXN-1006 = Recovery Complete[ : {0}]
#Connection
# 0 - Client id
@@ -83,12 +102,18 @@ CHN-1003 = Close
# 0 - bytes allowed in prefetch
# 1 - number of messagse.
CHN-1004 = Prefetch Size (bytes) {0,number} : Count {1,number}
+# 0 - queue causing flow control
+CHN-1005 = Flow Control Enforced (Queue {0})
+CHN-1006 = Flow Control Removed
#Queue
# 0 - owner
# 1 - priority
QUE-1001 = Create :[ Owner: {0}][ AutoDelete][ Durable][ Transient][ Priority: {1,number,#}]
QUE-1002 = Deleted
+QUE-1003 = Overfull : Size : {0,number} bytes, Capacity : {1,number}
+QUE-1004 = Underfull : Size : {0,number} bytes, Resume Capacity : {1,number}
+
#Exchange
# 0 - type
@@ -104,4 +129,4 @@ BND-1002 = Deleted
SUB-1001 = Create[ : Durable][ : Arguments : {0}]
SUB-1002 = Close
# 0 - The current subscription state
-SUB-1003 = State : {0} \ No newline at end of file
+SUB-1003 = State : {0}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties
index 9169a1a651..1a2cb7251c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties
@@ -16,173 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-# LogMessages used within the Java Broker as originally defined on the wiki:
-#
-# http://cwiki.apache.org/confluence/display/qpid/Status+Update+Design#StatusUpdateDesign-InitialStatusMessages
-#
-# Technical Notes:
-# This is a standard Java Properties file so white space is respected at the
-# end of the lines. This file is processed in a number of ways.
-# 1) ResourceBundle
-# This file is loaded through a ResourceBundle named LogMessages. the en_US
-# addition to the file is the localisation. Additional localisations can be
-# provided and will automatically be selected based on the <locale> value in
-# the config.xml. The default is en_US.
-#
-# 2) MessasgeFormat
-# Each entry is prepared with the Java Core MessageFormat methods. Therefore
-# most functionality you can do via MessageFormat can be done here:
-#
-# http://java.sun.com/javase/6/docs/api/java/text/MessageFormat.html
-#
-# The cavet here is that only default String and number FormatTypes can be used.
-# This is due to the processing described in 3 below. If support for date, time
-# or choice is requried then the GenerateLogMessages class should be updated to
-# provide support.
-#
-# Format Note:
-# As mentioned earlier white space in this file is very important. One thing
-# in particular to note is the way MessageFormat peforms its replacements.
-# The replacement text will totally replace the {xxx} section so there will be
-# no addtion of white space or removal e.g.
-# MSG = Text----{0}----
-# When given parameter 'Hello' result in text:
-# Text----Hello----
-#
-# For simple arguments this is expected however when using Style formats then
-# it can be a little unexepcted. In particular a common pattern is used for
-# number replacements : {0,number,#}. This is used in the Broker to display an
-# Integer simply as the Integer with no formating. e.g new Integer(1234567)
-# becomes the String "1234567" which is can be contrasted with the pattern
-# without a style format field : {0,number} which becomes string "1,234,567".
-#
-# What you may not expect is that {0,number, #} would produce the String " 1234567"
-# note the space after the ',' here /\ has resulted in a space /\ in
-# the output.
-#
-# More details on the SubformatPattern can be found on the API link above.
-#
-# 3) GenerateLogMessage/Velocity Macro
-# This is the first and final stage of processing that this file goes through.
-# 1) Class Generation:
-# The GenerateLogMessage processes this file and uses the velocity Macro
-# to create classes with static methods to perform the logging and give us
-# compile time validation.
-#
-# 2) Property Processing:
-# During the class generation the message properties ({x}) are identified
-# and used to create the method signature.
-#
-# 3) Option Processing:
-# The Classes perform final formatting of the messages at runtime based on
-# optional parameters that are defined within the message. Optional
-# paramters are enclosed in square brackets e.g. [optional].
-#
-# To provide fixed log messages as required by the Technical Specification:
-# http://cwiki.apache.org/confluence/display/qpid/Operational+Logging+-+Status+Update+-+Technical+Specification#OperationalLogging-StatusUpdate-TechnicalSpecification-Howtoprovidefixedlogmessages
-#
-# This file is processed by Velocity to create a number of classes that contain
-# static methods that provide LogMessages in the code to provide compile time
-# validation.
-#
-# For details of what processing is done see GenerateLogMessages.
-#
-# What a localiser or developer need know is the following:
-#
-# The Property structure is important is it defines how the class and methods
-# will be built.
-#
-# Class Generation:
-# =================
-#
-# Each class of messages will be split in to their own <Class>Messages.java
-# Currently the following classes are created and are populated with the
-# messages that bear their 3-digit type identifier:
-#
-# Class | Type
-# ---------------------|--------
-# Broker | BKR
-# ManagementConsole | MNG
-# VirtualHost | VHT
-# MessageStore | MST
-# Connection | CON
-# Channel | CHN
-# Queue | QUE
-# Exchange | EXH
-# Binding | BND
-# Subscription | SUB
-#
-# Property Processing:
-# ====================
-#
-# Each property is then processed by the GenerateLogMessages class to identify
-# The number and type of parameters, {x} entries. Parameters are defaulted to
-# String types but the use of FormatType number (e.g.{0,number}) will result
-# in a Number type being used. These parameters are then used to build the
-# method parameter list. e.g:
-# Property:
-# BRK-1003 = Shuting down : {0} port {1,number,#}
-# becomes Method:
-# public static LogMessage BRK_1003(String param1, Number param2)
-#
-# This improves our compile time validation of log message content and
-# ensures that change in the message format does not accidentally cause
-# erroneous messages.
-#
-# Option Processing:
-# ====================
-#
-# Options are identified in the log message as being surrounded by square
-# brackets ([ ]). These optional values can themselves contain paramters
-# however nesting of options is not permitted. Identification is performed on
-# first matchings so give the message:
-# Msg = Log Message [option1] [option2]
-# Two options will be identifed and enabled to select text 'option1 and
-# 'option2'.
-#
-# The nesting of a options is not supported and will provide
-# unexpected results. e.g. Using Message:
-# Msg = Log Message [option1 [sub-option2]]
-#
-# The options will be 'option1 [sub-option2' and 'sub-option2'. The first
-# option includes the second option as the nesting is not detected.
-#
-# The detected options are presented in the method signature as boolean options
-# numerically identified by their position in the message. e.g.
-# Property:
-# CON-1001 = Open : Client ID {0} [: Protocol Version : {1}]
-# becomes Method:
-# public static LogMessage CON_1001(String param1, String param2, boolean opt1)
-#
-# The value of 'opt1' will show/hide the option in the message. Note that
-# 'param2' is still required however a null value can be used if the optional
-# section is not desired.
-#
-# Again here the importance of white space needs to be highlighted.
-# Looking at the QUE-1001 message as an example. The first thought on how this
-# would look would be as follows:
-# QUE-1001 = Create : Owner: {0} [AutoDelete] [Durable] [Transient] [Priority: {1,number,#}]
-# Each option is correctly defined so the text that is defined will appear when
-# selected. e.g. 'AutoDelete'. However, what may not be immediately apparent is
-# the white space. Using the above definition of QUE-1001 if we were to print
-# the message with only the Priority option displayed it would appear as this:
-# "Create : Owner: guest Priority: 1"
-# Note the spaces here /\ This is because only the text between the brackets
-# has been removed.
-#
-# Each option needs to include white space to correctly format the message. So
-# the correct definition of QUE-1001 is as follows:
-# QUE-1001 = Create : Owner: {0}[ AutoDelete][ Durable][ Transient][ Priority: {1,number,#}]
-# Note that white space is included with each option and there is no extra
-# white space between the options. As a result the output with just Priority
-# enabled is as follows:
-# "Create : Owner: guest Priority: 1"
-#
-# The final processing that is done in the generation is the conversion of the
-# property name. As a '-' is an illegal character in the method name it is
-# converted to '_' This processing gives the final method signature as follows:
-# <Class>Message.<Type>_<Number>(<parmaters>,<options>)
-#
+# Default File used for all non-defined locales.
#Broker
# 0 - Version
# 1 = Build
@@ -227,13 +61,32 @@ MST-1001 = Created : {0}
# 0 - path
MST-1002 = Store location : {0}
MST-1003 = Closed
+MST-1004 = Recovery Start
+MST-1005 = Recovered {0,number} messages
+MST-1006 = Recovery Complete
+
+#ConfigStore
+# 0 - name
+CFG-1001 = Created : {0}
+# 0 - path
+CFG-1002 = Store location : {0}
+CFG-1003 = Closed
+CFG-1004 = Recovery Start
+CFG-1005 = Recovery Complete
+
+#TransactionLog
+# 0 - name
+TXN-1001 = Created : {0}
+# 0 - path
+TXN-1002 = Store location : {0}
+TXN-1003 = Closed
# 0 - queue name
-MST-1004 = Recovery Start[ : {0}]
+TXN-1004 = Recovery Start[ : {0}]
# 0 - count
# 1 - queue count
-MST-1005 = Recovered {0,number} messages for queue {1}
+TXN-1005 = Recovered {0,number} messages for queue {1}
# 0 - queue name
-MST-1006 = Recovery Complete[ : {0}]
+TXN-1006 = Recovery Complete[ : {0}]
#Connection
# 0 - Client id
@@ -247,8 +100,9 @@ CHN-1001 = Create
CHN-1002 = Flow {0}
CHN-1003 = Close
# 0 - bytes allowed in prefetch
-# 1 - number of messagse.
+# 1 - number of messagse.
CHN-1004 = Prefetch Size (bytes) {0,number} : Count {1,number}
+# 0 - queue causing flow control
CHN-1005 = Flow Control Enforced (Queue {0})
CHN-1006 = Flow Control Removed
@@ -260,6 +114,7 @@ QUE-1002 = Deleted
QUE-1003 = Overfull : Size : {0,number} bytes, Capacity : {1,number}
QUE-1004 = Underfull : Size : {0,number} bytes, Resume Capacity : {1,number}
+
#Exchange
# 0 - type
# 1 - name
@@ -273,4 +128,5 @@ BND-1002 = Deleted
#Subscription
SUB-1001 = Create[ : Durable][ : Arguments : {0}]
SUB-1002 = Close
+# 0 - The current subscription state
SUB-1003 = State : {0}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java
index 1b22de6d01..03afd0b772 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java
@@ -46,7 +46,7 @@ public class ChannelLogSubject extends AbstractLogSubject
// Provide the value for the 4th replacement.
setLogStringWithFormat(CHANNEL_FORMAT,
session.getSessionID(),
- session.getAuthorizedID().getName(),
+ session.getPrincipal().getName(),
session.getRemoteAddress(),
session.getVirtualHost().getName(),
channel.getChannelId());
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java
index e07dbcda23..65d65a24d2 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java
@@ -41,7 +41,7 @@ public class ConnectionLogSubject extends AbstractLogSubject
public ConnectionLogSubject(AMQProtocolSession session)
{
setLogStringWithFormat(CONNECTION_FORMAT, session.getSessionID(),
- session.getAuthorizedID().getName(),
+ session.getPrincipal().getName(),
session.getRemoteAddress(),
session.getVirtualHost().getName());
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java
index 67aee90ba4..d72b8f24ec 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -65,16 +65,9 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
return null;
}
- public void register() throws AMQException
+ public void register() throws JMException
{
- try
- {
- getManagedObjectRegistry().registerObject(this);
- }
- catch (JMException e)
- {
- throw new AMQException("Error registering managed object " + this + ": " + e, e);
- }
+ getManagedObjectRegistry().registerObject(this);
}
protected ManagedObjectRegistry getManagedObjectRegistry()
@@ -98,7 +91,7 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
{
return getObjectInstanceName() + "[" + getType() + "]";
}
-
+
/**
* Created the ObjectName as per the JMX Specs
@@ -140,7 +133,7 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
objectName.append(",");
objectName.append("version=").append(_version);
-
+
return new ObjectName(objectName.toString());
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
index aea9ab43ea..92657d7f3c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
@@ -54,6 +54,7 @@ import java.lang.reflect.Proxy;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
+import java.net.UnknownHostException;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
@@ -236,8 +237,17 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
* The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer
* on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's.
*/
- final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(port+PORT_EXPORT_OFFSET, csf, ssf, env);
- final String hostname = InetAddress.getLocalHost().getHostName();
+ final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(port+PORT_EXPORT_OFFSET, csf, ssf, env);
+ String localHost;
+ try
+ {
+ localHost = InetAddress.getLocalHost().getHostName();
+ }
+ catch(UnknownHostException ex)
+ {
+ localHost="127.0.0.1";
+ }
+ final String hostname = localHost;
final JMXServiceURL externalUrl = new JMXServiceURL(
"service:jmx:rmi://"+hostname+":"+(port+PORT_EXPORT_OFFSET)+"/jndi/rmi://"+hostname+":"+port+"/jmxrmi");
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java
index 42ea8921a4..de14785fb0 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -22,6 +22,7 @@ package org.apache.qpid.server.management;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
+import javax.management.JMException;
import org.apache.qpid.AMQException;
@@ -45,7 +46,7 @@ public interface ManagedObject
ManagedObject getParentObject();
- void register() throws AMQException;
+ void register() throws AMQException, JMException;
void unregister() throws AMQException;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java
new file mode 100644
index 0000000000..b8a36aba58
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java
@@ -0,0 +1,329 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.message;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.queue.AMQQueue;
+
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.nio.ByteBuffer;
+
+/**
+ * A deliverable message.
+ */
+public class AMQMessage implements ServerMessage
+{
+ /** Used for debugging purposes. */
+ private static final Logger _log = Logger.getLogger(AMQMessage.class);
+
+ private final AtomicInteger _referenceCount = new AtomicInteger(0);
+
+ /** Flag to indicate that this message requires 'immediate' delivery. */
+
+ private static final byte IMMEDIATE = 0x01;
+
+ /**
+ * Flag to indicate whether this message has been delivered to a consumer. Used in implementing return functionality
+ * for messages published with the 'immediate' flag.
+ */
+
+ private static final byte DELIVERED_TO_CONSUMER = 0x02;
+
+ private byte _flags = 0;
+
+ private long _expiration;
+
+ private final long _size;
+
+ private Object _sessionIdentifier;
+ private static final byte IMMEDIATE_AND_DELIVERED = (byte) (IMMEDIATE | DELIVERED_TO_CONSUMER);
+
+ private final StoredMessage<MessageMetaData> _handle;
+
+
+ public AMQMessage(StoredMessage<MessageMetaData> handle)
+ {
+ _handle = handle;
+ final MessageMetaData metaData = handle.getMetaData();
+ _size = metaData.getContentSize();
+ final MessagePublishInfo messagePublishInfo = metaData.getMessagePublishInfo();
+
+ if(messagePublishInfo.isImmediate())
+ {
+ _flags |= IMMEDIATE;
+ }
+ }
+
+
+ public String debugIdentity()
+ {
+ return "(HC:" + System.identityHashCode(this) + " ID:" + getMessageId() + " Ref:" + _referenceCount.get() + ")";
+ }
+
+ public void setExpiration(final long expiration)
+ {
+
+ _expiration = expiration;
+
+ }
+
+ public boolean isReferenced()
+ {
+ return _referenceCount.get() > 0;
+ }
+
+ public MessageMetaData getMessageMetaData()
+ {
+ return _handle.getMetaData();
+ }
+
+ public ContentHeaderBody getContentHeaderBody() throws AMQException
+ {
+ return getMessageMetaData().getContentHeaderBody();
+ }
+
+
+
+ public Long getMessageId()
+ {
+ return _handle.getMessageNumber();
+ }
+
+ /**
+ * Creates a long-lived reference to this message, and increments the count of such references, as an atomic
+ * operation.
+ */
+ public AMQMessage takeReference()
+ {
+ incrementReference(); // _referenceCount.incrementAndGet();
+
+ return this;
+ }
+
+ public boolean incrementReference()
+ {
+ return incrementReference(1);
+ }
+
+ /* Threadsafe. Increment the reference count on the message. */
+ public boolean incrementReference(int count)
+ {
+
+ if(_referenceCount.addAndGet(count) <= 0)
+ {
+ _referenceCount.addAndGet(-count);
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+
+ }
+
+ /**
+ * Threadsafe. This will decrement the reference count and when it reaches zero will remove the message from the
+ * message store.
+ *
+ *
+ * @throws org.apache.qpid.server.queue.MessageCleanupException when an attempt was made to remove the message from the message store and that
+ * failed
+ */
+ public void decrementReference()
+ {
+ int count = _referenceCount.decrementAndGet();
+
+ // note that the operation of decrementing the reference count and then removing the message does not
+ // have to be atomic since the ref count starts at 1 and the exchange itself decrements that after
+ // the message has been passed to all queues. i.e. we are
+ // not relying on the all the increments having taken place before the delivery manager decrements.
+ if (count == 0)
+ {
+ // set the reference count way below 0 so that we can detect that the message has been deleted
+ // this is to guard against the message being spontaneously recreated (from the mgmt console)
+ // by copying from other queues at the same time as it is being removed.
+ _referenceCount.set(Integer.MIN_VALUE/2);
+
+ // must check if the handle is null since there may be cases where we decide to throw away a message
+ // and the handle has not yet been constructed
+ if (_handle != null)
+ {
+ _handle.remove();
+
+ }
+ }
+ else
+ {
+ if (count < 0)
+ {
+ throw new RuntimeException("Reference count for message id " + debugIdentity()
+ + " has gone below 0.");
+ }
+ }
+ }
+
+
+ /**
+ * Called selectors to determin if the message has already been sent
+ *
+ * @return _deliveredToConsumer
+ */
+ public boolean getDeliveredToConsumer()
+ {
+ return (_flags & DELIVERED_TO_CONSUMER) != 0;
+ }
+
+ public String getRoutingKey()
+ {
+ // TODO
+ return null;
+ }
+
+ public AMQMessageHeader getMessageHeader()
+ {
+ return getMessageMetaData().getMessageHeader();
+ }
+
+ public boolean isPersistent()
+ {
+ return getMessageMetaData().isPersistent();
+ }
+
+ /**
+ * Called to enforce the 'immediate' flag.
+ *
+ * @returns true if the message is marked for immediate delivery but has not been marked as delivered
+ * to a consumer
+ */
+ public boolean immediateAndNotDelivered()
+ {
+
+ return (_flags & IMMEDIATE_AND_DELIVERED) == IMMEDIATE;
+
+ }
+
+ public MessagePublishInfo getMessagePublishInfo() throws AMQException
+ {
+ return getMessageMetaData().getMessagePublishInfo();
+ }
+
+ public long getArrivalTime()
+ {
+ return getMessageMetaData().getArrivalTime();
+ }
+
+ /**
+ * Checks to see if the message has expired. If it has the message is dequeued.
+ *
+ * @param queue The queue to check the expiration against. (Currently not used)
+ *
+ * @return true if the message has expire
+ *
+ * @throws AMQException
+ */
+ public boolean expired(AMQQueue queue) throws AMQException
+ {
+
+ if (_expiration != 0L)
+ {
+ long now = System.currentTimeMillis();
+
+ return (now > _expiration);
+ }
+
+ return false;
+ }
+
+ /**
+ * Called when this message is delivered to a consumer. (used to implement the 'immediate' flag functionality).
+ * And for selector efficiency.
+ */
+ public void setDeliveredToConsumer()
+ {
+ _flags |= DELIVERED_TO_CONSUMER;
+ }
+
+ public long getSize()
+ {
+ return _size;
+
+ }
+
+ public boolean isImmediate()
+ {
+ return (_flags & IMMEDIATE) == IMMEDIATE;
+ }
+
+ public long getExpiration()
+ {
+ return _expiration;
+ }
+
+ public MessageReference newReference()
+ {
+ return new AMQMessageReference(this);
+ }
+
+ public Long getMessageNumber()
+ {
+ return getMessageId();
+ }
+
+
+ public Object getPublisherIdentifier()
+ {
+ //todo store sessionIdentifier/client id with message in store
+ //Currently the _sessionIdentifier will be null if the message has been
+ // restored from a message Store
+
+ return _sessionIdentifier;
+
+ }
+
+ public void setClientIdentifier(final Object sessionIdentifier)
+ {
+ _sessionIdentifier = sessionIdentifier;
+ }
+
+
+ public String toString()
+ {
+ // return "Message[" + debugIdentity() + "]: " + _messageId + "; ref count: " + _referenceCount + "; taken : " +
+ // _taken + " by :" + _takenBySubcription;
+
+ return "Message[" + debugIdentity() + "]: " + getMessageId() + "; ref count: " + _referenceCount;
+ }
+
+ public int getContent(ByteBuffer buf, int offset)
+ {
+ return _handle.getContent(offset, buf);
+ }
+
+ public StoredMessage<MessageMetaData> getStoredMessage()
+ {
+ return _handle;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java
new file mode 100644
index 0000000000..6c9311c3de
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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.util.Set;
+
+public interface AMQMessageHeader
+{
+ String getCorrelationId();
+
+ long getExpiration();
+
+ String getMessageId();
+
+ String getMimeType();
+
+ String getEncoding();
+
+ byte getPriority();
+
+ long getTimestamp();
+
+ String getType();
+
+ String getReplyTo();
+
+ Object getHeader(String name);
+
+ boolean containsHeaders(Set<String> names);
+
+ boolean containsHeader(String name);
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java
index 0b214ca336..940caaefe4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java
@@ -18,29 +18,27 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.message;
-import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.queue.MessageCleanupException;
-/**
- * Constructs a message handle based on the publish body, the content header and the queue to which the message
- * has been routed.
- *
- * @author Robert Greig (robert.j.greig@jpmorgan.com)
- */
-public class MessageHandleFactory
+public class AMQMessageReference extends MessageReference<AMQMessage>
{
- public AMQMessageHandle createMessageHandle(Long messageId, MessageStore store, boolean persistent)
+
+ public AMQMessageReference(AMQMessage message)
+ {
+ super(message);
+ }
+
+ protected void onReference(AMQMessage message)
+ {
+ message.incrementReference();
+ }
+
+ protected void onRelease(AMQMessage message)
{
- // just hardcoded for now
- if (persistent)
- {
- return new WeakReferenceMessageHandle(messageId, store);
- }
- else
- {
- return new InMemoryMessageHandle(messageId);
- }
+ message.decrementReference();
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java
new file mode 100644
index 0000000000..4a1f8dd191
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java
@@ -0,0 +1,114 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.message;
+
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.FieldTable;
+
+import java.util.Set;
+
+public class ContentHeaderBodyAdapter implements AMQMessageHeader
+{
+ private final ContentHeaderBody _contentHeaderBody;
+
+ public ContentHeaderBodyAdapter(ContentHeaderBody contentHeaderBody)
+ {
+ _contentHeaderBody = contentHeaderBody;
+ }
+
+ private BasicContentHeaderProperties getProperties()
+ {
+ return (BasicContentHeaderProperties) _contentHeaderBody.properties;
+ }
+
+ public String getCorrelationId()
+ {
+ return getProperties().getCorrelationIdAsString();
+ }
+
+ public long getExpiration()
+ {
+ return getProperties().getExpiration();
+ }
+
+ public String getMessageId()
+ {
+ return getProperties().getMessageIdAsString();
+ }
+
+ public String getMimeType()
+ {
+ return getProperties().getContentTypeAsString();
+ }
+
+ public String getEncoding()
+ {
+ return getProperties().getEncodingAsString();
+ }
+
+ public byte getPriority()
+ {
+ return getProperties().getPriority();
+ }
+
+ public long getTimestamp()
+ {
+ return getProperties().getTimestamp();
+ }
+
+ public String getType()
+ {
+ return getProperties().getTypeAsString();
+ }
+
+ public String getReplyTo()
+ {
+ return getProperties().getReplyToAsString();
+ }
+
+ public Object getHeader(String name)
+ {
+ FieldTable ft = getProperties().getHeaders();
+ return ft.get(name);
+ }
+
+ public boolean containsHeaders(Set<String> names)
+ {
+ FieldTable ft = getProperties().getHeaders();
+ for(String name : names)
+ {
+ if(!ft.containsKey(name))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean containsHeader(String name)
+ {
+ FieldTable ft = getProperties().getHeaders();
+ return ft.containsKey(name);
+ }
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.java
new file mode 100755
index 0000000000..c32f80fc5b
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/EnqueableMessage.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.message;
+
+public interface EnqueableMessage
+{
+ Long getMessageNumber();
+ boolean isPersistent();
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessageHandle.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java
index bdb0707c27..1b3fdb1870 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessageHandle.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java
@@ -18,20 +18,20 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.message;
-import org.apache.qpid.server.store.StoreContext;
-public class MockAMQMessageHandle extends InMemoryMessageHandle
+import org.apache.qpid.server.queue.Filterable;
+
+public interface InboundMessage extends Filterable
{
- public MockAMQMessageHandle(final Long messageId)
- {
- super(messageId);
- }
+ String getRoutingKey();
+
+ AMQMessageHeader getMessageHeader();
+
+ boolean isPersistent();
+
+ boolean isRedelivered();
- @Override
- public long getBodySize(StoreContext store)
- {
- return 0l;
- }
+ long getSize();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.java
new file mode 100755
index 0000000000..08a09c4a85
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageContentSource.java
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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;
+
+public interface MessageContentSource
+{
+ public int getContent(ByteBuffer buf, int offset);
+
+ long getSize();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java
new file mode 100644
index 0000000000..b34a8fc470
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java
@@ -0,0 +1,309 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.message;
+
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.EncodingUtils;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.server.store.StorableMessageMetaData;
+import org.apache.qpid.server.store.MessageMetaDataType;
+import org.apache.qpid.AMQException;
+
+import java.nio.ByteBuffer;
+import java.util.Set;
+
+/**
+ * Encapsulates a publish body and a content header. In the context of the message store these are treated as a
+ * single unit.
+ */
+public class MessageMetaData implements StorableMessageMetaData
+{
+ private MessagePublishInfo _messagePublishInfo;
+
+ private ContentHeaderBody _contentHeaderBody;
+
+ private int _contentChunkCount;
+
+ private long _arrivalTime;
+ private static final byte MANDATORY_FLAG = 1;
+ private static final byte IMMEDIATE_FLAG = 2;
+ public static final MessageMetaDataType.Factory<MessageMetaData> FACTORY = new MetaDataFactory();
+
+ public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount)
+ {
+ this(publishBody,contentHeaderBody, contentChunkCount, System.currentTimeMillis());
+ }
+
+ public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount, long arrivalTime)
+ {
+ _contentHeaderBody = contentHeaderBody;
+ _messagePublishInfo = publishBody;
+ _contentChunkCount = contentChunkCount;
+ _arrivalTime = arrivalTime;
+ }
+
+ public int getContentChunkCount()
+ {
+ return _contentChunkCount;
+ }
+
+ public void setContentChunkCount(int contentChunkCount)
+ {
+ _contentChunkCount = contentChunkCount;
+ }
+
+ public ContentHeaderBody getContentHeaderBody()
+ {
+ return _contentHeaderBody;
+ }
+
+ public void setContentHeaderBody(ContentHeaderBody contentHeaderBody)
+ {
+ _contentHeaderBody = contentHeaderBody;
+ }
+
+ public MessagePublishInfo getMessagePublishInfo()
+ {
+ return _messagePublishInfo;
+ }
+
+ public void setMessagePublishInfo(MessagePublishInfo messagePublishInfo)
+ {
+ _messagePublishInfo = messagePublishInfo;
+ }
+
+ public long getArrivalTime()
+ {
+ return _arrivalTime;
+ }
+
+ public void setArrivalTime(long arrivalTime)
+ {
+ _arrivalTime = arrivalTime;
+ }
+
+ public MessageMetaDataType getType()
+ {
+ return MessageMetaDataType.META_DATA_0_8;
+ }
+
+ public int getStorableSize()
+ {
+ BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.properties);
+ int size = _contentHeaderBody.getSize();
+ size += 4;
+ size += EncodingUtils.encodedShortStringLength(_messagePublishInfo.getExchange());
+ size += EncodingUtils.encodedShortStringLength(_messagePublishInfo.getRoutingKey());
+ size += 1; // flags for immediate/mandatory
+ size += EncodingUtils.encodedLongLength();
+
+ return size;
+ }
+
+ public int writeToBuffer(int offset, ByteBuffer dest)
+ {
+ ByteBuffer src = ByteBuffer.allocate((int)getStorableSize());
+
+ org.apache.mina.common.ByteBuffer minaSrc = org.apache.mina.common.ByteBuffer.wrap(src);
+ EncodingUtils.writeInteger(minaSrc, _contentHeaderBody.getSize());
+ _contentHeaderBody.writePayload(minaSrc);
+ EncodingUtils.writeShortStringBytes(minaSrc, _messagePublishInfo.getExchange());
+ EncodingUtils.writeShortStringBytes(minaSrc, _messagePublishInfo.getRoutingKey());
+ byte flags = 0;
+ if(_messagePublishInfo.isMandatory())
+ {
+ flags |= MANDATORY_FLAG;
+ }
+ if(_messagePublishInfo.isImmediate())
+ {
+ flags |= IMMEDIATE_FLAG;
+ }
+ EncodingUtils.writeByte(minaSrc, flags);
+ EncodingUtils.writeLong(minaSrc,_arrivalTime);
+ src.position(minaSrc.position());
+ src.flip();
+ src.position(offset);
+ src = src.slice();
+ if(dest.remaining() < src.limit())
+ {
+ src.limit(dest.remaining());
+ }
+ dest.put(src);
+
+
+ return src.limit();
+ }
+
+ public int getContentSize()
+ {
+ return (int) _contentHeaderBody.bodySize;
+ }
+
+ public boolean isPersistent()
+ {
+ BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.properties);
+ return properties.getDeliveryMode() == BasicContentHeaderProperties.PERSISTENT;
+ }
+
+ private static class MetaDataFactory implements MessageMetaDataType.Factory
+ {
+
+
+ public MessageMetaData createMetaData(ByteBuffer buf)
+ {
+ try
+ {
+ org.apache.mina.common.ByteBuffer minaSrc = org.apache.mina.common.ByteBuffer.wrap(buf);
+ int size = EncodingUtils.readInteger(minaSrc);
+ ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(minaSrc, size);
+ final AMQShortString exchange = EncodingUtils.readAMQShortString(minaSrc);
+ final AMQShortString routingKey = EncodingUtils.readAMQShortString(minaSrc);
+
+ final byte flags = EncodingUtils.readByte(minaSrc);
+ long arrivalTime = EncodingUtils.readLong(minaSrc);
+
+ MessagePublishInfo publishBody =
+ new MessagePublishInfo()
+ {
+
+ public AMQShortString getExchange()
+ {
+ return exchange;
+ }
+
+ public void setExchange(AMQShortString exchange)
+ {
+ }
+
+ public boolean isImmediate()
+ {
+ return (flags & IMMEDIATE_FLAG) != 0;
+ }
+
+ public boolean isMandatory()
+ {
+ return (flags & MANDATORY_FLAG) != 0;
+ }
+
+ public AMQShortString getRoutingKey()
+ {
+ return routingKey;
+ }
+ };
+ return new MessageMetaData(publishBody, chb, 0, arrivalTime);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ }
+ };
+
+ public AMQMessageHeader getMessageHeader()
+ {
+ return new MessageHeaderAdapter();
+ }
+
+ private final class MessageHeaderAdapter implements AMQMessageHeader
+ {
+ private BasicContentHeaderProperties getProperties()
+ {
+ return (BasicContentHeaderProperties) getContentHeaderBody().properties;
+ }
+
+ public String getCorrelationId()
+ {
+ return getProperties().getCorrelationIdAsString();
+ }
+
+ public long getExpiration()
+ {
+ return getProperties().getExpiration();
+ }
+
+ public String getMessageId()
+ {
+ return getProperties().getMessageIdAsString();
+ }
+
+ public String getMimeType()
+ {
+ return getProperties().getContentTypeAsString();
+ }
+
+ public String getEncoding()
+ {
+ return getProperties().getEncodingAsString();
+ }
+
+ public byte getPriority()
+ {
+ return getProperties().getPriority();
+ }
+
+ public long getTimestamp()
+ {
+ return getProperties().getTimestamp();
+ }
+
+ public String getType()
+ {
+ return getProperties().getTypeAsString();
+ }
+
+ public String getReplyTo()
+ {
+ return getProperties().getReplyToAsString();
+ }
+
+ public Object getHeader(String name)
+ {
+ FieldTable ft = getProperties().getHeaders();
+ return ft.get(name);
+ }
+
+ public boolean containsHeaders(Set<String> names)
+ {
+ FieldTable ft = getProperties().getHeaders();
+ for(String name : names)
+ {
+ if(!ft.containsKey(name))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean containsHeader(String name)
+ {
+ FieldTable ft = getProperties().getHeaders();
+ return ft.containsKey(name);
+ }
+
+
+
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
new file mode 100755
index 0000000000..5a5e2fe5b4
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
@@ -0,0 +1,242 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.message;
+
+import org.apache.qpid.server.store.StorableMessageMetaData;
+import org.apache.qpid.server.store.MessageMetaDataType;
+import org.apache.qpid.transport.MessageTransfer;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageDeliveryMode;
+import org.apache.qpid.transport.Struct;
+import org.apache.qpid.transport.codec.BBEncoder;
+import org.apache.qpid.transport.codec.BBDecoder;
+
+import java.nio.ByteBuffer;
+import java.lang.ref.WeakReference;
+
+public class MessageMetaData_0_10 implements StorableMessageMetaData
+{
+ private Header _header;
+ private DeliveryProperties _deliveryProps;
+ private MessageProperties _messageProps;
+ private MessageTransferHeader _messageHeader;
+ private long _arrivalTime;
+ private int _bodySize;
+ private volatile WeakReference<ByteBuffer> _body;
+
+ private static final int ENCODER_SIZE = 1 << 16;
+
+ public static final MessageMetaDataType.Factory<MessageMetaData_0_10> FACTORY = new MetaDataFactory();
+
+ private volatile ByteBuffer _encoded;
+
+
+ public MessageMetaData_0_10(MessageTransfer xfr)
+ {
+ this(xfr.getHeader(), xfr.getBodySize(), xfr.getBody(), System.currentTimeMillis());
+ }
+
+ private MessageMetaData_0_10(Header header, int bodySize, long arrivalTime)
+ {
+ this(header, bodySize, null, arrivalTime);
+ }
+
+ private MessageMetaData_0_10(Header header, int bodySize, ByteBuffer xfrBody, long arrivalTime)
+ {
+ _header = header;
+ if(_header != null)
+ {
+ _deliveryProps = _header.get(DeliveryProperties.class);
+ _messageProps = _header.get(MessageProperties.class);
+ }
+ else
+ {
+ _deliveryProps = null;
+ _messageProps = null;
+ }
+ _messageHeader = new MessageTransferHeader(_deliveryProps, _messageProps);
+ _arrivalTime = arrivalTime;
+ _bodySize = bodySize;
+
+
+
+ if(xfrBody == null)
+ {
+ _body = null;
+ }
+ else
+ {
+ ByteBuffer body = ByteBuffer.allocate(_bodySize);
+ body.put(xfrBody);
+ body.flip();
+ _body = new WeakReference(body);
+ }
+
+
+ }
+
+
+
+ public MessageMetaDataType getType()
+ {
+ return MessageMetaDataType.META_DATA_0_10;
+ }
+
+ public int getStorableSize()
+ {
+ ByteBuffer buf = _encoded;
+
+ if(buf == null)
+ {
+ buf = encodeAsBuffer();
+ _encoded = buf;
+ }
+
+ //TODO -- need to add stuff
+ return buf.limit();
+ }
+
+ private ByteBuffer encodeAsBuffer()
+ {
+ BBEncoder encoder = new BBEncoder(ENCODER_SIZE);
+
+ encoder.writeInt64(_arrivalTime);
+ encoder.writeInt32(_bodySize);
+ Struct[] headers = _header == null ? new Struct[0] : _header.getStructs();
+ encoder.writeInt32(headers.length);
+
+
+ for(Struct header : headers)
+ {
+ encoder.writeStruct32(header);
+
+ }
+
+ ByteBuffer buf = encoder.buffer();
+ 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()
+ {
+ return _bodySize;
+ }
+
+ public boolean isPersistent()
+ {
+ return _deliveryProps == null ? false : _deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT;
+ }
+
+ public String getRoutingKey()
+ {
+ return _deliveryProps == null ? null : _deliveryProps.getRoutingKey();
+ }
+
+ public AMQMessageHeader getMessageHeader()
+ {
+ return _messageHeader;
+ }
+
+ public long getSize()
+ {
+
+ return _bodySize;
+ }
+
+ public boolean isImmediate()
+ {
+ return _deliveryProps != null && _deliveryProps.getImmediate();
+ }
+
+ public long getExpiration()
+ {
+ return _deliveryProps == null ? 0L : _deliveryProps.getExpiration();
+ }
+
+ public long getArrivalTime()
+ {
+ return _arrivalTime;
+ }
+
+ public Header getHeader()
+ {
+ return _header;
+ }
+
+ public ByteBuffer getBody()
+ {
+ ByteBuffer body = _body == null ? null : _body.get();
+ return body;
+ }
+
+ public void setBody(ByteBuffer body)
+ {
+ _body = new WeakReference(body);
+ }
+
+ private static class MetaDataFactory implements MessageMetaDataType.Factory<MessageMetaData_0_10>
+ {
+ public MessageMetaData_0_10 createMetaData(ByteBuffer buf)
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(buf);
+
+ long arrivalTime = decoder.readInt64();
+ int bodySize = decoder.readInt32();
+ int headerCount = decoder.readInt32();
+
+ Struct[] headers = new Struct[headerCount];
+
+ for(int i = 0 ; i < headerCount; i++)
+ {
+ headers[i] = decoder.readStruct32();
+ }
+
+ Header header = new Header(headers);
+
+ return new MessageMetaData_0_10(header, bodySize, arrivalTime);
+
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageReference.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageReference.java
new file mode 100644
index 0000000000..055403ff08
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageReference.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.message;
+
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+public abstract class MessageReference<M extends ServerMessage>
+{
+
+ private static final AtomicReferenceFieldUpdater<MessageReference, ServerMessage> _messageUpdater =
+ AtomicReferenceFieldUpdater.newUpdater(MessageReference.class, ServerMessage.class,"_message");
+
+ private volatile M _message;
+
+ public MessageReference(M message)
+ {
+ _message = message;
+ onReference(message);
+ }
+
+ abstract protected void onReference(M message);
+
+ abstract protected void onRelease(M message);
+
+ public M getMessage()
+ {
+ return _message;
+ }
+
+ public void release()
+ {
+ M message = (M) _messageUpdater.getAndSet(this,null);
+ if(message != null)
+ {
+ onRelease(message);
+ }
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java
new file mode 100644
index 0000000000..1a75d7ca65
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java
@@ -0,0 +1,112 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.message;
+
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.MessageDeliveryPriority;
+
+import java.util.Set;
+import java.util.Map;
+
+class MessageTransferHeader implements AMQMessageHeader
+{
+
+
+ public static final String JMS_TYPE = "x-jms-type";
+
+ private final DeliveryProperties _deliveryProps;
+ private final MessageProperties _messageProps;
+
+ public MessageTransferHeader(DeliveryProperties deliveryProps, MessageProperties messageProps)
+ {
+ _deliveryProps = deliveryProps;
+ _messageProps = messageProps;
+ }
+
+ public String getCorrelationId()
+ {
+ return _messageProps == null ? null : new String(_messageProps.getCorrelationId());
+ }
+
+ public long getExpiration()
+ {
+ return _deliveryProps == null ? null : _deliveryProps.getExpiration();
+ }
+
+ public String getMessageId()
+ {
+ return _messageProps == null ? null : String.valueOf(_messageProps.getMessageId());
+ }
+
+ public String getMimeType()
+ {
+ return _messageProps == null ? null : _messageProps.getContentType();
+ }
+
+ public String getEncoding()
+ {
+ return _messageProps == null ? null : _messageProps.getContentEncoding();
+ }
+
+ public byte getPriority()
+ {
+ MessageDeliveryPriority priority = _deliveryProps == null
+ ? MessageDeliveryPriority.MEDIUM
+ : _deliveryProps.getPriority();
+ return (byte) priority.getValue();
+ }
+
+ public long getTimestamp()
+ {
+ return _deliveryProps == null ? 0L : _deliveryProps.getTimestamp();
+ }
+
+ public String getType()
+ {
+ Object type = getHeader(JMS_TYPE);
+ return type instanceof String ? (String) type : null;
+ }
+
+ public String getReplyTo()
+ {
+ return _messageProps == null ? null : _messageProps.getReplyTo().toString();
+ }
+
+ public Object getHeader(String name)
+ {
+ Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders();
+ return appHeaders == null ? null : appHeaders.get(name);
+ }
+
+ public boolean containsHeaders(Set<String> names)
+ {
+ Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders();
+ return appHeaders != null && appHeaders.keySet().containsAll(names);
+
+ }
+
+ public boolean containsHeader(String name)
+ {
+ Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders();
+ return appHeaders != null && appHeaders.containsKey(name);
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java
new file mode 100644
index 0000000000..e866ad5078
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.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.message;
+
+import org.apache.qpid.transport.*;
+import org.apache.qpid.server.store.StoredMessage;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.nio.ByteBuffer;
+import java.lang.ref.WeakReference;
+
+
+public class MessageTransferMessage implements InboundMessage, ServerMessage
+{
+
+
+ private StoredMessage<MessageMetaData_0_10> _storeMessage;
+
+
+ private WeakReference<Session> _sessionRef;
+
+
+ public MessageTransferMessage(StoredMessage<MessageMetaData_0_10> storeMessage, WeakReference<Session> sessionRef)
+ {
+
+ _storeMessage = storeMessage;
+ _sessionRef = sessionRef;
+
+ }
+
+ private MessageMetaData_0_10 getMetaData()
+ {
+ return _storeMessage.getMetaData();
+ }
+
+ public String getRoutingKey()
+ {
+ return getMetaData().getRoutingKey();
+
+ }
+
+ public AMQMessageHeader getMessageHeader()
+ {
+ return getMetaData().getMessageHeader();
+ }
+
+ public boolean isPersistent()
+ {
+ return getMetaData().isPersistent();
+ }
+
+
+ public boolean isRedelivered()
+ {
+ // The *Message* is never redelivered, only queue entries are... this is here so that filters
+ // can run against the message on entry to an exchange
+ return false;
+ }
+
+ public long getSize()
+ {
+
+ return getMetaData().getSize();
+ }
+
+ public boolean isImmediate()
+ {
+ return getMetaData().isImmediate();
+ }
+
+ public long getExpiration()
+ {
+ return getMetaData().getExpiration();
+ }
+
+ public MessageReference newReference()
+ {
+ return new TransferMessageReference(this);
+ }
+
+ public Long getMessageNumber()
+ {
+ return _storeMessage.getMessageNumber();
+ }
+
+ public long getArrivalTime()
+ {
+ return getMetaData().getArrivalTime();
+ }
+
+ public int getContent(ByteBuffer buf, int offset)
+ {
+ return _storeMessage.getContent(offset, buf);
+ }
+
+ public Header getHeader()
+ {
+ return getMetaData().getHeader();
+ }
+
+ public ByteBuffer getBody()
+ {
+ ByteBuffer body = getMetaData().getBody();
+ if(body == null)
+ {
+ final int size = (int) getSize();
+ int pos = 0;
+ body = ByteBuffer.allocate(size);
+
+ while(pos < size)
+ {
+ pos += getContent(body, pos);
+ }
+
+ body.flip();
+
+ getMetaData().setBody(body.duplicate());
+ }
+ return body;
+ }
+
+ public Session getSession()
+ {
+ return _sessionRef == null ? null : _sessionRef.get();
+ }
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java
new file mode 100644
index 0000000000..1ac538c15b
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ServerMessage.java
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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;
+
+public interface ServerMessage extends EnqueableMessage, MessageContentSource
+{
+ String getRoutingKey();
+
+ AMQMessageHeader getMessageHeader();
+
+ boolean isPersistent();
+
+ long getSize();
+
+ boolean isImmediate();
+
+ long getExpiration();
+
+ MessageReference newReference();
+
+ Long getMessageNumber();
+
+ long getArrivalTime();
+
+ public int getContent(ByteBuffer buf, int offset);
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java
new file mode 100644
index 0000000000..ed189c49c4
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.message;
+
+public class TransferMessageReference extends MessageReference<MessageTransferMessage>
+{
+ public TransferMessageReference(MessageTransferMessage message)
+ {
+ super(message);
+ }
+
+ protected void onReference(MessageTransferMessage message)
+ {
+
+ }
+
+ protected void onRelease(MessageTransferMessage message)
+ {
+
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java
new file mode 100755
index 0000000000..aded3f3d2a
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java
@@ -0,0 +1,124 @@
+/*
+*
+* 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.output;
+
+import org.apache.qpid.server.message.MessageTransferMessage;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.MessageDeliveryMode;
+import org.apache.qpid.AMQPInvalidClassException;
+
+import java.util.Map;
+
+public class HeaderPropertiesConverter
+{
+
+ public static BasicContentHeaderProperties convert(MessageTransferMessage messageTransferMessage)
+ {
+ BasicContentHeaderProperties props = new BasicContentHeaderProperties();
+
+ Header header = messageTransferMessage.getHeader();
+ DeliveryProperties deliveryProps = header.get(DeliveryProperties.class);
+ MessageProperties messageProps = header.get(MessageProperties.class);
+
+ if(deliveryProps != null)
+ {
+ if(deliveryProps.hasDeliveryMode())
+ {
+ props.setDeliveryMode((byte)(deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT ? BasicContentHeaderProperties.PERSISTENT : BasicContentHeaderProperties.NON_PERSISTENT));
+ }
+ if(deliveryProps.hasExpiration())
+ {
+ props.setExpiration(deliveryProps.getExpiration());
+ }
+ if(deliveryProps.hasPriority())
+ {
+ props.setPriority((byte)deliveryProps.getPriority().getValue());
+ }
+ if(deliveryProps.hasTimestamp())
+ {
+ props.setTimestamp(deliveryProps.getTimestamp());
+ }
+ }
+ if(messageProps != null)
+ {
+ if(messageProps.hasAppId())
+ {
+ props.setAppId(new AMQShortString(messageProps.getAppId()));
+ }
+ if(messageProps.hasContentType())
+ {
+ props.setContentType(messageProps.getContentType());
+ }
+ if(messageProps.hasCorrelationId())
+ {
+ props.setCorrelationId(new AMQShortString(messageProps.getCorrelationId()));
+ }
+ if(messageProps.hasContentEncoding())
+ {
+ props.setEncoding(messageProps.getContentEncoding());
+ }
+ if(messageProps.hasMessageId())
+ {
+ props.setMessageId(messageProps.getMessageId().toString());
+ }
+
+ // TODO Reply-to
+
+ if(messageProps.hasUserId())
+ {
+ props.setUserId(new AMQShortString(messageProps.getUserId()));
+ }
+
+ if(messageProps.hasApplicationHeaders())
+ {
+ Map<String, Object> appHeaders = messageProps.getApplicationHeaders();
+ FieldTable ft = new FieldTable();
+ for(Map.Entry<String, Object> entry : appHeaders.entrySet())
+ {
+ try
+ {
+ ft.put(new AMQShortString(entry.getKey()), entry.getValue());
+ }
+ catch(AMQPInvalidClassException e)
+ {
+ // TODO
+ // log here, but ignore - just can;t convert
+ }
+ }
+ props.setHeaders(ft);
+
+ }
+ }
+
+
+
+
+
+
+
+ return props;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java
index e01c5aabbf..5300bad613 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java
@@ -26,10 +26,13 @@
*/
package org.apache.qpid.server.output;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.message.MessageContentSource;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.AMQException;
public interface ProtocolOutputConverter
@@ -41,16 +44,16 @@ public interface ProtocolOutputConverter
ProtocolOutputConverter newInstance(AMQProtocolSession session);
}
- void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException;
- void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException;
+ void writeGetOk(QueueEntry message, int channelId, long deliveryTag, int queueSize) throws AMQException;
byte getProtocolMinorVersion();
byte getProtocolMajorVersion();
- void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource msgContent, int channelId, int replyCode, AMQShortString replyText)
throws AMQException;
void writeFrame(AMQDataBlock block);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
index 2b55d294b5..2cebec373e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
@@ -27,28 +27,34 @@
package org.apache.qpid.server.output.amqp0_8;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQMessageHandle;
-import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.server.output.HeaderPropertiesConverter;
+import org.apache.qpid.server.message.MessageContentSource;
+import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.amqp_8_0.BasicGetBodyImpl;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.AMQException;
+import org.apache.qpid.transport.DeliveryProperties;
-import org.apache.mina.common.ByteBuffer;
-
-import java.util.Iterator;
+import java.nio.ByteBuffer;
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
+ private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+
+ private static final ProtocolVersionMethodConverter PROTOCOL_CONVERTER =
+ METHOD_REGISTRY.getProtocolVersionMethodConverter();
public static Factory getInstanceFactory()
{
return new Factory()
{
-
+
public ProtocolOutputConverter newInstance(AMQProtocolSession session)
{
return new ProtocolOutputConverterImpl(session);
@@ -69,71 +75,47 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return _protocolSession;
}
- public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
- AMQDataBlock deliver = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
-
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
-
-
- final int bodyCount = messageHandle.getBodyCount(storeContext);
+ AMQDataBlock deliver = createEncodedDeliverFrame(entry, channelId, deliveryTag, consumerTag);
+ writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliver);
+ }
- if(bodyCount == 0)
+ private ContentHeaderBody getContentHeaderBody(QueueEntry entry)
+ throws AMQException
+ {
+ if(entry.getMessage() instanceof AMQMessage)
{
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
-
- writeFrame(compositeBlock);
+ return ((AMQMessage)entry.getMessage()).getContentHeaderBody();
}
else
{
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext, i);
- writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
- }
-
-
+ final MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ BasicContentHeaderProperties props = HeaderPropertiesConverter.convert(message);
+ ContentHeaderBody chb = new ContentHeaderBody(props, BasicGetBodyImpl.CLASS_ID);
+ chb.bodySize = message.getSize();
+ return chb;
}
-
-
}
- public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
{
+ AMQDataBlock deliver = createEncodedGetOkFrame(entry, channelId, deliveryTag, queueSize);
+ writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliver);
+ }
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
+ private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody chb, int channelId, AMQDataBlock deliver)
+ throws AMQException
+ {
- AMQDataBlock deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId, chb);
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
- final int bodyCount = messageHandle.getBodyCount(storeContext);
- if(bodyCount == 0)
+ final int bodySize = (int) message.getSize();
+ if(bodySize == 0)
{
SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
contentHeader);
@@ -141,66 +123,97 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
}
else
{
+ int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
+ final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+ ByteBuffer buf = ByteBuffer.allocate(capacity);
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
+ int writtenSize = 0;
- AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf));
AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
writeFrame(compositeBlock);
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
+ while(writtenSize < bodySize)
{
- cb = messageHandle.getContentChunk(storeContext, i);
- writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
+ buf = java.nio.ByteBuffer.allocate(capacity);
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
}
-
}
-
-
}
- private AMQDataBlock createEncodedDeliverFrame(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ private AMQDataBlock createEncodedDeliverFrame(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final AMQShortString exchangeName;
+ final AMQShortString routingKey;
+
+ if(entry.getMessage() instanceof AMQMessage)
+ {
+ final AMQMessage message = (AMQMessage) entry.getMessage();
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ exchangeName = pb.getExchange();
+ routingKey = pb.getRoutingKey();
+ }
+ else
+ {
+ MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ DeliveryProperties delvProps = message.getHeader().get(DeliveryProperties.class);
+ exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange());
+ routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey());
+ }
+
+ final boolean isRedelivered = entry.isRedelivered();
+
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
BasicDeliverBody deliverBody =
- methodRegistry.createBasicDeliverBody(consumerTag,
+ METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
deliveryTag,
- messageHandle.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey());
+ isRedelivered,
+ exchangeName,
+ routingKey);
+
AMQFrame deliverFrame = deliverBody.generateFrame(channelId);
return deliverFrame;
}
- private AMQDataBlock createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
+ private AMQDataBlock createEncodedGetOkFrame(QueueEntry entry, int channelId, long deliveryTag, int queueSize)
throws AMQException
{
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final AMQShortString exchangeName;
+ final AMQShortString routingKey;
+
+ if(entry.getMessage() instanceof AMQMessage)
+ {
+ final AMQMessage message = (AMQMessage) entry.getMessage();
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ exchangeName = pb.getExchange();
+ routingKey = pb.getRoutingKey();
+ }
+ else
+ {
+ MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ DeliveryProperties delvProps = message.getHeader().get(DeliveryProperties.class);
+ exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange());
+ routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey());
+ }
+
+ final boolean isRedelivered = entry.isRedelivered();
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
BasicGetOkBody getOkBody =
- methodRegistry.createBasicGetOkBody(deliveryTag,
- messageHandle.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey(),
+ METHOD_REGISTRY.createBasicGetOkBody(deliveryTag,
+ isRedelivered,
+ exchangeName,
+ routingKey,
queueSize);
AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
@@ -217,54 +230,31 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return getProtocolSession().getProtocolMajorVersion();
}
- private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ private AMQDataBlock createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, int channelId, int replyCode, AMQShortString replyText) throws AMQException
{
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
BasicReturnBody basicReturnBody =
- methodRegistry.createBasicReturnBody(replyCode,
+ METHOD_REGISTRY.createBasicReturnBody(replyCode,
replyText,
- message.getMessagePublishInfo().getExchange(),
- message.getMessagePublishInfo().getRoutingKey());
+ messagePublishInfo.getExchange(),
+ messagePublishInfo.getRoutingKey());
AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
return returnFrame;
}
- public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ public void writeReturn(MessagePublishInfo messagePublishInfo,
+ ContentHeaderBody header,
+ MessageContentSource content,
+ int channelId,
+ int replyCode,
+ AMQShortString replyText)
throws AMQException
{
- AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
- Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- if (bodyFrameIterator.hasNext())
- {
- AMQDataBlock firstContentBody = bodyFrameIterator.next();
- AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
- }
- else
- {
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
+ AMQDataBlock returnFrame = createEncodedReturnFrame(messagePublishInfo, channelId, replyCode, replyText);
- writeFrame(compositeBlock);
- }
+ writeMessageDelivery(content, header, channelId, returnFrame);
- //
- // Now start writing out the other content bodies
- // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
- //
- while (bodyFrameIterator.hasNext())
- {
- writeFrame(bodyFrameIterator.next());
- }
}
@@ -276,8 +266,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
{
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicCancelOkBody basicCancelOkBody = methodRegistry.createBasicCancelOkBody(consumerTag);
+ BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
writeFrame(basicCancelOkBody.generateFrame(channelId));
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
index 65184fe744..319b5cc7bd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
@@ -1,46 +1,48 @@
package org.apache.qpid.server.output.amqp0_9;
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
-import org.apache.mina.common.ByteBuffer;
-import java.util.Iterator;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.server.output.HeaderPropertiesConverter;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQMessageHandle;
-import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.MessageContentSource;
+import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.amqp_0_9.BasicGetBodyImpl;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.AMQException;
+import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
- private static final ProtocolVersionMethodConverter PROTOCOL_METHOD_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
+ private static final ProtocolVersionMethodConverter
+ PROTOCOL_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
public static Factory getInstanceFactory()
@@ -68,20 +70,46 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return _protocolSession;
}
- public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
- AMQBody deliverBody = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
- final ContentHeaderBody contentHeaderBody = message.getContentHeaderBody();
+ AMQBody deliverBody = createEncodedDeliverBody(entry, deliveryTag, consumerTag);
+ writeMessageDelivery(entry, channelId, deliverBody);
+ }
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
+ private ContentHeaderBody getContentHeaderBody(QueueEntry entry)
+ throws AMQException
+ {
+ if(entry.getMessage() instanceof AMQMessage)
+ {
+ return ((AMQMessage)entry.getMessage()).getContentHeaderBody();
+ }
+ else
+ {
+ final MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ BasicContentHeaderProperties props = HeaderPropertiesConverter.convert(message);
+ ContentHeaderBody chb = new ContentHeaderBody(props, BasicGetBodyImpl.CLASS_ID);
+ chb.bodySize = message.getSize();
+ return chb;
+ }
+ }
- final int bodyCount = messageHandle.getBodyCount(storeContext);
+ private void writeMessageDelivery(QueueEntry entry, int channelId, AMQBody deliverBody)
+ throws AMQException
+ {
+ writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliverBody);
+ }
+
+ private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody contentHeaderBody, int channelId, AMQBody deliverBody)
+ throws AMQException
+ {
- if(bodyCount == 0)
+
+ int bodySize = (int) message.getSize();
+
+ if(bodySize == 0)
{
SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
contentHeaderBody);
@@ -90,101 +118,75 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
}
else
{
+ int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
+
+
+ final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(capacity);
+ int writtenSize = 0;
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
- AMQBody firstContentBody = PROTOCOL_METHOD_CONVERTER.convertToBody(cb);
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ AMQBody firstContentBody = PROTOCOL_CONVERTER.convertToBody(buf);
- CompositeAMQBodyBlock compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
+ CompositeAMQBodyBlock
+ compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
writeFrame(compositeBlock);
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
+ while(writtenSize < bodySize)
{
- cb = messageHandle.getContentChunk(storeContext, i);
- writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
- }
-
+ buf = java.nio.ByteBuffer.allocate(capacity);
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
+ }
}
-
}
private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
{
-
+
AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
contentHeaderBody);
return contentHeader;
}
- public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
{
+ AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize);
+ writeMessageDelivery(entry, channelId, deliver);
+ }
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
-
- AMQFrame deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
+ private AMQBody createEncodedDeliverBody(QueueEntry entry,
+ final long deliveryTag,
+ final AMQShortString consumerTag)
+ throws AMQException
+ {
- AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
+ final AMQShortString exchangeName;
+ final AMQShortString routingKey;
- final int bodyCount = messageHandle.getBodyCount(storeContext);
- if(bodyCount == 0)
+ if(entry.getMessage() instanceof AMQMessage)
{
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
- writeFrame(compositeBlock);
+ final AMQMessage message = (AMQMessage) entry.getMessage();
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ exchangeName = pb.getExchange();
+ routingKey = pb.getRoutingKey();
}
else
{
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext, i);
- writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
- }
-
-
+ MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ DeliveryProperties delvProps = message.getHeader().get(DeliveryProperties.class);
+ exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange());
+ routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey());
}
-
- }
-
-
- private AMQBody createEncodedDeliverFrame(AMQMessage message, final int channelId, final long deliveryTag, final AMQShortString consumerTag)
- throws AMQException
- {
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
-
- final boolean isRedelivered = messageHandle.isRedelivered();
- final AMQShortString exchangeName = pb.getExchange();
- final AMQShortString routingKey = pb.getRoutingKey();
+ final boolean isRedelivered = entry.isRedelivered();
final AMQBody returnBlock = new AMQBody()
{
@@ -237,22 +239,37 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return returnBlock;
}
- private AMQFrame createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
+ private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize)
throws AMQException
{
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final AMQShortString exchangeName;
+ final AMQShortString routingKey;
+
+ if(entry.getMessage() instanceof AMQMessage)
+ {
+ final AMQMessage message = (AMQMessage) entry.getMessage();
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ exchangeName = pb.getExchange();
+ routingKey = pb.getRoutingKey();
+ }
+ else
+ {
+ MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
+ DeliveryProperties delvProps = message.getHeader().get(DeliveryProperties.class);
+ exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange());
+ routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey());
+ }
+ final boolean isRedelivered = entry.isRedelivered();
BasicGetOkBody getOkBody =
METHOD_REGISTRY.createBasicGetOkBody(deliveryTag,
- messageHandle.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey(),
+ isRedelivered,
+ exchangeName,
+ routingKey,
queueSize);
- AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
- return getOkFrame;
+ return getOkBody;
}
public byte getProtocolMinorVersion()
@@ -265,53 +282,28 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return getProtocolSession().getProtocolMajorVersion();
}
- private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo,
+ int replyCode,
+ AMQShortString replyText) throws AMQException
{
BasicReturnBody basicReturnBody =
METHOD_REGISTRY.createBasicReturnBody(replyCode,
replyText,
- message.getMessagePublishInfo().getExchange(),
- message.getMessagePublishInfo().getRoutingKey());
- AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
+ messagePublishInfo.getExchange(),
+ messagePublishInfo.getRoutingKey());
- return returnFrame;
+
+ return basicReturnBody;
}
- public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText)
throws AMQException
{
- AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
-
- AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
-
- Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- if (bodyFrameIterator.hasNext())
- {
- AMQDataBlock firstContentBody = bodyFrameIterator.next();
- AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
- }
- else
- {
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
- writeFrame(compositeBlock);
- }
+ AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText);
- //
- // Now start writing out the other content bodies
- // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
- //
- while (bodyFrameIterator.hasNext())
- {
- writeFrame(bodyFrameIterator.next());
- }
+ writeMessageDelivery(message, header, channelId, returnFrame);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
index a6fcadad0f..04b3e75f8c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
@@ -34,6 +34,8 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicMarkableReference;
+import java.util.concurrent.atomic.AtomicBoolean;
import javax.management.JMException;
import javax.security.sasl.SaslServer;
@@ -83,8 +85,8 @@ import org.apache.qpid.server.output.ProtocolOutputConverterRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.state.AMQState;
import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.NetworkDriver;
import org.apache.qpid.transport.Sender;
@@ -124,7 +126,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
private Object _lastSent;
- protected boolean _closed;
+ protected volatile boolean _closed;
// maximum number of channels this session should have
private long _maxNoOfChannels = 1000;
@@ -139,7 +141,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
private Principal _authorizedID;
private MethodDispatcher _dispatcher;
private ProtocolSessionIdentifier _sessionIdentifier;
-
+
// Create a simple ID that increments for ever new Session
private final long _sessionID = idGenerator.getAndIncrement();
@@ -152,11 +154,13 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
private long _writtenBytes;
private long _readBytes;
-
+
private Job _readJob;
private Job _writeJob;
private ReferenceCountingExecutorService _poolReference = ReferenceCountingExecutorService.getInstance();
+ private long _maxFrameSize;
+ private final AtomicBoolean _closing = new AtomicBoolean(false);
public ManagedObject getManagedObject()
{
@@ -167,7 +171,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
{
_stateManager = new AMQStateManager(virtualHostRegistry, this);
_networkDriver = driver;
-
+
_codecFactory = new AMQCodecFactory(true, this);
_poolReference.acquireExecutorService();
_readJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, true);
@@ -178,17 +182,9 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
}
- private AMQProtocolSessionMBean createMBean() throws AMQException
+ private AMQProtocolSessionMBean createMBean() throws JMException
{
- try
- {
- return new AMQProtocolSessionMBean(this);
- }
- catch (JMException ex)
- {
- _logger.error("AMQProtocolSession MBean creation has failed ", ex);
- throw new AMQException("AMQProtocolSession MBean creation has failed ", ex);
- }
+ return new AMQProtocolSessionMBean(this);
}
public long getSessionID()
@@ -201,6 +197,21 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
return _actor;
}
+ public void setMaxFrameSize(long frameMax)
+ {
+ _maxFrameSize = frameMax;
+ }
+
+ public long getMaxFrameSize()
+ {
+ return _maxFrameSize;
+ }
+
+ public boolean isClosing()
+ {
+ return _closing.get();
+ }
+
public void received(final ByteBuffer msg)
{
_lastIoTime = System.currentTimeMillis();
@@ -290,7 +301,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
else
{
// The channel has been told to close, we don't process any more frames until
- // it's closed.
+ // it's closed.
return;
}
}
@@ -545,7 +556,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
private void checkForNotification()
{
int channelsCount = _channelMap.size();
- if (channelsCount >= _maxNoOfChannels)
+ if (_managedObject != null && channelsCount >= _maxNoOfChannels)
{
_managedObject.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value");
}
@@ -560,7 +571,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
{
_maxNoOfChannels = value;
}
-
+
public void commitTransactions(AMQChannel channel) throws AMQException
{
if ((channel != null) && channel.isTransactional())
@@ -576,7 +587,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
channel.rollback();
}
}
-
+
/**
* Close a specific channel. This will remove any resources used by the channel, including: <ul><li>any queue
* subscriptions (this may in turn remove queues if they are auto delete</li> </ul>
@@ -676,34 +687,58 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
/** This must be called when the session is _closed in order to free up any resources managed by the session. */
public void closeSession() throws AMQException
{
- // REMOVE THIS SHOULD NOT BE HERE.
- if (CurrentActor.get() == null)
- {
- CurrentActor.set(_actor);
- }
- if (!_closed)
+ if(_closing.compareAndSet(false,true))
{
- if (_virtualHost != null)
+ // REMOVE THIS SHOULD NOT BE HERE.
+ if (CurrentActor.get() == null)
{
- _virtualHost.getConnectionRegistry().deregisterConnection(this);
+ CurrentActor.set(_actor);
}
-
- closeAllChannels();
- if (_managedObject != null)
+ if (!_closed)
{
- _managedObject.unregister();
- // Ensure we only do this once.
- _managedObject = null;
- }
+ if (_virtualHost != null)
+ {
+ _virtualHost.getConnectionRegistry().deregisterConnection(this);
+ }
+
+ closeAllChannels();
+ if (_managedObject != null)
+ {
+ _managedObject.unregister();
+ // Ensure we only do this once.
+ _managedObject = null;
+ }
- for (Task task : _taskList)
+ for (Task task : _taskList)
+ {
+ task.doTask(this);
+ }
+
+ synchronized(this)
+ {
+ _closed = true;
+ notifyAll();
+ }
+ _poolReference.releaseExecutorService();
+ CurrentActor.get().message(_logSubject, ConnectionMessages.CON_1002());
+ }
+ }
+ else
+ {
+ synchronized(this)
{
- task.doTask(this);
+ while(!_closed)
+ {
+ try
+ {
+ wait(1000);
+ }
+ catch (InterruptedException e)
+ {
+
+ }
+ }
}
-
- _closed = true;
- _poolReference.releaseExecutorService();
- CurrentActor.get().message(_logSubject, ConnectionMessages.CON_1002());
}
}
@@ -778,7 +813,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
throw new IllegalArgumentException("Unsupported socket address class: " + address);
}
}
-
+
public SaslServer getSaslServer()
{
return _saslServer;
@@ -868,8 +903,15 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
_virtualHost.getConnectionRegistry().registerConnection(this);
- _managedObject = createMBean();
- _managedObject.register();
+ try
+ {
+ _managedObject = createMBean();
+ _managedObject.register();
+ }
+ catch (JMException e)
+ {
+ _logger.error(e);
+ }
}
public void addSessionCloseTask(Task task)
@@ -881,7 +923,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
{
_taskList.remove(task);
}
-
+
public ProtocolOutputConverter getProtocolOutputConverter()
{
return _protocolOutputConverter;
@@ -900,10 +942,15 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
return _authorizedID;
}
+ public Principal getPrincipal()
+ {
+ return _authorizedID;
+ }
+
public SocketAddress getRemoteAddress()
{
return _networkDriver.getRemoteAddress();
- }
+ }
public SocketAddress getLocalAddress()
{
@@ -939,7 +986,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
public void setNetworkDriver(NetworkDriver driver)
{
- _networkDriver = driver;
+ _networkDriver = driver;
}
public void writerIdle()
@@ -968,7 +1015,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(getProtocolVersion());
ConnectionCloseBody closeBody = methodRegistry.createConnectionCloseBody(200,new AMQShortString(throwable.getMessage()),0,0);
-
+
writeFrame(closeBody.generateFrame(0));
_networkDriver.close();
@@ -984,7 +1031,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
{
// Do nothing
}
-
+
public long getReadBytes()
{
return _readBytes;
@@ -1004,7 +1051,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
{
return _sessionIdentifier;
}
-
+
public String getClientVersion()
{
return (_clientVersion == null) ? null : _clientVersion.toString();
@@ -1022,5 +1069,5 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
}
}
}
-
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
index b16ed01c79..48dd16a98c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -28,7 +28,7 @@ import org.apache.qpid.framing.*;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -37,12 +37,18 @@ import java.security.Principal;
import java.util.List;
-public interface AMQProtocolSession extends AMQVersionAwareProtocolSession
+public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, PrincipalHolder
{
long getSessionID();
LogActor getLogActor();
+ void setMaxFrameSize(long frameMax);
+
+ long getMaxFrameSize();
+
+ boolean isClosing();
+
public static final class ProtocolSessionIdentifier
{
private final Object _sessionIdentifier;
@@ -201,9 +207,6 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession
void setAuthorizedID(Principal authorizedID);
- /** @return a Principal that was used to authorized this session */
- Principal getAuthorizedID();
-
public java.net.SocketAddress getRemoteAddress();
public MethodRegistry getMethodRegistry();
@@ -224,8 +227,10 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession
void commitTransactions(AMQChannel channel) throws AMQException;
+ void rollbackTransactions(AMQChannel channel) throws AMQException;
+
List<AMQChannel> getChannels();
void closeIfLingeringClosedChannels();
-
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
index 8497c95e26..67c1e51f6e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
@@ -133,7 +133,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
public String getAuthorizedId()
{
- return (_protocolSession.getAuthorizedID() != null ) ? _protocolSession.getAuthorizedID().getName() : null;
+ return (_protocolSession.getPrincipal() != null ) ? _protocolSession.getPrincipal().getName() : null;
}
public String getVersion()
@@ -227,7 +227,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
}
- _protocolSession.commitTransactions(channel);
+ _protocolSession.rollbackTransactions(channel);
}
catch (AMQException ex)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
new file mode 100755
index 0000000000..78e21a8f14
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
@@ -0,0 +1,366 @@
+/*
+*
+* 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 org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionDelegate;
+import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory.VERSION;
+import org.apache.qpid.server.transport.ServerConnection;
+import org.apache.log4j.Logger;
+
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.util.Set;
+
+public class MultiVersionProtocolEngine implements ProtocolEngine
+{
+ private static final Logger _logger = Logger.getLogger(MultiVersionProtocolEngine.class);
+
+
+
+ private NetworkDriver _networkDriver;
+ private Set<VERSION> _supported;
+ private String _fqdn;
+ private IApplicationRegistry _appRegistry;
+
+ private volatile ProtocolEngine _delegate = new SelfDelegateProtocolEngine();
+
+ public MultiVersionProtocolEngine(IApplicationRegistry appRegistry,
+ String fqdn,
+ Set<VERSION> supported, NetworkDriver networkDriver)
+ {
+ _appRegistry = appRegistry;
+ _fqdn = fqdn;
+ _supported = supported;
+ _networkDriver = networkDriver;
+ }
+
+ public void setNetworkDriver(NetworkDriver driver)
+ {
+ _delegate.setNetworkDriver(driver);
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ return _delegate.getRemoteAddress();
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return _delegate.getLocalAddress();
+ }
+
+ public long getWrittenBytes()
+ {
+ return _delegate.getWrittenBytes();
+ }
+
+ public long getReadBytes()
+ {
+ return _delegate.getReadBytes();
+ }
+
+ public void closed()
+ {
+ _delegate.closed();
+ }
+
+ public void writerIdle()
+ {
+ _delegate.writerIdle();
+ }
+
+ public void readerIdle()
+ {
+ _delegate.readerIdle();
+ }
+
+ public void received(ByteBuffer msg)
+ {
+ _delegate.received(msg);
+ }
+
+ public void exception(Throwable t)
+ {
+ _delegate.exception(t);
+ }
+
+ private static final int MINIMUM_REQUIRED_HEADER_BYTES = 8;
+
+ private static final byte[] AMQP_0_8_HEADER =
+ new byte[] { (byte) 'A',
+ (byte) 'M',
+ (byte) 'Q',
+ (byte) 'P',
+ (byte) 1,
+ (byte) 1,
+ (byte) 8,
+ (byte) 0
+ };
+
+ private static final byte[] AMQP_0_9_HEADER =
+ new byte[] { (byte) 'A',
+ (byte) 'M',
+ (byte) 'Q',
+ (byte) 'P',
+ (byte) 1,
+ (byte) 1,
+ (byte) 0,
+ (byte) 9
+ };
+
+private static final byte[] AMQP_0_9_1_HEADER =
+ new byte[] { (byte) 'A',
+ (byte) 'M',
+ (byte) 'Q',
+ (byte) 'P',
+ (byte) 1,
+ (byte) 0,
+ (byte) 9,
+ (byte) 1
+ };
+
+
+ private static final byte[] AMQP_0_10_HEADER =
+ new byte[] { (byte) 'A',
+ (byte) 'M',
+ (byte) 'Q',
+ (byte) 'P',
+ (byte) 1,
+ (byte) 1,
+ (byte) 0,
+ (byte) 10
+ };
+
+ private static interface DelegateCreator
+ {
+ VERSION getVersion();
+ byte[] getHeaderIdentifier();
+ ProtocolEngine getProtocolEngine();
+ }
+
+ private DelegateCreator creator_0_8 = new DelegateCreator()
+ {
+
+ public VERSION getVersion()
+ {
+ return VERSION.v0_8;
+ }
+
+ public byte[] getHeaderIdentifier()
+ {
+ return AMQP_0_8_HEADER;
+ }
+
+ public ProtocolEngine getProtocolEngine()
+ {
+ return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _networkDriver);
+ }
+ };
+
+ private DelegateCreator creator_0_9 = new DelegateCreator()
+ {
+
+ public VERSION getVersion()
+ {
+ return VERSION.v0_9;
+ }
+
+
+ public byte[] getHeaderIdentifier()
+ {
+ return AMQP_0_9_HEADER;
+ }
+
+ public ProtocolEngine getProtocolEngine()
+ {
+ return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _networkDriver);
+ }
+ };
+
+ private DelegateCreator creator_0_9_1 = new DelegateCreator()
+ {
+
+ public VERSION getVersion()
+ {
+ return VERSION.v0_9_1;
+ }
+
+
+ public byte[] getHeaderIdentifier()
+ {
+ return AMQP_0_9_1_HEADER;
+ }
+
+ public ProtocolEngine getProtocolEngine()
+ {
+ return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _networkDriver);
+ }
+ };
+
+
+ private DelegateCreator creator_0_10 = new DelegateCreator()
+ {
+
+ public VERSION getVersion()
+ {
+ return VERSION.v0_10;
+ }
+
+
+ public byte[] getHeaderIdentifier()
+ {
+ return AMQP_0_10_HEADER;
+ }
+
+ public ProtocolEngine getProtocolEngine()
+ {
+ final ConnectionDelegate connDelegate =
+ new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn);
+
+ Connection conn = new ServerConnection();
+ conn.setConnectionDelegate(connDelegate);
+
+ return new ProtocolEngine_0_10( conn, _networkDriver);
+ }
+ };
+
+ private final DelegateCreator[] _creators =
+ new DelegateCreator[] { creator_0_8, creator_0_9, creator_0_9_1, creator_0_10 };
+
+
+ private class SelfDelegateProtocolEngine implements ProtocolEngine
+ {
+
+ private final ByteBuffer _header = ByteBuffer.allocate(MINIMUM_REQUIRED_HEADER_BYTES);
+
+ public void setNetworkDriver(NetworkDriver driver)
+ {
+ _networkDriver = driver;
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ return _networkDriver.getRemoteAddress();
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return _networkDriver.getLocalAddress();
+ }
+
+ public long getWrittenBytes()
+ {
+ return 0;
+ }
+
+ public long getReadBytes()
+ {
+ return 0;
+ }
+
+ public void received(ByteBuffer msg)
+ {
+ ByteBuffer msgheader = msg.duplicate();
+ if(_header.remaining() > msgheader.limit())
+ {
+ msg.position(msg.limit());
+ }
+ else
+ {
+ msgheader.limit(_header.remaining());
+ msg.position(_header.remaining());
+ }
+
+ _header.put(msgheader);
+
+ if(!_header.hasRemaining())
+ {
+ _header.flip();
+ byte[] headerBytes = new byte[MINIMUM_REQUIRED_HEADER_BYTES];
+ _header.get(headerBytes);
+
+
+ ProtocolEngine newDelegate = null;
+
+ for(int i = 0; newDelegate == null && i < _creators.length; i++)
+ {
+
+ if(_supported.contains(_creators[i].getVersion()))
+ {
+ byte[] compareBytes = _creators[i].getHeaderIdentifier();
+ boolean equal = true;
+ for(int j = 0; equal && j<compareBytes.length; j++)
+ {
+ equal = headerBytes[j] == compareBytes[j];
+ }
+ if(equal)
+ {
+ newDelegate = _creators[i].getProtocolEngine();
+ }
+
+
+ }
+ }
+ // let the first delegate handle completely unknown versions
+ if(newDelegate == null)
+ {
+ newDelegate = _creators[0].getProtocolEngine();
+ }
+ newDelegate.setNetworkDriver(_networkDriver);
+
+ _delegate = newDelegate;
+
+ _header.flip();
+ _delegate.received(_header);
+ if(msg.hasRemaining())
+ {
+ _delegate.received(msg);
+ }
+
+ }
+
+ }
+
+ public void exception(Throwable t)
+ {
+ _logger.error("Error establishing session", t);
+ }
+
+ public void closed()
+ {
+
+ }
+
+ public void writerIdle()
+ {
+
+ }
+
+ public void readerIdle()
+ {
+
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
new file mode 100755
index 0000000000..75358c42d9
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.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.protocol;
+
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+
+import java.util.Set;
+import java.util.Arrays;
+import java.util.HashSet;
+
+public class MultiVersionProtocolEngineFactory implements ProtocolEngineFactory
+{
+ ;
+
+
+ public enum VERSION { v0_8, v0_9, v0_9_1, v0_10 };
+
+ private static final Set<VERSION> ALL_VERSIONS = new HashSet<VERSION>(Arrays.asList(VERSION.values()));
+
+ private final IApplicationRegistry _appRegistry;
+ private final String _fqdn;
+ private final Set<VERSION> _supported;
+
+
+ public MultiVersionProtocolEngineFactory()
+ {
+ this(1, "localhost", ALL_VERSIONS);
+ }
+
+ public MultiVersionProtocolEngineFactory(String fqdn, Set<VERSION> versions)
+ {
+ this(1, fqdn, versions);
+ }
+
+
+ public MultiVersionProtocolEngineFactory(String fqdn)
+ {
+ this(1, fqdn, ALL_VERSIONS);
+ }
+
+ public MultiVersionProtocolEngineFactory(int instance, String fqdn, Set<VERSION> supportedVersions)
+ {
+ _appRegistry = ApplicationRegistry.getInstance(instance);
+ _fqdn = fqdn;
+ _supported = supportedVersions;
+ }
+
+
+ public ProtocolEngine newProtocolEngine(NetworkDriver networkDriver)
+ {
+ return new MultiVersionProtocolEngine(_appRegistry, _fqdn, _supported, networkDriver);
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngineFactory_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngineFactory_0_10.java
new file mode 100755
index 0000000000..7c3adf8b7d
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngineFactory_0_10.java
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol;
+
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionDelegate;
+import org.apache.qpid.server.transport.ServerConnection;
+import org.apache.qpid.server.protocol.ProtocolEngine_0_10;
+
+public class ProtocolEngineFactory_0_10 implements ProtocolEngineFactory
+{
+ private ConnectionDelegate _delegate;
+
+ public ProtocolEngineFactory_0_10(ConnectionDelegate delegate)
+ {
+ _delegate = delegate;
+ }
+
+ public ProtocolEngine newProtocolEngine(NetworkDriver networkDriver)
+ {
+ Connection conn = new ServerConnection();
+ conn.setConnectionDelegate(_delegate);
+ return new ProtocolEngine_0_10(conn, networkDriver);
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java
new file mode 100755
index 0000000000..e3cd3acd98
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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 org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.network.InputHandler;
+import org.apache.qpid.transport.network.Assembler;
+import org.apache.qpid.transport.network.Disassembler;
+
+import java.net.SocketAddress;
+
+public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine
+{
+ public static final int MAX_FRAME_SIZE = 64 * 1024 - 1;
+
+ private NetworkDriver _networkDriver;
+ private long _readBytes;
+ private long _writtenBytes;
+ private Connection _connection;
+
+ public ProtocolEngine_0_10(Connection conn, NetworkDriver networkDriver)
+ {
+ super(new Assembler(conn));
+ _connection = conn;
+ _networkDriver = networkDriver;
+ }
+
+ public void setNetworkDriver(NetworkDriver driver)
+ {
+ _networkDriver = driver;
+ Disassembler dis = new Disassembler(driver, MAX_FRAME_SIZE);
+ _connection.setSender(dis);
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ return _networkDriver.getRemoteAddress();
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return _networkDriver.getLocalAddress();
+ }
+
+ public long getReadBytes()
+ {
+ return _readBytes;
+ }
+
+ public long getWrittenBytes()
+ {
+ return _writtenBytes;
+ }
+
+ public void writerIdle()
+ {
+ //Todo
+ }
+
+ public void readerIdle()
+ {
+ //Todo
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
deleted file mode 100644
index b987dae16d..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
+++ /dev/null
@@ -1,502 +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.queue;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQBody;
-import org.apache.qpid.framing.AMQDataBlock;
-import org.apache.qpid.framing.AMQFrame;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.txn.TransactionalContext;
-
-
-import java.util.Iterator;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * A deliverable message.
- */
-public class AMQMessage implements Filterable<AMQException>
-{
- /** Used for debugging purposes. */
- private static final Logger _log = Logger.getLogger(AMQMessage.class);
-
- private final AtomicInteger _referenceCount = new AtomicInteger(1);
-
- private final AMQMessageHandle _messageHandle;
-
- /** Holds the transactional context in which this message is being processed. */
- private StoreContext _storeContext;
-
- /** Flag to indicate that this message requires 'immediate' delivery. */
-
- private static final byte IMMEDIATE = 0x01;
-
- /**
- * Flag to indicate whether this message has been delivered to a consumer. Used in implementing return functionality
- * for messages published with the 'immediate' flag.
- */
-
- private static final byte DELIVERED_TO_CONSUMER = 0x02;
-
- private byte _flags = 0;
-
- private long _expiration;
-
- private final long _size;
-
- private AMQProtocolSession.ProtocolSessionIdentifier _sessionIdentifier;
- private static final byte IMMEDIATE_AND_DELIVERED = (byte) (IMMEDIATE | DELIVERED_TO_CONSUMER);
-
-
-
- /**
- * Used to iterate through all the body frames associated with this message. Will not keep all the data in memory
- * therefore is memory-efficient.
- */
- private class BodyFrameIterator implements Iterator<AMQDataBlock>
- {
- private int _channel;
-
- private int _index = -1;
- private AMQProtocolSession _protocolSession;
-
- private BodyFrameIterator(AMQProtocolSession protocolSession, int channel)
- {
- _channel = channel;
- _protocolSession = protocolSession;
- }
-
- public boolean hasNext()
- {
- try
- {
- return _index < (_messageHandle.getBodyCount(getStoreContext()) - 1);
- }
- catch (AMQException e)
- {
- _log.error("Unable to get body count: " + e, e);
-
- return false;
- }
- }
-
- public AMQDataBlock next()
- {
- try
- {
-
- AMQBody cb =
- getProtocolVersionMethodConverter().convertToBody(_messageHandle.getContentChunk(getStoreContext(),
- ++_index));
-
- return new AMQFrame(_channel, cb);
- }
- catch (AMQException e)
- {
- // have no choice but to throw a runtime exception
- throw new RuntimeException("Error getting content body: " + e, e);
- }
-
- }
-
- private ProtocolVersionMethodConverter getProtocolVersionMethodConverter()
- {
- return _protocolSession.getMethodRegistry().getProtocolVersionMethodConverter();
- }
-
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
- }
-
- public void clearStoreContext()
- {
- _storeContext = new StoreContext();
- }
-
- public StoreContext getStoreContext()
- {
- return _storeContext;
- }
-
- private class BodyContentIterator implements Iterator<ContentChunk>
- {
-
- private int _index = -1;
-
- public boolean hasNext()
- {
- try
- {
- return _index < (_messageHandle.getBodyCount(getStoreContext()) - 1);
- }
- catch (AMQException e)
- {
- _log.error("Error getting body count: " + e, e);
-
- return false;
- }
- }
-
- public ContentChunk next()
- {
- try
- {
- return _messageHandle.getContentChunk(getStoreContext(), ++_index);
- }
- catch (AMQException e)
- {
- throw new RuntimeException("Error getting content body: " + e, e);
- }
- }
-
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
- }
-
-
-
- /**
- * Used when recovering, i.e. when the message store is creating references to messages. In that case, the normal
- * enqueue/routingComplete is not done since the recovery process is responsible for routing the messages to
- * queues.
- *
- * @param messageId
- * @param store
- * @param factory
- *
- * @throws AMQException
- */
- public AMQMessage(Long messageId, MessageStore store, MessageHandleFactory factory, TransactionalContext txnConext)
- throws AMQException
- {
- _messageHandle = factory.createMessageHandle(messageId, store, true);
- _storeContext = txnConext.getStoreContext();
- _size = _messageHandle.getBodySize(txnConext.getStoreContext());
- }
-
- /**
- * Used when recovering, i.e. when the message store is creating references to messages. In that case, the normal
- * enqueue/routingComplete is not done since the recovery process is responsible for routing the messages to
- * queues.
- *
- * @param messageHandle
- *
- * @throws AMQException
- */
- public AMQMessage(
- AMQMessageHandle messageHandle,
- StoreContext storeConext,
- MessagePublishInfo info)
- throws AMQException
- {
- _messageHandle = messageHandle;
- _storeContext = storeConext;
-
- if(info.isImmediate())
- {
- _flags |= IMMEDIATE;
- }
- _size = messageHandle.getBodySize(storeConext);
-
- }
-
-
- protected AMQMessage(AMQMessage msg) throws AMQException
- {
- _messageHandle = msg._messageHandle;
- _storeContext = msg._storeContext;
- _flags = msg._flags;
- _size = msg._size;
-
- }
-
-
- public String debugIdentity()
- {
- return "(HC:" + System.identityHashCode(this) + " ID:" + getMessageId() + " Ref:" + _referenceCount.get() + ")";
- }
-
- public void setExpiration(final long expiration)
- {
-
- _expiration = expiration;
-
- }
-
- public boolean isReferenced()
- {
- return _referenceCount.get() > 0;
- }
-
- public Iterator<AMQDataBlock> getBodyFrameIterator(AMQProtocolSession protocolSession, int channel)
- {
- return new BodyFrameIterator(protocolSession, channel);
- }
-
- public Iterator<ContentChunk> getContentBodyIterator()
- {
- return new BodyContentIterator();
- }
-
- public ContentHeaderBody getContentHeaderBody() throws AMQException
- {
- return _messageHandle.getContentHeaderBody(getStoreContext());
- }
-
-
-
- public Long getMessageId()
- {
- return _messageHandle.getMessageId();
- }
-
- /**
- * Creates a long-lived reference to this message, and increments the count of such references, as an atomic
- * operation.
- */
- public AMQMessage takeReference()
- {
- incrementReference(); // _referenceCount.incrementAndGet();
-
- return this;
- }
-
- public boolean incrementReference()
- {
- return incrementReference(1);
- }
-
- /* Threadsafe. Increment the reference count on the message. */
- public boolean incrementReference(int count)
- {
- if(_referenceCount.addAndGet(count) <= 1)
- {
- _referenceCount.addAndGet(-count);
- return false;
- }
- else
- {
- return true;
- }
-
- }
-
- /**
- * Threadsafe. This will decrement the reference count and when it reaches zero will remove the message from the
- * message store.
- *
- * @param storeContext
- *
- * @throws MessageCleanupException when an attempt was made to remove the message from the message store and that
- * failed
- */
- public void decrementReference(StoreContext storeContext) throws MessageCleanupException
- {
-
- int count = _referenceCount.decrementAndGet();
-
- // note that the operation of decrementing the reference count and then removing the message does not
- // have to be atomic since the ref count starts at 1 and the exchange itself decrements that after
- // the message has been passed to all queues. i.e. we are
- // not relying on the all the increments having taken place before the delivery manager decrements.
- if (count == 0)
- {
- // set the reference count way below 0 so that we can detect that the message has been deleted
- // this is to guard against the message being spontaneously recreated (from the mgmt console)
- // by copying from other queues at the same time as it is being removed.
- _referenceCount.set(Integer.MIN_VALUE/2);
-
- try
- {
- // must check if the handle is null since there may be cases where we decide to throw away a message
- // and the handle has not yet been constructed
- if (_messageHandle != null)
- {
- _messageHandle.removeMessage(storeContext);
- }
- }
- catch (AMQException e)
- {
- // to maintain consistency, we revert the count
- incrementReference();
- throw new MessageCleanupException(getMessageId(), e);
- }
- }
- else
- {
- if (count < 0)
- {
- throw new MessageCleanupException("Reference count for message id " + debugIdentity()
- + " has gone below 0.");
- }
- }
- }
-
-
- /**
- * Called selectors to determin if the message has already been sent
- *
- * @return _deliveredToConsumer
- */
- public boolean getDeliveredToConsumer()
- {
- return (_flags & DELIVERED_TO_CONSUMER) != 0;
- }
-
- public boolean isPersistent() throws AMQException
- {
- return _messageHandle.isPersistent();
- }
-
- /**
- * Called to enforce the 'immediate' flag.
- *
- * @returns true if the message is marked for immediate delivery but has not been marked as delivered
- * to a consumer
- */
- public boolean immediateAndNotDelivered()
- {
-
- return (_flags & IMMEDIATE_AND_DELIVERED) == IMMEDIATE;
-
- }
-
- public MessagePublishInfo getMessagePublishInfo() throws AMQException
- {
- return _messageHandle.getMessagePublishInfo(getStoreContext());
- }
-
- public boolean isRedelivered()
- {
- return _messageHandle.isRedelivered();
- }
-
- public void setRedelivered(boolean redelivered)
- {
- _messageHandle.setRedelivered(redelivered);
- }
-
- public long getArrivalTime()
- {
- return _messageHandle.getArrivalTime();
- }
-
- /**
- * Checks to see if the message has expired. If it has the message is dequeued.
- *
- * @param queue The queue to check the expiration against. (Currently not used)
- *
- * @return true if the message has expire
- *
- * @throws AMQException
- */
- public boolean expired(AMQQueue queue) throws AMQException
- {
-
- if (_expiration != 0L)
- {
- long now = System.currentTimeMillis();
-
- return (now > _expiration);
- }
-
- return false;
- }
-
- /**
- * Called when this message is delivered to a consumer. (used to implement the 'immediate' flag functionality).
- * And for selector efficiency.
- */
- public void setDeliveredToConsumer()
- {
- _flags |= DELIVERED_TO_CONSUMER;
- }
-
-
-
- public AMQMessageHandle getMessageHandle()
- {
- return _messageHandle;
- }
-
- public long getSize()
- {
- return _size;
-
- }
-
- public Object getPublisherClientInstance()
- {
- //todo store sessionIdentifier/client id with message in store
- //Currently the _sessionIdentifier will be null if the message has been
- // restored from a message Store
- if (_sessionIdentifier == null)
- {
- return null;
- }
- else
- {
- return _sessionIdentifier.getSessionInstance();
- }
- }
-
- public Object getPublisherIdentifier()
- {
- //todo store sessionIdentifier/client id with message in store
- //Currently the _sessionIdentifier will be null if the message has been
- // restored from a message Store
- if (_sessionIdentifier == null)
- {
- return null;
- }
- else
- {
- return _sessionIdentifier.getSessionIdentifier();
- }
- }
-
- public void setClientIdentifier(final AMQProtocolSession.ProtocolSessionIdentifier sessionIdentifier)
- {
- _sessionIdentifier = sessionIdentifier;
- }
-
-
- public String toString()
- {
- // return "Message[" + debugIdentity() + "]: " + _messageId + "; ref count: " + _referenceCount + "; taken : " +
- // _taken + " by :" + _takenBySubcription;
-
- return "Message[" + debugIdentity() + "]: " + getMessageId() + "; ref count: " + _referenceCount;
- }
-
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java
deleted file mode 100644
index 0ddd4e4d92..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java
+++ /dev/null
@@ -1,79 +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.queue;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-
-/**
- * A pluggable way of getting message data. Implementations can provide intelligent caching for example or
- * even no caching at all to minimise the broker memory footprint.
- */
-public interface AMQMessageHandle
-{
- ContentHeaderBody getContentHeaderBody(StoreContext context) throws AMQException;
-
- /**
- *
- * @return the messageId for the message associated with this handle
- */
- Long getMessageId();
-
-
- /**
- * @return the number of body frames associated with this message
- */
- int getBodyCount(StoreContext context) throws AMQException;
-
- /**
- * @return the size of the body
- */
- long getBodySize(StoreContext context) throws AMQException;
-
- /**
- * Get a particular content body
- * @param index the index of the body to retrieve, must be between 0 and getBodyCount() - 1
- * @return a content body
- * @throws IllegalArgumentException if the index is invalid
- */
- ContentChunk getContentChunk(StoreContext context, int index) throws IllegalArgumentException, AMQException;
-
- void addContentBodyFrame(StoreContext storeContext, ContentChunk contentBody, boolean isLastContentBody) throws AMQException;
-
- MessagePublishInfo getMessagePublishInfo(StoreContext context) throws AMQException;
-
- boolean isRedelivered();
-
- void setRedelivered(boolean redelivered);
-
- boolean isPersistent();
-
- void setPublishAndContentHeaderBody(StoreContext storeContext, MessagePublishInfo messagePublishInfo,
- ContentHeaderBody contentHeaderBody)
- throws AMQException;
-
- void removeMessage(StoreContext storeContext) throws AMQException;
-
- long getArrivalTime();
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
index bb6ce65d42..51fbff76f4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
@@ -24,7 +24,6 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.subscription.SubscriptionList;
import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.AMQException;
public class AMQPriorityQueue extends SimpleAMQQueue
{
@@ -34,11 +33,19 @@ public class AMQPriorityQueue extends SimpleAMQQueue
final boolean autoDelete,
final VirtualHost virtualHost,
int priorities)
- throws AMQException
{
super(name, durable, owner, autoDelete, virtualHost, new PriorityQueueList.Factory(priorities));
}
+ public AMQPriorityQueue(String queueName,
+ boolean durable,
+ String owner,
+ boolean autoDelete,
+ VirtualHost virtualHost, int priorities)
+ {
+ this(new AMQShortString(queueName), durable, new AMQShortString(owner),autoDelete,virtualHost,priorities);
+ }
+
public int getPriorities()
{
return ((PriorityQueueList) _entries).getPriorities();
@@ -52,16 +59,25 @@ public class AMQPriorityQueue extends SimpleAMQQueue
while(subIter.advance() && !entry.isAcquired())
{
final Subscription subscription = subIter.getNode().getSubscription();
- QueueEntry subnode = subscription.getLastSeenEntry();
- while(subnode != null && entry.compareTo(subnode) < 0 && !entry.isAcquired())
+ if(!subscription.isClosed())
{
- if(subscription.setLastSeenEntry(subnode,entry))
- {
- break;
- }
- else
+ QueueContext context = (QueueContext) subscription.getQueueContext();
+ if(context != null)
{
- subnode = subscription.getLastSeenEntry();
+ QueueEntry subnode = context._lastSeenEntry;
+ QueueEntry released = context._releasedEntry;
+ while(subnode != null && entry.compareTo(subnode) < 0 && !entry.isAcquired() && (released == null || released.compareTo(entry) < 0))
+ {
+ if(QueueContext._releasedUpdater.compareAndSet(context,released,entry))
+ {
+ break;
+ }
+ else
+ {
+ subnode = context._lastSeenEntry;
+ released = context._releasedEntry;
+ }
+ }
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
index 184504717e..c9d20c53e4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
@@ -20,34 +20,49 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.commons.configuration.CompositeConfiguration;
-import org.apache.commons.configuration.Configuration;
import org.apache.qpid.server.management.Managable;
import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.configuration.QueueConfiguration;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.exchange.ExchangeReferrer;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.security.PrincipalHolder;
+import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.AMQException;
import java.util.List;
import java.util.Set;
+import java.util.Map;
-public interface AMQQueue extends Managable, Comparable<AMQQueue>
+public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource
{
+
+ public interface Context
+ {
+ QueueEntry getLastSeenEntry();
+ }
+
AMQShortString getName();
+ void setNoLocal(boolean b);
+
boolean isDurable();
boolean isAutoDelete();
AMQShortString getOwner();
+ PrincipalHolder getPrincipalHolder();
+ void setPrincipalHolder(PrincipalHolder principalHolder);
+
+ void setExclusiveOwner(Object owner);
+ Object getExclusiveOwner();
VirtualHost getVirtualHost();
@@ -89,17 +104,19 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>
int delete() throws AMQException;
- QueueEntry enqueue(StoreContext storeContext, AMQMessage message) throws AMQException;
+ QueueEntry enqueue(ServerMessage message) throws AMQException;
+
+ void requeue(QueueEntry entry);
- void requeue(StoreContext storeContext, QueueEntry entry) throws AMQException;
+ void requeue(QueueEntryImpl storeContext, Subscription subscription);
- void dequeue(StoreContext storeContext, QueueEntry entry) throws FailedDequeueException;
+ void dequeue(QueueEntry entry);
boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException;
-
+
void addQueueDeleteTask(final Task task);
@@ -113,11 +130,11 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>
List<Long> getMessagesOnTheQueue(int num, int offest);
QueueEntry getMessageOnTheQueue(long messageId);
-
+
/**
* Returns a list of QueEntries from a given range of queue positions, eg messages 5 to 10 on the queue.
- *
- * The 'queue position' index starts from 1. Using 0 in 'from' will be ignored and continue from 1.
+ *
+ * The 'queue position' index starts from 1. Using 0 in 'from' will be ignored and continue from 1.
* Using 0 in the 'to' field will return an empty list regardless of the 'from' value.
* @param fromPosition
* @param toPosition
@@ -127,11 +144,11 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>
void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName,
- StoreContext storeContext);
+ ServerTransaction transaction);
- void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, StoreContext storeContext);
+ void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction transaction);
- void removeMessagesFromQueue(long fromMessageId, long toMessageId, StoreContext storeContext);
+ void removeMessagesFromQueue(long fromMessageId, long toMessageId);
@@ -171,9 +188,9 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>
- void deleteMessageFromTop(StoreContext storeContext) throws AMQException;
+ void deleteMessageFromTop();
- long clearQueue(StoreContext storeContext) throws AMQException;
+ long clearQueue();
/**
* Checks the status of messages on the queue, purging expired ones, firing age related alerts etc.
@@ -191,6 +208,14 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>
void stop();
+ boolean isExclusive();
+
+ Exchange getAlternateExchange();
+
+ void setAlternateExchange(Exchange exchange);
+
+ Map<String, Object> getArguments();
+
void checkCapacity(AMQChannel channel);
/**
@@ -242,6 +267,6 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>
}
void configure(QueueConfiguration config);
-
+
ManagedObject getManagedObject();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
index 267ccf43ea..d4a5b3258b 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
@@ -27,7 +27,6 @@ import org.apache.qpid.server.configuration.QueueConfiguration;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Map;
-import java.util.HashMap;
public class AMQQueueFactory
@@ -130,7 +129,6 @@ public class AMQQueueFactory
AMQShortString owner,
boolean autoDelete,
VirtualHost virtualHost, final FieldTable arguments)
- throws AMQException
{
final int priorities = arguments == null ? 1 : arguments.containsKey(X_QPID_PRIORITIES) ? arguments.getInteger(X_QPID_PRIORITIES) : 1;
@@ -189,4 +187,39 @@ public class AMQQueueFactory
q.configure(config);
return q;
}
+
+ public static AMQQueue createAMQQueueImpl(String queueName,
+ boolean durable,
+ String owner,
+ boolean autoDelete,
+ VirtualHost virtualHost, Map<String, Object> arguments)
+ throws AMQException
+ {
+ int priorities = 1;
+ if(arguments != null && arguments.containsKey(X_QPID_PRIORITIES))
+ {
+ Object prioritiesObj = arguments.get(X_QPID_PRIORITIES);
+ if(prioritiesObj instanceof Number)
+ {
+ priorities = ((Number)prioritiesObj).intValue();
+ }
+ }
+
+
+ AMQQueue q = null;
+ if(priorities > 1)
+ {
+ q = new AMQPriorityQueue(queueName, durable, owner, autoDelete, virtualHost, priorities);
+ }
+ else
+ {
+ q = new SimpleAMQQueue(queueName, durable, owner, autoDelete, virtualHost);
+ }
+
+ //Register the new queue
+ virtualHost.getQueueRegistry().registerQueue(q);
+ q.configure(virtualHost.getConfiguration().getQueueConfiguration(queueName));
+ return q;
+
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
index d340c9a91f..8e5310bc16 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
@@ -22,23 +22,21 @@ package org.apache.qpid.server.queue;
import org.apache.log4j.Logger;
-import org.apache.mina.common.ByteBuffer;
-
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.CommonContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.management.common.mbeans.ManagedQueue;
import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
import org.apache.qpid.server.management.AMQManagedObject;
import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.LocalTransaction;
import javax.management.JMException;
-import javax.management.MBeanException;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.OperationsException;
@@ -72,12 +70,6 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
private static final SimpleDateFormat _dateFormat = new SimpleDateFormat("MM-dd-yy HH:mm:ss.SSS z");
- /**
- * Since the MBean is not associated with a real channel we can safely create our own store context
- * for use in the few methods that require one.
- */
- private StoreContext _storeContext = new StoreContext();
-
private AMQQueue _queue = null;
private String _queueName = null;
// OpenMBean data types for viewMessages method
@@ -131,7 +123,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
_msgContentAttributeTypes[1] = SimpleType.STRING; // For MimeType
_msgContentAttributeTypes[2] = SimpleType.STRING; // For Encoding
_msgContentAttributeTypes[3] = new ArrayType(1, SimpleType.BYTE); // For message content
- _msgContentType = new CompositeType("Message Content", "AMQ Message Content",
+ _msgContentType = new CompositeType("Message Content", "AMQ Message Content",
VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES, VIEW_MSG_CONTENT_COMPOSITE_ITEM_DESCRIPTIONS,
_msgContentAttributeTypes);
@@ -141,9 +133,9 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
_msgAttributeTypes[3] = SimpleType.BOOLEAN; // For redelivered
_msgAttributeTypes[4] = SimpleType.LONG; // For queue position
- _messageDataType = new CompositeType("Message", "AMQ Message", VIEW_MSGS_COMPOSITE_ITEM_NAMES,
+ _messageDataType = new CompositeType("Message", "AMQ Message", VIEW_MSGS_COMPOSITE_ITEM_NAMES,
VIEW_MSGS_COMPOSITE_ITEM_DESCRIPTIONS, _msgAttributeTypes);
- _messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType,
+ _messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType,
VIEW_MSGS_TABULAR_UNIQUE_INDEX);
}
@@ -164,7 +156,11 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
public String getOwner()
{
- return String.valueOf(_queue.getOwner());
+ return String.valueOf(_queue.getPrincipalHolder() == null
+ ? null
+ : _queue.getPrincipalHolder().getPrincipal() == null
+ ? null
+ : _queue.getPrincipalHolder().getPrincipal().getName());
}
public boolean isAutoDelete()
@@ -246,7 +242,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
/**
* Checks if there is any notification to be send to the listeners
*/
- public void checkForNotification(AMQMessage msg) throws AMQException
+ public void checkForNotification(ServerMessage msg) throws AMQException
{
final Set<NotificationCheck> notificationChecks = _queue.getNotificationChecks();
@@ -296,32 +292,18 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
*/
public void deleteMessageFromTop() throws JMException
{
- try
- {
- _queue.deleteMessageFromTop(_storeContext);
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
+ _queue.deleteMessageFromTop();
}
/**
* Clears the queue of non-acquired messages
- *
+ *
* @return the number of messages deleted
* @see AMQQueue#clearQueue
*/
public Long clearQueue() throws JMException
{
- try
- {
- return _queue.clearQueue(_storeContext);
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
+ return _queue.clearQueue();
}
/**
@@ -336,49 +318,41 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
throw new OperationsException("AMQMessage with message id = " + msgId + " is not in the " + _queueName);
}
- AMQMessage msg = entry.getMessage();
- // get message content
- Iterator<ContentChunk> cBodies = msg.getContentBodyIterator();
+ ServerMessage serverMsg = entry.getMessage();
+ final int bodySize = (int) serverMsg.getSize();
+
+
List<Byte> msgContent = new ArrayList<Byte>();
- while (cBodies.hasNext())
- {
- ContentChunk body = cBodies.next();
- if (body.getSize() != 0)
- {
- if (body.getSize() != 0)
- {
- ByteBuffer slice = body.getData().slice();
- for (int j = 0; j < slice.limit(); j++)
- {
- msgContent.add(slice.get());
- }
- }
- }
- }
- try
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(bodySize);
+ int position = 0;
+
+ while(position < bodySize)
{
- // Create header attributes list
- CommonContentHeaderProperties headerProperties =
- (CommonContentHeaderProperties) msg.getContentHeaderBody().properties;
- String mimeType = null, encoding = null;
- if (headerProperties != null)
+ position += serverMsg.getContent(buf, position);
+ buf.flip();
+ for(int i = 0; i < buf.limit(); i++)
{
- AMQShortString mimeTypeShortSting = headerProperties.getContentType();
- mimeType = (mimeTypeShortSting == null) ? null : mimeTypeShortSting.toString();
- encoding = (headerProperties.getEncoding() == null) ? "" : headerProperties.getEncoding().toString();
+ msgContent.add(buf.get(i));
}
+ buf.clear();
+ }
- Object[] itemValues = { msgId, mimeType, encoding, msgContent.toArray(new Byte[0]) };
+ AMQMessageHeader header = serverMsg.getMessageHeader();
- return new CompositeDataSupport(_msgContentType, VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES, itemValues);
- }
- catch (AMQException e)
+ String mimeType = null, encoding = null;
+ if (header != null)
{
- JMException jme = new JMException("Error creating header attributes list: " + e);
- jme.initCause(e);
- throw jme;
+ mimeType = header.getMimeType();
+
+ encoding = header.getEncoding();
}
+
+
+ Object[] itemValues = { msgId, mimeType, encoding, msgContent.toArray(new Byte[0]) };
+
+ return new CompositeDataSupport(_msgContentType, VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES, itemValues);
+
}
/**
@@ -390,8 +364,8 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
{
return viewMessages((long)beginIndex,(long)endIndex);
}
-
-
+
+
/**
* Returns the header contents of the messages stored in this queue in tabular form.
* @param startPosition The queue position of the first message to be viewed
@@ -404,7 +378,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
throw new OperationsException("From Index = " + startPosition + ", To Index = " + endPosition
+ "\n\"From Index\" should be greater than 0 and less than \"To Index\"");
}
-
+
if ((endPosition - startPosition) > Integer.MAX_VALUE)
{
throw new OperationsException("Specified MessageID interval is too large. Intervals must be less than 2^31 in size");
@@ -421,13 +395,22 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
for (int i = 0; i < size ; i++)
{
long position = startPosition + i;
- AMQMessage msg = list.get(i).getMessage();
- ContentHeaderBody headerBody = msg.getContentHeaderBody();
- // Create header attributes list
- String[] headerAttributes = getMessageHeaderProperties(headerBody);
- Object[] itemValues = { msg.getMessageId(), headerAttributes, headerBody.bodySize, msg.isRedelivered(), position};
- CompositeData messageData = new CompositeDataSupport(_messageDataType, VIEW_MSGS_COMPOSITE_ITEM_NAMES, itemValues);
- _messageList.put(messageData);
+ final QueueEntry queueEntry = list.get(i);
+ ServerMessage serverMsg = queueEntry.getMessage();
+ if(serverMsg instanceof AMQMessage)
+ {
+ AMQMessage msg = (AMQMessage) serverMsg;
+ ContentHeaderBody headerBody = msg.getContentHeaderBody();
+ // Create header attributes list
+ String[] headerAttributes = getMessageHeaderProperties(headerBody);
+ Object[] itemValues = { msg.getMessageId(), headerAttributes, headerBody.bodySize, queueEntry.isRedelivered(), position};
+ CompositeData messageData = new CompositeDataSupport(_messageDataType, VIEW_MSGS_COMPOSITE_ITEM_NAMES, itemValues);
+ _messageList.put(messageData);
+ }
+ else
+ {
+ // TODO 0-10 Message
+ }
}
}
catch (AMQException e)
@@ -484,7 +467,9 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
}
- _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, _storeContext);
+ ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getTransactionLog());
+ _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn);
+ txn.commit();
}
/**
@@ -500,9 +485,9 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
}
- _queue.removeMessagesFromQueue(fromMessageId, toMessageId, _storeContext);
+ _queue.removeMessagesFromQueue(fromMessageId, toMessageId);
}
-
+
/**
* @see ManagedQueue#copyMessages
* @param fromMessageId
@@ -517,9 +502,15 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
}
- _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, _storeContext);
+ ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getTransactionLog());
+
+ _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, txn);
+
+ txn.commit();
+
+
}
-
+
/**
* returns Notifications sent by this MBean.
*/
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
index cbe9246f09..aea485e749 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -44,12 +44,12 @@ public class DefaultQueueRegistry implements QueueRegistry
return _virtualHost;
}
- public void registerQueue(AMQQueue queue) throws AMQException
+ public void registerQueue(AMQQueue queue)
{
_queueMap.put(queue.getName(), queue);
}
- public void unregisterQueue(AMQShortString name) throws AMQException
+ public void unregisterQueue(AMQShortString name)
{
_queueMap.remove(name);
}
@@ -68,4 +68,9 @@ public class DefaultQueueRegistry implements QueueRegistry
{
return _queueMap.values();
}
+
+ public AMQQueue getQueue(String queue)
+ {
+ return getQueue(new AMQShortString(queue));
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/Filterable.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/Filterable.java
index d38932bb61..eaa3992e98 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/Filterable.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/Filterable.java
@@ -22,12 +22,13 @@ package org.apache.qpid.server.queue;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.message.AMQMessageHeader;
-public interface Filterable<E extends Exception>
+public interface Filterable
{
- ContentHeaderBody getContentHeaderBody() throws E;
+ AMQMessageHeader getMessageHeader();
- boolean isPersistent() throws E;
+ boolean isPersistent();
boolean isRedelivered();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java
deleted file mode 100644
index 35ad5be4e0..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.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.queue;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Collections;
-import java.util.ArrayList;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.server.store.StoreContext;
-
-/**
- */
-public class InMemoryMessageHandle implements AMQMessageHandle
-{
-
- private ContentHeaderBody _contentHeaderBody;
-
- private MessagePublishInfo _messagePublishInfo;
-
- private List<ContentChunk> _contentBodies;
-
- private boolean _redelivered;
-
- private long _arrivalTime;
-
- private final Long _messageId;
-
- public InMemoryMessageHandle(final Long messageId)
- {
- _messageId = messageId;
- }
-
- public ContentHeaderBody getContentHeaderBody(StoreContext context) throws AMQException
- {
- return _contentHeaderBody;
- }
-
- public Long getMessageId()
- {
- return _messageId;
- }
-
- public int getBodyCount(StoreContext context)
- {
- return _contentBodies.size();
- }
-
- public long getBodySize(StoreContext context) throws AMQException
- {
- return getContentHeaderBody(context).bodySize;
- }
-
- public ContentChunk getContentChunk(StoreContext context, int index) throws AMQException, IllegalArgumentException
- {
- if (index > _contentBodies.size() - 1)
- {
- throw new IllegalArgumentException("Index " + index + " out of valid range 0 to " +
- (_contentBodies.size() - 1));
- }
- return _contentBodies.get(index);
- }
-
- public void addContentBodyFrame(StoreContext storeContext, ContentChunk contentBody, boolean isLastContentBody)
- throws AMQException
- {
- if(_contentBodies == null)
- {
- if(isLastContentBody)
- {
- _contentBodies = Collections.singletonList(contentBody);
- }
- else
- {
- _contentBodies = new ArrayList<ContentChunk>();
- _contentBodies.add(contentBody);
- }
- }
- else
- {
- _contentBodies.add(contentBody);
- }
- }
-
- public MessagePublishInfo getMessagePublishInfo(StoreContext context) throws AMQException
- {
- return _messagePublishInfo;
- }
-
- public boolean isRedelivered()
- {
- return _redelivered;
- }
-
-
- public void setRedelivered(boolean redelivered)
- {
- _redelivered = redelivered;
- }
-
- public boolean isPersistent()
- {
- return false;
- }
-
- /**
- * This is called when all the content has been received.
- * @param messagePublishInfo
- * @param contentHeaderBody
- * @throws AMQException
- */
- public void setPublishAndContentHeaderBody(StoreContext storeContext, MessagePublishInfo messagePublishInfo,
- ContentHeaderBody contentHeaderBody)
- throws AMQException
- {
- _messagePublishInfo = messagePublishInfo;
- _contentHeaderBody = contentHeaderBody;
- if(contentHeaderBody.bodySize == 0)
- {
- _contentBodies = Collections.EMPTY_LIST;
- }
- _arrivalTime = System.currentTimeMillis();
- }
-
- public void removeMessage(StoreContext storeContext) throws AMQException
- {
- // NO OP
- }
-
- public long getArrivalTime()
- {
- return _arrivalTime;
- }
-
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NoConsumersException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java
index d6fd1eec89..77da08d8c4 100644..100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NoConsumersException.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java
@@ -18,30 +18,54 @@
* under the License.
*
*/
+
package org.apache.qpid.server.queue;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.RequiredDeliveryException;
+import org.apache.qpid.server.message.InboundMessage;
+import org.apache.qpid.server.message.AMQMessageHeader;
-/**
- * NoConsumersException is a {@link RequiredDeliveryException} that represents the failure case where an immediate
- * message cannot be delivered because there are presently no consumers for the message. The AMQP status code, 313, is
- * always used to report this condition.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represent failure to deliver a message that must be delivered.
- * </table>
- */
-public class NoConsumersException extends RequiredDeliveryException
+class InboundMessageAdapter implements InboundMessage
{
- public NoConsumersException(AMQMessage message)
+
+ private QueueEntry _entry;
+
+ InboundMessageAdapter()
+ {
+ }
+
+ InboundMessageAdapter(QueueEntry entry)
+ {
+ _entry = entry;
+ }
+
+ public void setEntry(QueueEntry entry)
+ {
+ _entry = entry;
+ }
+
+
+ public String getRoutingKey()
+ {
+ return _entry.getMessage().getRoutingKey();
+ }
+
+ public AMQMessageHeader getMessageHeader()
+ {
+ return _entry.getMessageHeader();
+ }
+
+ public boolean isPersistent()
+ {
+ return _entry.isPersistent();
+ }
+
+ public boolean isRedelivered()
{
- super("Immediate delivery is not possible.", message);
+ return _entry.isRedelivered();
}
- public AMQConstant getReplyCode()
+ public long getSize()
{
- return AMQConstant.NO_CONSUMERS;
+ return _entry.getSize();
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
index d5e0b4d187..da4173d5d3 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
@@ -25,19 +25,22 @@ import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.server.txn.TransactionalContext;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.exchange.NoRouteException;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.message.InboundMessage;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.message.MessageContentSource;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.AMQException;
import org.apache.log4j.Logger;
import java.util.ArrayList;
-import java.util.Collection;
+import java.util.List;
+import java.nio.ByteBuffer;
-public class IncomingMessage implements Filterable<RuntimeException>
+public class IncomingMessage implements Filterable, InboundMessage, EnqueableMessage, MessageContentSource
{
/** Used for debugging purposes. */
@@ -48,12 +51,6 @@ public class IncomingMessage implements Filterable<RuntimeException>
private final MessagePublishInfo _messagePublishInfo;
private ContentHeaderBody _contentHeaderBody;
- private AMQMessageHandle _messageHandle;
- private final Long _messageId;
- private final TransactionalContext _txnContext;
-
- private static final boolean MSG_AUTH =
- ApplicationRegistry.getInstance().getConfiguration().getMsgAuth();
/**
@@ -68,23 +65,27 @@ public class IncomingMessage implements Filterable<RuntimeException>
*/
private ArrayList<AMQQueue> _destinationQueues;
- private AMQProtocolSession _publisher;
- private MessageStore _messageStore;
private long _expiration;
-
+
private Exchange _exchange;
- public IncomingMessage(final Long messageId,
- final MessagePublishInfo info,
- final TransactionalContext txnContext,
- final AMQProtocolSession publisher)
+ 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
+ // store would otherwise flow it to disk
+
+ private MessageMetaData _messageMetaData;
+
+ private StoredMessage<MessageMetaData> _storedMessageHandle;
+
+
+ public IncomingMessage(
+ final MessagePublishInfo info
+ )
{
- _messageId = messageId;
_messagePublishInfo = info;
- _txnContext = txnContext;
- _publisher = publisher;
-
}
public void setContentHeaderBody(final ContentHeaderBody contentHeaderBody) throws AMQException
@@ -123,183 +124,94 @@ public class IncomingMessage implements Filterable<RuntimeException>
}
- public void routingComplete(final MessageStore store,
- final MessageHandleFactory factory) throws AMQException
+ public MessageMetaData headersReceived()
{
-
- final boolean persistent = isPersistent();
- _messageHandle = factory.createMessageHandle(_messageId, store, persistent);
- if (persistent)
- {
- _txnContext.beginTranIfNecessary();
- // enqueuing the messages ensure that if required the destinations are recorded to a
- // persistent store
-
- if(_destinationQueues != null)
- {
- for (int i = 0; i < _destinationQueues.size(); i++)
- {
- store.enqueueMessage(_txnContext.getStoreContext(),
- _destinationQueues.get(i), _messageId);
- }
- }
- }
+ _messageMetaData = new MessageMetaData(_messagePublishInfo, _contentHeaderBody, 0);
+ return _messageMetaData;
}
- public AMQMessage deliverToQueues()
- throws AMQException
- {
-
- // we get a reference to the destination queues now so that we can clear the
- // transient message data as quickly as possible
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Delivering message " + _messageId + " to " + _destinationQueues);
- }
-
- AMQMessage message = null;
-
- try
- {
- // first we allow the handle to know that the message has been fully received. This is useful if it is
- // maintaining any calculated values based on content chunks
- _messageHandle.setPublishAndContentHeaderBody(_txnContext.getStoreContext(),
- _messagePublishInfo, getContentHeaderBody());
-
-
-
- message = new AMQMessage(_messageHandle,_txnContext.getStoreContext(), _messagePublishInfo);
-
- message.setExpiration(_expiration);
- message.setClientIdentifier(_publisher.getSessionIdentifier());
-
- // we then allow the transactional context to do something with the message content
- // now that it has all been received, before we attempt delivery
- _txnContext.messageFullyReceived(isPersistent());
-
- AMQShortString userID = getContentHeaderBody().properties instanceof BasicContentHeaderProperties ?
- ((BasicContentHeaderProperties) getContentHeaderBody().properties).getUserId() : null;
-
- if (MSG_AUTH && !_publisher.getAuthorizedID().getName().equals(userID == null? "" : userID.toString()))
- {
- throw new UnauthorizedAccessException("Acccess Refused",message);
- }
-
- if ((_destinationQueues == null) || _destinationQueues.size() == 0)
- {
-
- if (isMandatory() || isImmediate())
- {
- throw new NoRouteException("No Route for message", message);
-
- }
- else
- {
- _logger.warn("MESSAGE DISCARDED: No routes for message - " + message);
- }
- }
- else
- {
- int offset;
- final int queueCount = _destinationQueues.size();
- message.incrementReference(queueCount);
- if(queueCount == 1)
- {
- offset = 0;
- }
- else
- {
- offset = ((int)(message.getMessageId().longValue())) % queueCount;
- if(offset < 0)
- {
- offset = -offset;
- }
- }
- for (int i = offset; i < queueCount; i++)
- {
- // normal deliver so add this message at the end.
- _txnContext.deliver(_destinationQueues.get(i), message);
- }
- for (int i = 0; i < offset; i++)
- {
- // normal deliver so add this message at the end.
- _txnContext.deliver(_destinationQueues.get(i), message);
- }
- }
-
- message.clearStoreContext();
- return message;
- }
- finally
- {
- // Remove refence for routing process . Reference count should now == delivered queue count
- if(message != null) message.decrementReference(_txnContext.getStoreContext());
- }
+ public ArrayList<AMQQueue> getDestinationQueues()
+ {
+ return _destinationQueues;
}
- public void addContentBodyFrame(final ContentChunk contentChunk)
+ public int addContentBodyFrame(final ContentChunk contentChunk)
throws AMQException
{
-
+ _storedMessageHandle.addContent((int)_bodyLengthReceived, contentChunk.getData().buf());
_bodyLengthReceived += contentChunk.getSize();
+ _contentChunks.add(contentChunk);
+
- _messageHandle.addContentBodyFrame(_txnContext.getStoreContext(), contentChunk, allContentReceived());
+ return _receivedChunkCount++;
}
public boolean allContentReceived()
{
- return (_bodyLengthReceived == getContentHeaderBody().bodySize);
+ return (_bodyLengthReceived == getContentHeader().bodySize);
}
- public AMQShortString getExchange() throws AMQException
+ public AMQShortString getExchange()
{
return _messagePublishInfo.getExchange();
}
- public AMQShortString getRoutingKey() throws AMQException
+ public String getRoutingKey()
{
- return _messagePublishInfo.getRoutingKey();
+ return _messagePublishInfo.getRoutingKey() == null ? null : _messagePublishInfo.getRoutingKey().toString();
}
- public boolean isMandatory() throws AMQException
+ public String getBinding()
+ {
+ return _messagePublishInfo.getRoutingKey() == null ? null : _messagePublishInfo.getRoutingKey().toString();
+ }
+
+
+ public boolean isMandatory()
{
return _messagePublishInfo.isMandatory();
}
- public boolean isImmediate() throws AMQException
+ public boolean isImmediate()
{
return _messagePublishInfo.isImmediate();
}
- public ContentHeaderBody getContentHeaderBody()
+ public ContentHeaderBody getContentHeader()
{
return _contentHeaderBody;
}
+ public AMQMessageHeader getMessageHeader()
+ {
+ return _messageMetaData.getMessageHeader();
+ }
+
public boolean isPersistent()
{
- return getContentHeaderBody().properties instanceof BasicContentHeaderProperties &&
- ((BasicContentHeaderProperties) getContentHeaderBody().properties).getDeliveryMode() ==
+ return getContentHeader().properties instanceof BasicContentHeaderProperties &&
+ ((BasicContentHeaderProperties) getContentHeader().properties).getDeliveryMode() ==
BasicContentHeaderProperties.PERSISTENT;
}
-
+
public boolean isRedelivered()
{
return false;
}
- public void setMessageStore(final MessageStore messageStore)
+
+ public long getSize()
{
- _messageStore = messageStore;
+ return getContentHeader().bodySize;
}
- public Long getMessageId()
+ public Long getMessageNumber()
{
- return _messageId;
+ return _storedMessageHandle.getMessageNumber();
}
public void setExchange(final Exchange e)
@@ -307,13 +219,82 @@ public class IncomingMessage implements Filterable<RuntimeException>
_exchange = e;
}
- public void route() throws AMQException
+ public void route()
{
- _exchange.route(this);
+ enqueue(_exchange.route(this));
+
}
public void enqueue(final ArrayList<AMQQueue> queues)
{
_destinationQueues = queues;
}
+
+ public MessagePublishInfo getMessagePublishInfo()
+ {
+ return _messagePublishInfo;
+ }
+
+ public long getExpiration()
+ {
+ return _expiration;
+ }
+
+ public int getReceivedChunkCount()
+ {
+ return _receivedChunkCount;
+ }
+
+
+ public int getBodyCount() throws AMQException
+ {
+ return _contentChunks.size();
+ }
+
+ public ContentChunk getContentChunk(int index) throws IllegalArgumentException, AMQException
+ {
+ return _contentChunks.get(index);
+ }
+
+
+ public int getContent(ByteBuffer buf, int offset)
+ {
+ int pos = 0;
+ int written = 0;
+ for(ContentChunk cb : _contentChunks)
+ {
+ ByteBuffer data = cb.getData().buf();
+ if(offset+written >= pos && offset < pos + data.limit())
+ {
+ ByteBuffer src = data.duplicate();
+ src.position(offset+written - pos);
+ src = src.slice();
+
+ if(buf.remaining() < src.limit())
+ {
+ src.limit(buf.remaining());
+ }
+ int count = src.limit();
+ buf.put(src);
+ written += count;
+ if(buf.remaining() == 0)
+ {
+ break;
+ }
+ }
+ pos+=data.limit();
+ }
+ return written;
+
+ }
+
+ public void setStoredMessage(StoredMessage<MessageMetaData> storedMessageHandle)
+ {
+ _storedMessageHandle = storedMessageHandle;
+ }
+
+ public StoredMessage<MessageMetaData> getStoredMessage()
+ {
+ return _storedMessageHandle;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageMetaData.java
deleted file mode 100644
index 6118a4c11f..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/MessageMetaData.java
+++ /dev/null
@@ -1,92 +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.queue;
-
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-
-/**
- * Encapsulates a publish body and a content header. In the context of the message store these are treated as a
- * single unit.
- */
-public class MessageMetaData
-{
- private MessagePublishInfo _messagePublishInfo;
-
- private ContentHeaderBody _contentHeaderBody;
-
- private int _contentChunkCount;
-
- private long _arrivalTime;
-
- public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount)
- {
- this(publishBody,contentHeaderBody, contentChunkCount, System.currentTimeMillis());
- }
-
- public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount, long arrivalTime)
- {
- _contentHeaderBody = contentHeaderBody;
- _messagePublishInfo = publishBody;
- _contentChunkCount = contentChunkCount;
- _arrivalTime = arrivalTime;
- }
-
- public int getContentChunkCount()
- {
- return _contentChunkCount;
- }
-
- public void setContentChunkCount(int contentChunkCount)
- {
- _contentChunkCount = contentChunkCount;
- }
-
- public ContentHeaderBody getContentHeaderBody()
- {
- return _contentHeaderBody;
- }
-
- public void setContentHeaderBody(ContentHeaderBody contentHeaderBody)
- {
- _contentHeaderBody = contentHeaderBody;
- }
-
- public MessagePublishInfo getMessagePublishInfo()
- {
- return _messagePublishInfo;
- }
-
- public void setMessagePublishInfo(MessagePublishInfo messagePublishInfo)
- {
- _messagePublishInfo = messagePublishInfo;
- }
-
- public long getArrivalTime()
- {
- return _arrivalTime;
- }
-
- public void setArrivalTime(long arrivalTime)
- {
- _arrivalTime = arrivalTime;
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
index 6f9efd3200..d1fb0f3fe6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
@@ -21,13 +21,14 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.message.ServerMessage;
public enum NotificationCheck
{
MESSAGE_COUNT_ALERT
{
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
{
int msgCount;
final long maximumMessageCount = queue.getMaximumMessageCount();
@@ -41,26 +42,19 @@ public enum NotificationCheck
},
MESSAGE_SIZE_ALERT(true)
{
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
{
final long maximumMessageSize = queue.getMaximumMessageSize();
if(maximumMessageSize != 0)
{
// Check for threshold message size
long messageSize;
- try
- {
- messageSize = (msg == null) ? 0 : msg.getContentHeaderBody().bodySize;
- }
- catch (AMQException e)
- {
- messageSize = 0;
- }
+ messageSize = (msg == null) ? 0 : msg.getSize();
if (messageSize >= maximumMessageSize)
{
- listener.notifyClients(this, queue, messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageId() + "]");
+ listener.notifyClients(this, queue, messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageNumber() + "]");
return true;
}
}
@@ -70,7 +64,7 @@ public enum NotificationCheck
},
QUEUE_DEPTH_ALERT
{
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
{
// Check for threshold queue depth in bytes
final long maximumQueueDepth = queue.getMaximumQueueDepth();
@@ -91,7 +85,7 @@ public enum NotificationCheck
},
MESSAGE_AGE_ALERT
{
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
{
final long maxMessageAge = queue.getMaximumMessageAge();
@@ -133,6 +127,6 @@ public enum NotificationCheck
return _messageSpecific;
}
- abstract boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener);
+ abstract boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
index fd46a8a5ff..0c6b84d2b6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.queue;
import org.apache.qpid.framing.CommonContentHeaderProperties;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.message.ServerMessage;
public class PriorityQueueList implements QueueEntryList
{
@@ -52,26 +53,18 @@ public class PriorityQueueList implements QueueEntryList
return _queue;
}
- public QueueEntry add(AMQMessage message)
+ public QueueEntry add(ServerMessage message)
{
- try
+ int index = message.getMessageHeader().getPriority() - _priorityOffset;
+ if(index >= _priorities)
{
- int index = ((CommonContentHeaderProperties)((message.getContentHeaderBody().properties))).getPriority() - _priorityOffset;
- if(index >= _priorities)
- {
- index = _priorities-1;
- }
- else if(index < 0)
- {
- index = 0;
- }
- return _priorityLists[index].add(message);
+ index = _priorities-1;
}
- catch (AMQException e)
+ else if(index < 0)
{
- // TODO - fix AMQ Exception
- throw new RuntimeException(e);
+ index = 0;
}
+ return _priorityLists[index].add(message);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/UnauthorizedAccessException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java
index 295cb266b9..825a85a89c 100644..100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/UnauthorizedAccessException.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueContext.java
@@ -21,25 +21,29 @@
package org.apache.qpid.server.queue;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.RequiredDeliveryException;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-/**
- * UnauthorizedAccessException is a {@link RequiredDeliveryException} that represents the failure case where a message
- * is published with a user id different from the one used when creating the connection .
- * The AMQP status code, 403, is always used to report this condition.
- *
- */
-
-public class UnauthorizedAccessException extends RequiredDeliveryException
+final class QueueContext implements AMQQueue.Context
{
- public UnauthorizedAccessException(String msg, AMQMessage amqMessage)
+ volatile QueueEntry _lastSeenEntry;
+ volatile QueueEntry _releasedEntry;
+
+ static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry>
+ _lastSeenUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (QueueContext.class, QueueEntry.class, "_lastSeenEntry");
+ static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry>
+ _releasedUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (QueueContext.class, QueueEntry.class, "_releasedEntry");
+
+ public QueueContext(QueueEntry head)
{
- super(msg, amqMessage);
+ _lastSeenEntry = head;
}
- public AMQConstant getReplyCode()
+ public QueueEntry getLastSeenEntry()
{
- return AMQConstant.ACCESS_REFUSED;
+ return _lastSeenEntry;
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
index 2657c459a9..a50e2b561d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
@@ -1,8 +1,8 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.message.ServerMessage;
/*
*
@@ -24,18 +24,19 @@ import org.apache.qpid.server.subscription.Subscription;
* under the License.
*
*/
-public interface QueueEntry extends Comparable<QueueEntry>
+public interface QueueEntry extends Comparable<QueueEntry>, Filterable
{
-
public static enum State
{
AVAILABLE,
ACQUIRED,
EXPIRED,
DEQUEUED,
- DELETED
+ DELETED;
+
+
}
public static interface StateChangeListener
@@ -121,6 +122,27 @@ public interface QueueEntry extends Comparable<QueueEntry>
}
}
+ public final class SubscriptionAssignedState extends EntryState
+ {
+ private final Subscription _subscription;
+
+ public SubscriptionAssignedState(Subscription subscription)
+ {
+ _subscription = subscription;
+ }
+
+
+ public State getState()
+ {
+ return State.AVAILABLE;
+ }
+
+ public Subscription getSubscription()
+ {
+ return _subscription;
+ }
+ }
+
final static EntryState AVAILABLE_STATE = new AvailableState();
final static EntryState DELETED_STATE = new DeletedState();
@@ -133,7 +155,7 @@ public interface QueueEntry extends Comparable<QueueEntry>
AMQQueue getQueue();
- AMQMessage getMessage();
+ ServerMessage getMessage();
long getSize();
@@ -150,16 +172,17 @@ public interface QueueEntry extends Comparable<QueueEntry>
boolean isDeleted();
boolean acquiredBySubscription();
-
- void setDeliveredToSubscription();
+ boolean isAcquiredBy(Subscription subscription);
void release();
+ boolean releaseButRetain();
- String debugIdentity();
boolean immediateAndNotDelivered();
- void setRedelivered(boolean b);
+ void setRedelivered();
+
+ boolean isRedelivered();
Subscription getDeliveredSubscription();
@@ -169,13 +192,15 @@ public interface QueueEntry extends Comparable<QueueEntry>
boolean isRejectedBy(Subscription subscription);
- void requeue(StoreContext storeContext) throws AMQException;
+ void requeue(Subscription subscription);
+
+ void dequeue();
- void dequeue(final StoreContext storeContext) throws FailedDequeueException;
+ void dispose();
- void dispose(final StoreContext storeContext) throws MessageCleanupException;
+ void discard();
- void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException;
+ void routeToAlternate();
boolean isQueueDeleted();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
index 3b58f05f93..5873e8f566 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
@@ -21,12 +21,16 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.log4j.Logger;
-import java.util.Set;
-import java.util.HashSet;
+import java.util.*;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -42,7 +46,7 @@ public class QueueEntryImpl implements QueueEntry
private final SimpleQueueEntryList _queueEntryList;
- private final AMQMessage _message;
+ private MessageReference _message;
private Set<Subscription> _rejectedBy = null;
@@ -75,6 +79,11 @@ public class QueueEntryImpl implements QueueEntry
volatile QueueEntryImpl _next;
+ private static final int DELIVERED_TO_CONSUMER = 1;
+ private static final int REDELIVERED = 2;
+
+ private volatile int _deliveryState;
+
QueueEntryImpl(SimpleQueueEntryList queueEntryList)
{
@@ -83,18 +92,19 @@ public class QueueEntryImpl implements QueueEntry
}
- public QueueEntryImpl(SimpleQueueEntryList queueEntryList, AMQMessage message, final long entryId)
+ public QueueEntryImpl(SimpleQueueEntryList queueEntryList, ServerMessage message, final long entryId)
{
_queueEntryList = queueEntryList;
- _message = message;
+
+ _message = message == null ? null : message.newReference();
_entryIdUpdater.set(this, entryId);
}
- public QueueEntryImpl(SimpleQueueEntryList queueEntryList, AMQMessage message)
+ public QueueEntryImpl(SimpleQueueEntryList queueEntryList, ServerMessage message)
{
_queueEntryList = queueEntryList;
- _message = message;
+ _message = message == null ? null : message.newReference();
}
protected void setEntryId(long entryId)
@@ -112,24 +122,36 @@ public class QueueEntryImpl implements QueueEntry
return _queueEntryList.getQueue();
}
- public AMQMessage getMessage()
+ public ServerMessage getMessage()
{
- return _message;
+ return _message == null ? null : _message.getMessage();
}
public long getSize()
{
- return getMessage().getSize();
+ return getMessage() == null ? 0 : getMessage().getSize();
}
public boolean getDeliveredToConsumer()
{
- return getMessage().getDeliveredToConsumer();
+ return (_deliveryState & DELIVERED_TO_CONSUMER) != 0;
}
public boolean expired() throws AMQException
{
- return getMessage().expired(getQueue());
+ ServerMessage message = getMessage();
+ if(message != null)
+ {
+ long expiration = message.getExpiration();
+ if (expiration != 0L)
+ {
+ long now = System.currentTimeMillis();
+
+ return (now > expiration);
+ }
+ }
+ return false;
+
}
public boolean isAcquired()
@@ -145,6 +167,24 @@ public class QueueEntryImpl implements QueueEntry
private boolean acquire(final EntryState state)
{
boolean acquired = _stateUpdater.compareAndSet(this,AVAILABLE_STATE, state);
+
+ // deal with the case where the node has been assigned to a given subscription already
+ // including the case that the node is assigned to a closed subscription
+ if(!acquired)
+ {
+ if(state != NON_SUBSCRIPTION_ACQUIRED_STATE)
+ {
+ EntryState currentState = _state;
+ if(currentState.getState() == State.AVAILABLE
+ && ((currentState == AVAILABLE_STATE)
+ || (((SubscriptionAcquiredState)state).getSubscription() ==
+ ((SubscriptionAssignedState)currentState).getSubscription())
+ || ((SubscriptionAssignedState)currentState).getSubscription().isClosed() ))
+ {
+ acquired = _stateUpdater.compareAndSet(this,currentState, state);
+ }
+ }
+ }
if(acquired && _stateChangeListeners != null)
{
notifyStateChange(State.AVAILABLE, State.ACQUIRED);
@@ -155,7 +195,12 @@ public class QueueEntryImpl implements QueueEntry
public boolean acquire(Subscription sub)
{
- return acquire(sub.getOwningState());
+ final boolean acquired = acquire(sub.getOwningState());
+ if(acquired)
+ {
+ _deliveryState |= DELIVERED_TO_CONSUMER;
+ }
+ return acquired;
}
public boolean acquiredBySubscription()
@@ -164,38 +209,89 @@ public class QueueEntryImpl implements QueueEntry
return (_state instanceof SubscriptionAcquiredState);
}
- public void setDeliveredToSubscription()
+ public boolean isAcquiredBy(Subscription subscription)
{
- getMessage().setDeliveredToConsumer();
+ EntryState state = _state;
+ return state instanceof SubscriptionAcquiredState
+ && ((SubscriptionAcquiredState)state).getSubscription() == subscription;
}
public void release()
{
_stateUpdater.set(this,AVAILABLE_STATE);
- }
+ if(!getQueue().isDeleted())
+ {
+ getQueue().requeue(this);
+ if(_stateChangeListeners != null)
+ {
+ notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE);
+ }
- public String debugIdentity()
- {
- AMQMessage message = getMessage();
- if (message == null)
+ }
+ else if(acquire())
{
- return "null";
+ routeToAlternate();
}
- else
+
+
+ }
+
+ public boolean releaseButRetain()
+ {
+ EntryState state = _state;
+
+ boolean stateUpdated = false;
+
+ if(state instanceof SubscriptionAcquiredState)
{
- return message.debugIdentity();
+ 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)
+ {
+ notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE);
+ }
+ stateUpdated = true;
+ }
}
+
+ return stateUpdated;
+
}
+ public boolean immediateAndNotDelivered()
+ {
+ return !getDeliveredToConsumer() && isImmediate();
+ }
+
+ private boolean isImmediate()
+ {
+ final ServerMessage message = getMessage();
+ return message != null && message.isImmediate();
+ }
- public boolean immediateAndNotDelivered()
+ public void setRedelivered()
{
- return getMessage().immediateAndNotDelivered();
+ _deliveryState |= REDELIVERED;
}
- public void setRedelivered(boolean b)
+ public AMQMessageHeader getMessageHeader()
{
- getMessage().setRedelivered(b);
+ final ServerMessage message = getMessage();
+ return message == null ? null : message.getMessageHeader();
+ }
+
+ public boolean isPersistent()
+ {
+ final ServerMessage message = getMessage();
+ return message != null && message.isPersistent();
+ }
+
+ public boolean isRedelivered()
+ {
+ return (_deliveryState & REDELIVERED) != 0;
}
public Subscription getDeliveredSubscription()
@@ -230,12 +326,12 @@ public class QueueEntryImpl implements QueueEntry
}
else
{
- _log.warn("Requesting rejection by null subscriber:" + debugIdentity());
+ _log.warn("Requesting rejection by null subscriber:" + this);
}
}
public boolean isRejectedBy(Subscription subscription)
- {
+ {
if (_rejectedBy != null) // We have subscriptions that rejected this message
{
@@ -247,17 +343,16 @@ public class QueueEntryImpl implements QueueEntry
}
}
-
- public void requeue(final StoreContext storeContext) throws AMQException
+ public void requeue(Subscription subscription)
{
- getQueue().requeue(storeContext, this);
+ getQueue().requeue(this, subscription);
if(_stateChangeListeners != null)
{
notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE);
}
}
- public void dequeue(final StoreContext storeContext) throws FailedDequeueException
+ public void dequeue()
{
EntryState state = _state;
@@ -266,10 +361,10 @@ public class QueueEntryImpl implements QueueEntry
if (state instanceof SubscriptionAcquiredState)
{
Subscription s = ((SubscriptionAcquiredState) state).getSubscription();
- s.restoreCredit(this);
+ s.onDequeue(this);
}
- getQueue().dequeue(storeContext, this);
+ getQueue().dequeue(this);
if(_stateChangeListeners != null)
{
notifyStateChange(state.getState() , QueueEntry.State.DEQUEUED);
@@ -287,23 +382,74 @@ public class QueueEntryImpl implements QueueEntry
}
}
- public void dispose(final StoreContext storeContext) throws MessageCleanupException
+ public void dispose()
{
if(delete())
{
- getMessage().decrementReference(storeContext);
+ _message.release();
}
}
- public void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException
+ public void discard()
{
//if the queue is null then the message is waiting to be acked, but has been removed.
if (getQueue() != null)
{
- dequeue(storeContext);
+ dequeue();
}
- dispose(storeContext);
+ dispose();
+ }
+
+ public void routeToAlternate()
+ {
+ final AMQQueue currentQueue = getQueue();
+ Exchange alternateExchange = currentQueue.getAlternateExchange();
+
+ if(alternateExchange != null)
+ {
+ final List<AMQQueue> rerouteQueues = alternateExchange.route(new InboundMessageAdapter(this));
+ final ServerMessage message = getMessage();
+ if(rerouteQueues != null && rerouteQueues.size() != 0)
+ {
+ ServerTransaction txn = new AutoCommitTransaction(getQueue().getVirtualHost().getTransactionLog());
+
+ txn.enqueue(rerouteQueues, message, new ServerTransaction.Action() {
+ public void postCommit()
+ {
+ try
+ {
+ for(AMQQueue queue : rerouteQueues)
+ {
+ QueueEntry entry = queue.enqueue(message);
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ txn.dequeue(currentQueue,message,
+ new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ discard();
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ }
+ }
}
public boolean isQueueDeleted()
@@ -379,7 +525,7 @@ public class QueueEntryImpl implements QueueEntry
if(state != DELETED_STATE && _stateUpdater.compareAndSet(this,state,DELETED_STATE))
{
- _queueEntryList.advanceHead();
+ _queueEntryList.advanceHead();
return true;
}
else
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
index 313e076f61..b4042ce02c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
@@ -20,11 +20,13 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.qpid.server.message.ServerMessage;
+
public interface QueueEntryList
{
AMQQueue getQueue();
- QueueEntry add(AMQMessage message);
+ QueueEntry add(ServerMessage message);
QueueEntry next(QueueEntry node);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
index 1210f0e97c..a537e0c83f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -30,9 +30,9 @@ public interface QueueRegistry
{
VirtualHost getVirtualHost();
- void registerQueue(AMQQueue queue) throws AMQException;
+ void registerQueue(AMQQueue queue);
- void unregisterQueue(AMQShortString name) throws AMQException;
+ void unregisterQueue(AMQShortString name);
AMQQueue getQueue(AMQShortString name);
@@ -40,4 +40,5 @@ public interface QueueRegistry
Collection<AMQQueue> getQueues();
+ AMQQueue getQueue(String queue);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
index d781dc4dea..77a6fb9328 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
@@ -3,12 +3,9 @@ package org.apache.qpid.server.queue;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
import javax.management.JMException;
@@ -21,13 +18,12 @@ import org.apache.qpid.pool.ReferenceCountingExecutorService;
import org.apache.qpid.server.configuration.QueueConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.subscription.SubscriptionList;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.QueueActor;
import org.apache.qpid.server.logging.subjects.QueueLogSubject;
@@ -35,6 +31,9 @@ import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.logging.messages.QueueMessages;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.LocalTransaction;
/*
*
@@ -60,24 +59,40 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
{
private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class);
+
+ private final VirtualHost _virtualHost;
+
private final AMQShortString _name;
+ private final String _resourceName;
/** null means shared */
private final AMQShortString _owner;
+ private PrincipalHolder _prinicpalHolder;
+
+ private Object _exclusiveOwner;
+
+
private final boolean _durable;
/** If true, this queue is deleted when the last subscriber is removed */
private final boolean _autoDelete;
- private final VirtualHost _virtualHost;
+ private Exchange _alternateExchange;
/** Used to track bindings to exchanges so that on deletion they can easily be cancelled. */
private final ExchangeBindings _bindings = new ExchangeBindings(this);
- private final AtomicBoolean _deleted = new AtomicBoolean(false);
- private final List<Task> _deleteTaskList = new CopyOnWriteArrayList<Task>();
+ protected final QueueEntryList _entries;
+
+ protected final SubscriptionList _subscriptionList = new SubscriptionList(this);
+
+ private final AtomicReference<SubscriptionList.SubscriptionNode> _lastSubscriptionNode = new AtomicReference<SubscriptionList.SubscriptionNode>(_subscriptionList.getHead());
+
+ private volatile Subscription _exclusiveSubscriber;
+
+
private final AtomicInteger _atomicQueueCount = new AtomicInteger(0);
@@ -85,18 +100,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
private final AtomicInteger _activeSubscriberCount = new AtomicInteger();
- protected final SubscriptionList _subscriptionList = new SubscriptionList(this);
- private final AtomicReference<SubscriptionList.SubscriptionNode> _lastSubscriptionNode = new AtomicReference<SubscriptionList.SubscriptionNode>(_subscriptionList.getHead());
-
- private volatile Subscription _exclusiveSubscriber;
+ private final AtomicLong _totalMessagesReceived = new AtomicLong();
- protected final QueueEntryList _entries;
- private final AMQQueueMBean _managedObject;
- private final Executor _asyncDelivery;
- private final AtomicLong _totalMessagesReceived = new AtomicLong();
- private final ConcurrentMap<AMQChannel, Boolean> _blockedChannels = new ConcurrentHashMap<AMQChannel, Boolean>();
/** max allowed size(KB) of a single message */
public long _maximumMessageSize = ApplicationRegistry.getInstance().getConfiguration().getMaximumMessageSize();
@@ -113,24 +120,38 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
/** the minimum interval between sending out consecutive alerts of the same type */
public long _minimumAlertRepeatGap = ApplicationRegistry.getInstance().getConfiguration().getMinimumAlertRepeatGap();
- private static final int MAX_ASYNC_DELIVERIES = 10;
+ private long _capacity = ApplicationRegistry.getInstance().getConfiguration().getCapacity();
+
+ private long _flowResumeCapacity = ApplicationRegistry.getInstance().getConfiguration().getFlowResumeCapacity();
private final Set<NotificationCheck> _notificationChecks = EnumSet.noneOf(NotificationCheck.class);
+
+ static final int MAX_ASYNC_DELIVERIES = 10;
+
+
private final AtomicLong _stateChangeCount = new AtomicLong(Long.MIN_VALUE);
private AtomicReference _asynchronousRunner = new AtomicReference(null);
+ private final Executor _asyncDelivery;
private AtomicInteger _deliveredMessages = new AtomicInteger();
private AtomicBoolean _stopped = new AtomicBoolean(false);
+
+ private final ConcurrentMap<AMQChannel, Boolean> _blockedChannels = new ConcurrentHashMap<AMQChannel, Boolean>();
+
+ private final AtomicBoolean _deleted = new AtomicBoolean(false);
+ private final List<Task> _deleteTaskList = new CopyOnWriteArrayList<Task>();
+
+
private LogSubject _logSubject;
private LogActor _logActor;
+ private AMQQueueMBean _managedObject;
+ private static final String SUB_FLUSH_RUNNER = "SUB_FLUSH_RUNNER";
+ private boolean _nolocal;
- private long _capacity = ApplicationRegistry.getInstance().getConfiguration().getCapacity();
- private long _flowResumeCapacity = ApplicationRegistry.getInstance().getConfiguration().getFlowResumeCapacity();
private final AtomicBoolean _overfull = new AtomicBoolean(false);
protected SimpleAMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, VirtualHost virtualHost)
- throws AMQException
{
this(name, durable, owner, autoDelete, virtualHost, new SimpleQueueEntryList.Factory());
}
@@ -141,7 +162,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
boolean autoDelete,
VirtualHost virtualHost,
QueueEntryListFactory entryListFactory)
- throws AMQException
{
if (name == null)
@@ -155,6 +175,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
_name = name;
+ _resourceName = String.valueOf(name);
_durable = durable;
_owner = owner;
_autoDelete = autoDelete;
@@ -193,13 +214,19 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
catch (JMException e)
{
- throw new AMQException("AMQQueue MBean creation has failed ", e);
+ _logger.error("AMQQueue MBean creation has failed ", e);
}
resetNotifications();
}
+ public SimpleAMQQueue(String queueName, boolean durable, String owner, boolean autoDelete, VirtualHost virtualHost)
+ throws AMQException
+ {
+ this(new AMQShortString(queueName), durable, owner == null ? null : new AMQShortString(owner),autoDelete,virtualHost);
+ }
+
public void resetNotifications()
{
// This ensure that the notification checks for the configured alerts are created.
@@ -211,16 +238,54 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
// ------ Getters and Setters
+ public void execute(ReadWriteRunnable runnable)
+ {
+ _asyncDelivery.execute(runnable);
+ }
+
public AMQShortString getName()
{
return _name;
}
+ public void setNoLocal(boolean nolocal)
+ {
+ _nolocal = nolocal;
+ }
+
public boolean isDurable()
{
return _durable;
}
+ public boolean isExclusive()
+ {
+ return _exclusiveOwner != null;
+ }
+
+ public Exchange getAlternateExchange()
+ {
+ return _alternateExchange;
+ }
+
+ public void setAlternateExchange(Exchange exchange)
+ {
+ if(_alternateExchange != null)
+ {
+ _alternateExchange.removeReference(this);
+ }
+ if(exchange != null)
+ {
+ exchange.addReference(this);
+ }
+ _alternateExchange = exchange;
+ }
+
+ public Map<String, Object> getArguments()
+ {
+ return null;
+ }
+
public boolean isAutoDelete()
{
return _autoDelete;
@@ -231,6 +296,17 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
return _owner;
}
+ public PrincipalHolder getPrincipalHolder()
+ {
+ return _prinicpalHolder;
+ }
+
+ public void setPrincipalHolder(PrincipalHolder prinicpalHolder)
+ {
+ _prinicpalHolder = prinicpalHolder;
+ }
+
+
public VirtualHost getVirtualHost()
{
return _virtualHost;
@@ -238,13 +314,31 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
// ------ bind and unbind
+ public void bind(Exchange exchange, String bindingKey, Map<String, Object> arguments) throws AMQException
+ {
+
+ FieldTable fieldTable = FieldTable.convertToFieldTable(arguments);
+ AMQShortString routingKey = new AMQShortString(bindingKey);
+
+ exchange.registerQueue(routingKey, this, fieldTable);
+
+ if (isDurable() && exchange.isDurable())
+ {
+
+ _virtualHost.getDurableConfigurationStore().bindQueue(exchange, routingKey, this, fieldTable);
+ }
+
+ _bindings.addBinding(routingKey, fieldTable, exchange);
+ }
+
+
public void bind(Exchange exchange, AMQShortString routingKey, FieldTable arguments) throws AMQException
{
exchange.registerQueue(routingKey, this, arguments);
if (isDurable() && exchange.isDurable())
{
- _virtualHost.getMessageStore().bindQueue(exchange, routingKey, this, arguments);
+ _virtualHost.getDurableConfigurationStore().bindQueue(exchange, routingKey, this, arguments);
}
_bindings.addBinding(routingKey, arguments, exchange);
@@ -255,7 +349,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
exchange.deregisterQueue(routingKey, this, arguments);
if (isDurable() && exchange.isDurable())
{
- _virtualHost.getMessageStore().unbindQueue(exchange, routingKey, this, arguments);
+ _virtualHost.getDurableConfigurationStore().unbindQueue(exchange, routingKey, this, arguments);
}
boolean removed = _bindings.remove(routingKey, arguments, exchange);
@@ -295,11 +389,15 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
_activeSubscriberCount.incrementAndGet();
subscription.setStateListener(this);
- subscription.setLastSeenEntry(null, _entries.getHead());
+ subscription.setQueueContext(new QueueContext(_entries.getHead()));
if (!isDeleted())
{
subscription.setQueue(this, exclusive);
+ if(_nolocal)
+ {
+ subscription.setNoLocal(_nolocal);
+ }
_subscriptionList.add(subscription);
if (isDeleted())
{
@@ -329,17 +427,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
subscription.close();
// No longer can the queue have an exclusive consumer
setExclusiveSubscriber(null);
-
- QueueEntry lastSeen;
-
- while ((lastSeen = subscription.getLastSeenEntry()) != null)
- {
- subscription.setLastSeenEntry(lastSeen, null);
- }
+ subscription.setQueueContext(null);
// auto-delete queues must be deleted if there are no remaining subscribers
- if (_autoDelete && getConsumerCount() == 0)
+ if (_autoDelete && getConsumerCount() == 0 && !isExclusive())
{
if (_logger.isInfoEnabled())
{
@@ -358,7 +450,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
// ------ Enqueue / Dequeue
- public QueueEntry enqueue(StoreContext storeContext, AMQMessage message) throws AMQException
+ public QueueEntry enqueue(ServerMessage message) throws AMQException
{
incrementQueueCount();
@@ -378,14 +470,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
entry = _entries.add(message);
deliverToSubscription(exclusiveSub, entry);
-
- // where there is more than one producer there's a reasonable chance that even though there is
- // no "queueing" we do not deliver because we get an interleving of _entries.add and
- // deliverToSubscription between threads. Therefore have one more try.
- if (!(entry.isAcquired() || entry.isDeleted()))
- {
- deliverToSubscription(exclusiveSub, entry);
- }
}
finally
{
@@ -445,19 +529,18 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
}
- if (entry.immediateAndNotDelivered())
- {
- dequeue(storeContext, entry);
- entry.dispose(storeContext);
- }
- else if (!(entry.isAcquired() || entry.isDeleted()))
+
+ if (!(entry.isAcquired() || entry.isDeleted()))
{
checkSubscriptionsNotAheadOfDelivery(entry);
deliverAsync();
}
- _managedObject.checkForNotification(entry.getMessage());
+ if(_managedObject != null)
+ {
+ _managedObject.checkForNotification(entry.getMessage());
+ }
return entry;
}
@@ -474,17 +557,15 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
{
if (!sub.wouldSuspend(entry))
{
- if (!sub.isBrowser() && !entry.acquire(sub))
+ if (sub.acquires() && !entry.acquire(sub))
{
// restore credit here that would have been taken away by wouldSuspend since we didn't manage
// to acquire the entry for this subscription
- sub.restoreCredit(entry);
+ sub.onDequeue(entry);
}
else
{
-
deliverMessage(sub, entry);
-
}
}
}
@@ -501,7 +582,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
// Simple Queues don't :-)
}
- private void incrementQueueSize(final AMQMessage message)
+ private void incrementQueueSize(final ServerMessage message)
{
getAtomicQueueSize().addAndGet(message.getSize());
}
@@ -515,76 +596,48 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
throws AMQException
{
_deliveredMessages.incrementAndGet();
- if (_logger.isDebugEnabled())
- {
- _logger.debug(sub + ": deliverMessage: " + entry.debugIdentity());
- }
sub.send(entry);
+
+ setLastSeenEntry(sub,entry);
}
- private boolean subscriptionReadyAndHasInterest(final Subscription sub, final QueueEntry entry)
+ private boolean subscriptionReadyAndHasInterest(final Subscription sub, final QueueEntry entry) throws AMQException
{
+ return sub.hasInterest(entry) && (getNextAvailableEntry(sub) == entry);
+ }
- // We need to move this subscription on, past entries which are already acquired, or deleted or ones it has no
- // interest in.
- QueueEntry node = sub.getLastSeenEntry();
- while (node != null && (node.isAcquired() || node.isDeleted() || !sub.hasInterest(node)))
- {
-
- QueueEntry newNode = _entries.next(node);
- if (newNode != null)
- {
- sub.setLastSeenEntry(node, newNode);
- node = sub.getLastSeenEntry();
- }
- else
- {
- node = null;
- break;
- }
- }
+ private void setLastSeenEntry(final Subscription sub, final QueueEntry entry)
+ {
+ QueueContext subContext = (QueueContext) sub.getQueueContext();
+ QueueEntry releasedEntry = subContext._releasedEntry;
- if (node == entry)
+ QueueContext._lastSeenUpdater.set(subContext, entry);
+ if(releasedEntry == entry)
{
- // If the first entry that subscription can process is the one we are trying to deliver to it, then we are
- // good
- return true;
- }
- else
- {
- // Otherwise we should try to update the subscription's last seen entry to the entry we got to, providing
- // no-one else has updated it to something furhter on in the list
- //TODO - check
- //updateLastSeenEntry(sub, entry);
- return false;
+ QueueContext._releasedUpdater.compareAndSet(subContext, releasedEntry, null);
}
-
}
- private void updateLastSeenEntry(final Subscription sub, final QueueEntry entry)
+ private void updateSubRequeueEntry(final Subscription sub, final QueueEntry entry)
{
- QueueEntry node = sub.getLastSeenEntry();
- if (node != null && entry.compareTo(node) < 0 && sub.hasInterest(entry))
+ QueueContext subContext = (QueueContext) sub.getQueueContext();
+ if(subContext != null)
{
- do
+ QueueEntry oldEntry;
+
+ while((oldEntry = subContext._releasedEntry) == null || oldEntry.compareTo(entry) > 0)
{
- if (sub.setLastSeenEntry(node, entry))
- {
- return;
- }
- else
+ if(QueueContext._releasedUpdater.compareAndSet(subContext, oldEntry, entry))
{
- node = sub.getLastSeenEntry();
+ break;
}
}
- while (node != null && entry.compareTo(node) < 0);
}
-
}
- public void requeue(StoreContext storeContext, QueueEntry entry) throws AMQException
+ public void requeue(QueueEntry entry)
{
SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
@@ -594,9 +647,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
Subscription sub = subscriberIter.getNode().getSubscription();
// we don't make browsers send the same stuff twice
- if (!sub.isBrowser())
+ if (sub.seesRequeues())
{
- updateLastSeenEntry(sub, entry);
+ updateSubRequeueEntry(sub, entry);
}
}
@@ -604,36 +657,31 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
- public void dequeue(StoreContext storeContext, QueueEntry entry) throws FailedDequeueException
+ public void requeue(QueueEntryImpl entry, Subscription subscription)
{
- decrementQueueCount();
- decrementQueueSize(entry);
- if (entry.acquiredBySubscription())
+ 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())
{
- _deliveredMessages.decrementAndGet();
- }
+ Subscription sub = subscriberIter.getNode().getSubscription();
- try
- {
- AMQMessage msg = entry.getMessage();
- if (msg.isPersistent())
+ // we don't make browsers send the same stuff twice
+ if (sub.seesRequeues() && (!sub.acquires() && sub == subscription))
{
- _virtualHost.getMessageStore().dequeueMessage(storeContext, this, msg.getMessageId());
+ updateSubRequeueEntry(sub, entry);
}
- //entry.dispose(storeContext);
-
- }
- catch (MessageCleanupException e)
- {
- // Message was dequeued, but could not then be deleted
- // though it is no longer referenced. This should be very
- // rare and can be detected and cleaned up on recovery or
- // done through some form of manual intervention.
- _logger.error(e, e);
}
- catch (AMQException e)
+
+ deliverAsync();
+ }
+
+ public void dequeue(QueueEntry entry)
+ {
+ decrementQueueCount();
+ decrementQueueSize(entry);
+ if (entry.acquiredBySubscription())
{
- throw new FailedDequeueException(_name.toString(), e);
+ _deliveredMessages.decrementAndGet();
}
checkCapacity();
@@ -811,7 +859,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
public boolean accept(QueueEntry entry)
{
- final long messageId = entry.getMessage().getMessageId();
+ final long messageId = entry.getMessage().getMessageNumber();
return messageId >= fromMessageId && messageId <= toMessageId;
}
@@ -830,7 +878,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
public boolean accept(QueueEntry entry)
{
- _complete = entry.getMessage().getMessageId() == messageId;
+ _complete = entry.getMessage().getMessageNumber() == messageId;
return _complete;
}
@@ -872,7 +920,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
{
private long position = 0;
-
+
public boolean accept(QueueEntry entry)
{
position++;
@@ -884,25 +932,25 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
return position >= toPosition;
}
});
-
+
return entries;
}
public void moveMessagesToAnotherQueue(final long fromMessageId,
final long toMessageId,
String queueName,
- StoreContext storeContext)
+ ServerTransaction txn)
{
- AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
- MessageStore store = getVirtualHost().getMessageStore();
+ final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
+
List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
{
public boolean accept(QueueEntry entry)
{
- final long messageId = entry.getMessage().getMessageId();
+ final long messageId = entry.getMessage().getMessageNumber();
return (messageId >= fromMessageId)
&& (messageId <= toMessageId)
&& entry.acquire();
@@ -914,61 +962,48 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
});
- try
+
+
+ // Move the messages in on the message store.
+ for (final QueueEntry entry : entries)
{
- store.beginTran(storeContext);
+ final ServerMessage message = entry.getMessage();
+ txn.enqueue(toQueue, message,
+ new ServerTransaction.Action()
+ {
- // Move the messages in on the message store.
- for (QueueEntry entry : entries)
- {
- AMQMessage message = entry.getMessage();
+ public void postCommit()
+ {
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
- if (message.isPersistent() && toQueue.isDurable())
- {
- store.enqueueMessage(storeContext, toQueue, message.getMessageId());
- }
- // dequeue does not decrement the refence count
- entry.dequeue(storeContext);
- }
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+ txn.dequeue(this, message,
+ new ServerTransaction.Action()
+ {
- // Commit and flush the move transcations.
- try
- {
- store.commitTran(storeContext);
- }
- catch (AMQException e)
- {
- throw new RuntimeException("Failed to commit transaction whilst moving messages on message store.", e);
- }
- }
- catch (AMQException e)
- {
- try
- {
- store.abortTran(storeContext);
- }
- catch (AMQException rollbackEx)
- {
- _logger.error("Failed to rollback transaction when error occured moving messages", rollbackEx);
- }
- throw new RuntimeException(e);
- }
+ public void postCommit()
+ {
+ entry.discard();
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
- try
- {
- for (QueueEntry entry : entries)
- {
- toQueue.enqueue(storeContext, entry.getMessage());
- entry.delete();
- }
- }
- catch (MessageCleanupException e)
- {
- throw new RuntimeException(e);
- }
- catch (AMQException e)
- {
- throw new RuntimeException(e);
}
}
@@ -976,27 +1011,18 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
public void copyMessagesToAnotherQueue(final long fromMessageId,
final long toMessageId,
String queueName,
- final StoreContext storeContext)
+ final ServerTransaction txn)
{
- AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
- MessageStore store = getVirtualHost().getMessageStore();
+ final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
{
public boolean accept(QueueEntry entry)
{
- final long messageId = entry.getMessage().getMessageId();
- if ((messageId >= fromMessageId)
- && (messageId <= toMessageId))
- {
- if (!entry.isDeleted())
- {
- return entry.getMessage().incrementReference();
- }
- }
-
- return false;
+ final long messageId = entry.getMessage().getMessageNumber();
+ return ((messageId >= fromMessageId)
+ && (messageId <= toMessageId));
}
public boolean filterComplete()
@@ -1005,98 +1031,69 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
});
- try
+
+ // Move the messages in on the message store.
+ for (QueueEntry entry : entries)
{
- store.beginTran(storeContext);
+ final ServerMessage message = entry.getMessage();
- // Move the messages in on the message store.
- for (QueueEntry entry : entries)
+ if (message.isPersistent() && toQueue.isDurable())
{
- AMQMessage message = entry.getMessage();
- if (message.isReferenced() && message.isPersistent() && toQueue.isDurable())
- {
- store.enqueueMessage(storeContext, toQueue, message.getMessageId());
- }
- }
+ txn.enqueue(toQueue, message, new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
- // Commit and flush the move transcations.
- try
- {
- store.commitTran(storeContext);
- }
- catch (AMQException e)
- {
- throw new RuntimeException("Failed to commit transaction whilst moving messages on message store.", e);
- }
- }
- catch (AMQException e)
- {
- try
- {
- store.abortTran(storeContext);
- }
- catch (AMQException rollbackEx)
- {
- _logger.error("Failed to rollback transaction when error occured moving messages", rollbackEx);
- }
- throw new RuntimeException(e);
- }
+ public void onRollback()
+ {
+
+ }
+ });
- try
- {
- for (QueueEntry entry : entries)
- {
- if (entry.getMessage().isReferenced())
- {
- toQueue.enqueue(storeContext, entry.getMessage());
- }
}
}
- catch (MessageCleanupException e)
- {
- throw new RuntimeException(e);
- }
- catch (AMQException e)
- {
- throw new RuntimeException(e);
- }
}
- public void removeMessagesFromQueue(long fromMessageId, long toMessageId, StoreContext storeContext)
+ public void removeMessagesFromQueue(long fromMessageId, long toMessageId)
{
- try
+ QueueEntryIterator queueListIterator = _entries.iterator();
+
+ while (queueListIterator.advance())
{
- QueueEntryIterator queueListIterator = _entries.iterator();
+ QueueEntry node = queueListIterator.getNode();
- while (queueListIterator.advance())
+ final ServerMessage message = node.getMessage();
+ if(message != null)
{
- QueueEntry node = queueListIterator.getNode();
-
- final long messageId = node.getMessage().getMessageId();
+ final long messageId = message.getMessageNumber();
if ((messageId >= fromMessageId)
&& (messageId <= toMessageId)
&& !node.isDeleted()
&& node.acquire())
{
- node.discard(storeContext);
+ dequeueEntry(node);
}
-
}
}
- catch (AMQException e)
- {
- throw new RuntimeException(e);
- }
}
// ------ Management functions
- public void deleteMessageFromTop(StoreContext storeContext) throws AMQException
+ public void deleteMessageFromTop()
{
QueueEntryIterator queueListIterator = _entries.iterator();
boolean noDeletes = true;
@@ -1106,33 +1103,62 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
QueueEntry node = queueListIterator.getNode();
if (!node.isDeleted() && node.acquire())
{
- node.discard(storeContext);
+ dequeueEntry(node);
noDeletes = false;
}
}
}
- public long clearQueue(StoreContext storeContext) throws AMQException
+ public long clearQueue()
{
QueueEntryIterator queueListIterator = _entries.iterator();
long count = 0;
+ ServerTransaction txn = new LocalTransaction(getVirtualHost().getTransactionLog());
+
while (queueListIterator.advance())
{
QueueEntry node = queueListIterator.getNode();
if (!node.isDeleted() && node.acquire())
{
- node.discard(storeContext);
+ dequeueEntry(node, txn);
count++;
}
}
+
+ txn.commit();
+
return count;
}
+ private void dequeueEntry(final QueueEntry node)
+ {
+ ServerTransaction txn = new AutoCommitTransaction(getVirtualHost().getTransactionLog());
+ dequeueEntry(node, txn);
+ }
+
+ private void dequeueEntry(final QueueEntry node, ServerTransaction txn)
+ {
+ txn.dequeue(this, node.getMessage(),
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ node.discard();
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ }
+
public void addQueueDeleteTask(final Task task)
{
_deleteTaskList.add(task);
@@ -1157,7 +1183,111 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
_bindings.deregister();
_virtualHost.getQueueRegistry().unregisterQueue(_name);
- _managedObject.unregister();
+ List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
+ {
+
+ public boolean accept(QueueEntry entry)
+ {
+ return entry.acquire();
+ }
+
+ public boolean filterComplete()
+ {
+ return false;
+ }
+ });
+
+ ServerTransaction txn = new LocalTransaction(getVirtualHost().getTransactionLog());
+
+ if(_alternateExchange != null)
+ {
+
+ InboundMessageAdapter adapter = new InboundMessageAdapter();
+ for(final QueueEntry entry : entries)
+ {
+ adapter.setEntry(entry);
+ final List<AMQQueue> rerouteQueues = _alternateExchange.route(adapter);
+ final ServerMessage message = entry.getMessage();
+ if(rerouteQueues != null & rerouteQueues.size() != 0)
+ {
+ txn.enqueue(rerouteQueues, entry.getMessage(),
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ try
+ {
+ for(AMQQueue queue : rerouteQueues)
+ {
+ QueueEntry entry = queue.enqueue(message);
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ txn.dequeue(this, entry.getMessage(),
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ entry.discard();
+ }
+
+ public void onRollback()
+ {
+ }
+ });
+ }
+
+ }
+
+ _alternateExchange.removeReference(this);
+ }
+ else
+ {
+ // TODO log discard
+
+ for(final QueueEntry entry : entries)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ txn.dequeue(this, message,
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ entry.discard();
+ }
+
+ public void onRollback()
+ {
+ }
+ });
+ }
+ }
+ }
+
+ txn.commit();
+
+
+ if(_managedObject!=null)
+ {
+ _managedObject.unregister();
+ }
+
for (Task task : _deleteTaskList)
{
task.doTask(this);
@@ -1165,7 +1295,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
_deleteTaskList.clear();
stop();
-
+
//Log Queue Deletion
CurrentActor.get().message(_logSubject, QueueMessages.QUE_1002());
@@ -1249,7 +1379,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
public void deliverAsync(Subscription sub)
{
- _asyncDelivery.execute(new SubFlushRunner(sub));
+ SubFlushRunner flusher = (SubFlushRunner) sub.get(SUB_FLUSH_RUNNER);
+ if(flusher == null)
+ {
+ flusher = new SubFlushRunner(sub);
+ sub.set(SUB_FLUSH_RUNNER, flusher);
+ }
+ _asyncDelivery.execute(flusher);
}
@@ -1298,66 +1434,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
}
- private class SubFlushRunner implements ReadWriteRunnable
- {
- private final Subscription _sub;
-
- public SubFlushRunner(Subscription sub)
- {
- _sub = sub;
- }
-
- public void run()
- {
-
- String originalName = Thread.currentThread().getName();
- try{
- Thread.currentThread().setName("SubFlushRunner-"+_sub);
-
- boolean complete = false;
- try
- {
- CurrentActor.set(_sub.getLogActor());
- complete = flushSubscription(_sub, new Long(MAX_ASYNC_DELIVERIES));
-
- }
- catch (AMQException e)
- {
- _logger.error(e);
- }
- finally
- {
- CurrentActor.remove();
- }
- if (!complete && !_sub.isSuspended())
- {
- _asyncDelivery.execute(this);
- }
- }
- finally
- {
- Thread.currentThread().setName(originalName);
- }
-
- }
-
- public boolean isRead()
- {
- return false;
- }
-
- public boolean isWrite()
- {
- return true;
- }
- }
-
public void flushSubscription(Subscription sub) throws AMQException
{
flushSubscription(sub, Long.MAX_VALUE);
}
- public boolean flushSubscription(Subscription sub, Long iterations) throws AMQException
+ public boolean flushSubscription(Subscription sub, long iterations) throws AMQException
{
boolean atTail = false;
@@ -1371,8 +1453,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
{
unregisterSubscription(sub);
- ProtocolOutputConverter converter = sub.getChannel().getProtocolSession().getProtocolOutputConverter();
- converter.confirmConsumerAutoClose(sub.getChannel().getChannelId(), sub.getConsumerTag());
+ sub.confirmAutoClose();
+
}
else if (!atTail)
{
@@ -1408,41 +1490,26 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
private boolean attemptDelivery(Subscription sub) throws AMQException
{
boolean atTail = false;
- boolean advanced = false;
+
boolean subActive = sub.isActive() && !sub.isSuspended();
if (subActive)
{
- QueueEntry node = moveSubscriptionToNextNode(sub);
- if (_logger.isDebugEnabled())
- {
- _logger.debug(sub + ": attempting Delivery: " + node.debugIdentity());
- }
- if (!(node.isAcquired() || node.isDeleted()))
+
+ QueueEntry node = getNextAvailableEntry(sub);
+
+ if (node != null && !(node.isAcquired() || node.isDeleted()))
{
if (sub.hasInterest(node))
{
if (!sub.wouldSuspend(node))
{
- if (!sub.isBrowser() && !node.acquire(sub))
+ if (sub.acquires() && !node.acquire(sub))
{
- sub.restoreCredit(node);
+ sub.onDequeue(node);
}
else
{
deliverMessage(sub, node);
-
- if (sub.isBrowser())
- {
- QueueEntry newNode = _entries.next(node);
-
- if (newNode != null)
- {
- advanced = true;
- sub.setLastSeenEntry(node, newNode);
- node = sub.getLastSeenEntry();
- }
-
- }
}
}
@@ -1450,29 +1517,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
{
//QPID-1187 - Treat the subscription as suspended for this message
// and wait for the message to be removed to continue delivery.
-
- // 2009-09-30 : MR : setting subActive = false only causes, this
- // particular delivery attempt to end. This is called from
- // flushSubscription and processQueue both of which attempt
- // delivery a number of times. Won't a bytes limited
- // subscriber with not enough credit for the next message
- // create a lot of new QELs? How about a browser that calls
- // this method LONG.MAX_LONG times!
subActive = false;
- node.addStateChangeListener(new QueueEntryListener(sub, node));
- }
- }
- else
- {
- // this subscription is not interested in this node so we can skip over it
- QueueEntry newNode = _entries.next(node);
- if (newNode != null)
- {
- sub.setLastSeenEntry(node, newNode);
+ node.addStateChangeListener(new QueueEntryListener(sub));
}
}
+
}
- atTail = (_entries.next(node) == null) && !advanced;
+ atTail = (node == null) || (_entries.next(node) == null);
}
return atTail || !subActive;
}
@@ -1484,46 +1535,58 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
{
SubscriptionList.SubscriptionNode subNode = subscriberIter.getNode();
Subscription sub = subNode.getSubscription();
- moveSubscriptionToNextNode(sub);
+ if(sub.acquires())
+ {
+ getNextAvailableEntry(sub);
+ }
+ else
+ {
+ // TODO
+ }
}
}
- private QueueEntry moveSubscriptionToNextNode(final Subscription sub)
+ private QueueEntry getNextAvailableEntry(final Subscription sub)
throws AMQException
{
- QueueEntry node = sub.getLastSeenEntry();
-
- while (node != null && (node.isAcquired() || node.isDeleted() || node.expired()))
+ QueueContext context = (QueueContext) sub.getQueueContext();
+ if(context != null)
{
- if (!node.isAcquired() && !node.isDeleted() && node.expired())
+ QueueEntry lastSeen = context._lastSeenEntry;
+ QueueEntry releasedNode = context._releasedEntry;
+
+ QueueEntry node = (releasedNode != null && lastSeen.compareTo(releasedNode)>=0) ? releasedNode : _entries.next(lastSeen);
+
+ boolean expired = false;
+ while (node != null && (node.isAcquired() || node.isDeleted() || (expired = node.expired()) || !sub.hasInterest(node)))
{
- if (node.acquire())
+ if (expired)
{
- final StoreContext reapingStoreContext = new StoreContext();
- node.discard(reapingStoreContext);
+ expired = false;
+ if (node.acquire())
+ {
+ dequeueEntry(node);
+ }
}
- }
- QueueEntry newNode = _entries.next(node);
- if (newNode != null)
- {
- sub.setLastSeenEntry(node, newNode);
- node = sub.getLastSeenEntry();
- }
- else
- {
- break;
- }
- }
+ if(QueueContext._lastSeenUpdater.compareAndSet(context, lastSeen, node))
+ {
+ QueueContext._releasedUpdater.compareAndSet(context, releasedNode, null);
+ }
- if (_logger.isDebugEnabled())
+ lastSeen = context._lastSeenEntry;
+ releasedNode = context._releasedEntry;
+ node = (releasedNode != null && lastSeen.compareTo(releasedNode)>0) ? releasedNode : _entries.next(lastSeen);
+ }
+ return node;
+ }
+ else
{
- _logger.debug(sub + ": nextNode: " + (node == null ? "null" : node.debugIdentity()));
+ return null;
}
-
- return node;
}
+
private void processQueue(Runnable runner) throws AMQException
{
long stateChangeCount;
@@ -1563,7 +1626,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
sub.getSendLock();
try
{
- done = attemptDelivery(sub);
+ if (sub != null)
+ {
+ done = attemptDelivery(sub);
+ }
if (done)
{
if (extraLoops == 0)
@@ -1573,8 +1639,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
{
unregisterSubscription(sub);
- ProtocolOutputConverter converter = sub.getChannel().getProtocolSession().getProtocolOutputConverter();
- converter.confirmConsumerAutoClose(sub.getChannel().getChannelId(), sub.getConsumerTag());
+ sub.confirmAutoClose();
}
}
else
@@ -1611,8 +1676,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
public void checkMessageStatus() throws AMQException
{
- final StoreContext storeContext = new StoreContext();
-
QueueEntryIterator queueListIterator = _entries.iterator();
while (queueListIterator.advance())
@@ -1620,11 +1683,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
QueueEntry node = queueListIterator.getNode();
if (!node.isDeleted() && node.expired() && node.acquire())
{
- node.discard(storeContext);
+ dequeueEntry(node);
}
else
{
- _managedObject.checkForNotification(node.getMessage());
+ if(_managedObject!=null)
+ {
+ _managedObject.checkForNotification(node.getMessage());
+ }
}
}
@@ -1748,23 +1814,22 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
private final class QueueEntryListener implements QueueEntry.StateChangeListener
{
- private final QueueEntry _entry;
+
private final Subscription _sub;
- public QueueEntryListener(final Subscription sub, final QueueEntry entry)
+ public QueueEntryListener(final Subscription sub)
{
- _entry = entry;
_sub = sub;
}
public boolean equals(Object o)
{
- return _entry == ((QueueEntryListener) o)._entry && _sub == ((QueueEntryListener) o)._sub;
+ return _sub == ((QueueEntryListener) o)._sub;
}
public int hashCode()
{
- return System.identityHashCode(_entry) ^ System.identityHashCode(_sub);
+ return System.identityHashCode(_sub);
}
public void stateChanged(QueueEntry entry, QueueEntry.State oldSate, QueueEntry.State newState)
@@ -1791,11 +1856,22 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
for (int i = 0; i < num && !it.atTail(); i++)
{
it.advance();
- ids.add(it.getNode().getMessage().getMessageId());
+ ids.add(it.getNode().getMessage().getMessageNumber());
}
return ids;
}
+ public Object getExclusiveOwner()
+ {
+ return _exclusiveOwner;
+ }
+
+ public void setExclusiveOwner(Object exclusiveOwner)
+ {
+ _exclusiveOwner = exclusiveOwner;
+ }
+
+
public void configure(QueueConfiguration config)
{
if (config != null)
@@ -1809,4 +1885,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
_flowResumeCapacity = config.getFlowResumeCapacity();
}
}
+
+ public String getResourceName()
+ {
+ return _resourceName;
+ }
+
+
+ @Override
+ public String toString()
+ {
+ return String.valueOf(getName());
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
index a46c5ae2e8..d27a5ed234 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
@@ -1,6 +1,10 @@
package org.apache.qpid.server.queue;
+import org.apache.qpid.server.message.InboundMessage;
+import org.apache.qpid.server.message.ServerMessage;
+
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.util.concurrent.atomic.AtomicLong;
/*
*
@@ -24,6 +28,7 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
*/
public class SimpleQueueEntryList implements QueueEntryList
{
+
private final QueueEntryImpl _head;
private volatile QueueEntryImpl _tail;
@@ -40,9 +45,7 @@ public class SimpleQueueEntryList implements QueueEntryList
_nextUpdater =
AtomicReferenceFieldUpdater.newUpdater
(QueueEntryImpl.class, QueueEntryImpl.class, "_next");
-
-
-
+ private AtomicLong _deletes = new AtomicLong(0L);
public SimpleQueueEntryList(AMQQueue queue)
@@ -52,21 +55,77 @@ public class SimpleQueueEntryList implements QueueEntryList
_tail = _head;
}
+
+
void advanceHead()
{
+ _deletes.incrementAndGet();
QueueEntryImpl head = _head.nextNode();
+ boolean deleted = head.isDeleted();
while(head._next != null && head.isDeleted())
{
+ deleted = true;
final QueueEntryImpl newhead = head.nextNode();
if(newhead != null)
{
- _nextUpdater.compareAndSet(_head,head, newhead);
+ if(_nextUpdater.compareAndSet(_head,head, newhead))
+ {
+ _deletes.decrementAndGet();
+ }
}
head = _head.nextNode();
}
+
+ if(!deleted)
+ {
+ deleted = true;
+ }
+
+ if(_deletes.get() > 1000L)
+ {
+ _deletes.set(0L);
+ scavenge();
+ }
}
+ void scavenge()
+ {
+ QueueEntryImpl root = _head;
+ QueueEntryImpl next = root.nextNode();
+
+ do
+ {
+
+
+ while(next._next != null && next.isDeleted())
+ {
+
+ final QueueEntryImpl newhead = next.nextNode();
+ if(newhead != null)
+ {
+ _nextUpdater.compareAndSet(root,next, newhead);
+ }
+ next = root.nextNode();
+ }
+ if(next._next != null)
+ {
+ if(!next.isDeleted())
+ {
+ root = next;
+ next = root.nextNode();
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ } while (next != null && next._next != null);
+
+ }
+
+
public AMQQueue getQueue()
{
@@ -74,7 +133,7 @@ public class SimpleQueueEntryList implements QueueEntryList
}
- public QueueEntry add(AMQMessage message)
+ public QueueEntry add(ServerMessage message)
{
QueueEntryImpl node = new QueueEntryImpl(this, message);
for (;;)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java
new file mode 100755
index 0000000000..547365f647
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java
@@ -0,0 +1,68 @@
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.pool.ReadWriteRunnable;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.AMQException;
+import org.apache.log4j.Logger;
+
+
+class SubFlushRunner implements ReadWriteRunnable
+{
+ private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class);
+
+
+ private final Subscription _sub;
+ private final String _name;
+ private static final long ITERATIONS = SimpleAMQQueue.MAX_ASYNC_DELIVERIES;
+
+ public SubFlushRunner(Subscription sub)
+ {
+ _sub = sub;
+ _name = "SubFlushRunner-"+_sub;
+ }
+
+ public void run()
+ {
+
+
+ Thread.currentThread().setName(_name);
+
+ boolean complete = false;
+ try
+ {
+ CurrentActor.set(_sub.getLogActor());
+ complete = getQueue().flushSubscription(_sub, ITERATIONS);
+
+ }
+ catch (AMQException e)
+ {
+ _logger.error(e);
+ }
+ finally
+ {
+ CurrentActor.remove();
+ }
+ if (!complete && !_sub.isSuspended())
+ {
+ getQueue().execute(this);
+ }
+
+
+ }
+
+ private SimpleAMQQueue getQueue()
+ {
+ return (SimpleAMQQueue) _sub.getQueue();
+ }
+
+ public boolean isRead()
+ {
+ return false;
+ }
+
+ public boolean isWrite()
+ {
+ return true;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/TransientMessageData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/TransientMessageData.java
deleted file mode 100644
index b09283b11f..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/TransientMessageData.java
+++ /dev/null
@@ -1,127 +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.queue;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Collections;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
-
-/**
- * Contains data that is only used in AMQMessage transiently, e.g. while the content
- * body fragments are arriving.
- *
- * Having this data stored in a separate class means that the AMQMessage class avoids
- * the small overhead of numerous guaranteed-null references.
- *
- * @author Apache Software Foundation
- */
-public class TransientMessageData
-{
- /**
- * Stored temporarily until the header has been received at which point it is used when
- * constructing the handle
- */
- private MessagePublishInfo _messagePublishInfo;
-
- /**
- * Also stored temporarily.
- */
- private ContentHeaderBody _contentHeaderBody;
-
- /**
- * Keeps a track of how many bytes we have received in body frames
- */
- private long _bodyLengthReceived = 0;
-
- /**
- * This is stored during routing, to know the queues to which this message should immediately be
- * delivered. It is <b>cleared after delivery has been attempted</b>. Any persistent record of destinations is done
- * by the message handle.
- */
- private List<AMQQueue> _destinationQueues;
-
- public MessagePublishInfo getMessagePublishInfo()
- {
- return _messagePublishInfo;
- }
-
- public void setMessagePublishInfo(MessagePublishInfo messagePublishInfo)
- {
- _messagePublishInfo = messagePublishInfo;
- }
-
- public List<AMQQueue> getDestinationQueues()
- {
- return _destinationQueues == null ? (List<AMQQueue>) Collections.EMPTY_LIST : _destinationQueues;
- }
-
- public void setDestinationQueues(List<AMQQueue> destinationQueues)
- {
- _destinationQueues = destinationQueues;
- }
-
- public ContentHeaderBody getContentHeaderBody()
- {
- return _contentHeaderBody;
- }
-
- public void setContentHeaderBody(ContentHeaderBody contentHeaderBody)
- {
- _contentHeaderBody = contentHeaderBody;
- }
-
- public long getBodyLengthReceived()
- {
- return _bodyLengthReceived;
- }
-
- public void addBodyLength(int value)
- {
- _bodyLengthReceived += value;
- }
-
- public boolean isAllContentReceived() throws AMQException
- {
- return _bodyLengthReceived == _contentHeaderBody.bodySize;
- }
-
- public void addDestinationQueue(AMQQueue queue)
- {
- if(_destinationQueues == null)
- {
- _destinationQueues = new ArrayList<AMQQueue>();
- }
- _destinationQueues.add(queue);
- }
-
- public boolean isPersistent()
- {
- return _contentHeaderBody.properties instanceof BasicContentHeaderProperties &&
- ((BasicContentHeaderProperties) _contentHeaderBody.properties).getDeliveryMode() ==
- BasicContentHeaderProperties.PERSISTENT;
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java
deleted file mode 100644
index 3ed8b0e55c..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java
+++ /dev/null
@@ -1,219 +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.queue;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
-
-/**
- * @author Robert Greig (robert.j.greig@jpmorgan.com)
- */
-public class WeakReferenceMessageHandle implements AMQMessageHandle
-{
- private WeakReference<ContentHeaderBody> _contentHeaderBody;
-
- private WeakReference<MessagePublishInfo> _messagePublishInfo;
-
- private List<WeakReference<ContentChunk>> _contentBodies;
-
- private boolean _redelivered;
-
- private final MessageStore _messageStore;
-
- private final Long _messageId;
- private long _arrivalTime;
-
- public WeakReferenceMessageHandle(final Long messageId, MessageStore messageStore)
- {
- _messageId = messageId;
- _messageStore = messageStore;
- }
-
- public ContentHeaderBody getContentHeaderBody(StoreContext context) throws AMQException
- {
- ContentHeaderBody chb = (_contentHeaderBody != null ? _contentHeaderBody.get() : null);
- if (chb == null)
- {
- MessageMetaData mmd = loadMessageMetaData(context);
- chb = mmd.getContentHeaderBody();
- }
- return chb;
- }
-
- public Long getMessageId()
- {
- return _messageId;
- }
-
- private MessageMetaData loadMessageMetaData(StoreContext context)
- throws AMQException
- {
- MessageMetaData mmd = _messageStore.getMessageMetaData(context, _messageId);
- populateFromMessageMetaData(mmd);
- return mmd;
- }
-
- private void populateFromMessageMetaData(MessageMetaData mmd)
- {
- _arrivalTime = mmd.getArrivalTime();
- _contentHeaderBody = new WeakReference<ContentHeaderBody>(mmd.getContentHeaderBody());
- _messagePublishInfo = new WeakReference<MessagePublishInfo>(mmd.getMessagePublishInfo());
- }
-
- public int getBodyCount(StoreContext context) throws AMQException
- {
- if (_contentBodies == null)
- {
- MessageMetaData mmd = _messageStore.getMessageMetaData(context, _messageId);
- int chunkCount = mmd.getContentChunkCount();
- _contentBodies = new ArrayList<WeakReference<ContentChunk>>(chunkCount);
- for (int i = 0; i < chunkCount; i++)
- {
- _contentBodies.add(new WeakReference<ContentChunk>(null));
- }
- }
- return _contentBodies.size();
- }
-
- public long getBodySize(StoreContext context) throws AMQException
- {
- return getContentHeaderBody(context).bodySize;
- }
-
- public ContentChunk getContentChunk(StoreContext context, int index) throws AMQException, IllegalArgumentException
- {
- if (index > _contentBodies.size() - 1)
- {
- throw new IllegalArgumentException("Index " + index + " out of valid range 0 to " +
- (_contentBodies.size() - 1));
- }
- WeakReference<ContentChunk> wr = _contentBodies.get(index);
- ContentChunk cb = wr.get();
- if (cb == null)
- {
- cb = _messageStore.getContentBodyChunk(context, _messageId, index);
- _contentBodies.set(index, new WeakReference<ContentChunk>(cb));
- }
- return cb;
- }
-
- /**
- * Content bodies are set <i>before</i> the publish and header frames
- *
- * @param storeContext
- * @param contentChunk
- * @param isLastContentBody
- * @throws AMQException
- */
- public void addContentBodyFrame(StoreContext storeContext, ContentChunk contentChunk, boolean isLastContentBody) throws AMQException
- {
- if (_contentBodies == null && isLastContentBody)
- {
- _contentBodies = new ArrayList<WeakReference<ContentChunk>>(1);
- }
- else
- {
- if (_contentBodies == null)
- {
- _contentBodies = new LinkedList<WeakReference<ContentChunk>>();
- }
- }
- _contentBodies.add(new WeakReference<ContentChunk>(contentChunk));
- _messageStore.storeContentBodyChunk(storeContext, _messageId, _contentBodies.size() - 1,
- contentChunk, isLastContentBody);
- }
-
- public MessagePublishInfo getMessagePublishInfo(StoreContext context) throws AMQException
- {
- MessagePublishInfo bpb = (_messagePublishInfo != null ? _messagePublishInfo.get() : null);
- if (bpb == null)
- {
- MessageMetaData mmd = loadMessageMetaData(context);
-
- bpb = mmd.getMessagePublishInfo();
- }
- return bpb;
- }
-
- public boolean isRedelivered()
- {
- return _redelivered;
- }
-
- public void setRedelivered(boolean redelivered)
- {
- _redelivered = redelivered;
- }
-
- public boolean isPersistent()
- {
- return true;
- }
-
- /**
- * This is called when all the content has been received.
- *
- * @param publishBody
- * @param contentHeaderBody
- * @throws AMQException
- */
- public void setPublishAndContentHeaderBody(StoreContext storeContext, MessagePublishInfo publishBody,
- ContentHeaderBody contentHeaderBody)
- throws AMQException
- {
- // if there are no content bodies the list will be null so we must
- // create en empty list here
- if (contentHeaderBody.bodySize == 0)
- {
- _contentBodies = new LinkedList<WeakReference<ContentChunk>>();
- }
-
- final long arrivalTime = System.currentTimeMillis();
-
-
- MessageMetaData mmd = new MessageMetaData(publishBody, contentHeaderBody, _contentBodies.size(), arrivalTime);
-
- _messageStore.storeMessageMetaData(storeContext, _messageId, mmd);
-
-
- populateFromMessageMetaData(mmd);
- }
-
- public void removeMessage(StoreContext storeContext) throws AMQException
- {
- _messageStore.removeMessage(storeContext, _messageId);
- }
-
- public long getArrivalTime()
- {
- return _arrivalTime;
- }
-
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
index 831f928832..8e8581b66f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
@@ -35,8 +35,8 @@ import org.apache.qpid.server.plugins.PluginManager;
import org.apache.qpid.server.security.access.ACLManager;
import org.apache.qpid.server.security.auth.database.ConfigurationFilePrincipalDatabaseManager;
import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
-import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import java.io.File;
@@ -51,15 +51,15 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
public void initialise(int instanceID) throws Exception
{
- _rootMessageLogger = new RootMessageLoggerImpl(_configuration,
+ _rootMessageLogger = new RootMessageLoggerImpl(_configuration,
new Log4jMessageLogger());
-
+
_registryName = String.valueOf(instanceID);
// Set the Actor for current log messages
CurrentActor.set(new BrokerActor(_registryName, _rootMessageLogger));
- CurrentActor.get().message(BrokerMessages.BRK_1001(QpidProperties.getReleaseVersion(),QpidProperties.getBuildVersion()));
+ CurrentActor.get().message(BrokerMessages.BRK_1001(QpidProperties.getReleaseVersion(),QpidProperties.getBuildVersion()));
initialiseManagedObjectRegistry();
@@ -68,7 +68,7 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
_pluginManager = new PluginManager(_configuration.getPluginDirectory());
_accessManager = new ACLManager(_configuration.getSecurityConfiguration(), _pluginManager);
-
+
_databaseManager = new ConfigurationFilePrincipalDatabaseManager(_configuration);
_authenticationManager = new PrincipalDatabaseAuthenticationManager(null, null);
@@ -99,10 +99,10 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
}
private void initialiseVirtualHosts() throws Exception
- {
+ {
for (String name : _configuration.getVirtualHosts())
{
- _virtualHostRegistry.registerVirtualHost(new VirtualHost(_configuration.getVirtualHostConfig(name)));
+ _virtualHostRegistry.registerVirtualHost(new VirtualHostImpl(_configuration.getVirtualHostConfig(name)));
}
getVirtualHostRegistry().setDefaultVirtualHostName(_configuration.getDefaultVirtualHost());
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java
new file mode 100755
index 0000000000..7e93623cab
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.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.security;
+
+import java.security.Principal;
+
+public interface PrincipalHolder
+{
+ /** @return a Principal that was used to authorized this session */
+ Principal getPrincipal();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java
index 6f7f66fad2..af0a1944cd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java
@@ -14,9 +14,9 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.server.security.access;
@@ -32,14 +32,11 @@ import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.configuration.SecurityConfiguration;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.plugins.PluginManager;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult;
-import org.apache.qpid.server.security.access.plugins.SimpleXML;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.virtualhost.VirtualHost;
public class ACLManager
@@ -78,7 +75,7 @@ public class ACLManager
{
_hostPlugins = configurePlugins(hostConfig);
}
-
+
public Map<String, ACLPlugin> configurePlugins(SecurityConfiguration hostConfig) throws ConfigurationException
{
Configuration securityConfig = hostConfig.getConfiguration();
@@ -108,7 +105,7 @@ public class ACLManager
}
}
return plugins;
- }
+ }
public static Logger getLogger()
{
@@ -131,18 +128,18 @@ public class ACLManager
if (result == AuthzResult.DENIED)
{
// Something vetoed the access, we're done
- return false;
+ return false;
}
else if (result == AuthzResult.ALLOWED)
{
- // Remove plugin from global check list since
+ // Remove plugin from global check list since
// host allow overrides global allow
remainingPlugins.remove(plugin.getKey());
}
}
-
+
for (ACLPlugin plugin : remainingPlugins.values())
- {
+ {
result = checker.allowed(plugin);
if (result == AuthzResult.DENIED)
{
@@ -152,7 +149,7 @@ public class ACLManager
return true;
}
- public boolean authoriseBind(final AMQProtocolSession session, final Exchange exch, final AMQQueue queue,
+ public boolean authoriseBind(final PrincipalHolder session, final Exchange exch, final AMQQueue queue,
final AMQShortString routingKey)
{
return checkAllPlugins(new AccessCheck()
@@ -167,7 +164,7 @@ public class ACLManager
});
}
- public boolean authoriseConnect(final AMQProtocolSession session, final VirtualHost virtualHost)
+ public boolean authoriseConnect(final PrincipalHolder session, final VirtualHost virtualHost)
{
return checkAllPlugins(new AccessCheck()
{
@@ -181,7 +178,7 @@ public class ACLManager
});
}
- public boolean authoriseConsume(final AMQProtocolSession session, final boolean noAck, final AMQQueue queue)
+ public boolean authoriseConsume(final PrincipalHolder session, final boolean noAck, final AMQQueue queue)
{
return checkAllPlugins(new AccessCheck()
{
@@ -195,7 +192,7 @@ public class ACLManager
});
}
- public boolean authoriseConsume(final AMQProtocolSession session, final boolean exclusive, final boolean noAck,
+ public boolean authoriseConsume(final PrincipalHolder session, final boolean exclusive, final boolean noAck,
final boolean noLocal, final boolean nowait, final AMQQueue queue)
{
return checkAllPlugins(new AccessCheck()
@@ -210,7 +207,7 @@ public class ACLManager
});
}
- public boolean authoriseCreateExchange(final AMQProtocolSession session, final boolean autoDelete,
+ public boolean authoriseCreateExchange(final PrincipalHolder session, final boolean autoDelete,
final boolean durable, final AMQShortString exchangeName, final boolean internal, final boolean nowait,
final boolean passive, final AMQShortString exchangeType)
{
@@ -227,7 +224,7 @@ public class ACLManager
});
}
- public boolean authoriseCreateQueue(final AMQProtocolSession session, final boolean autoDelete,
+ public boolean authoriseCreateQueue(final PrincipalHolder session, final boolean autoDelete,
final boolean durable, final boolean exclusive, final boolean nowait, final boolean passive,
final AMQShortString queue)
{
@@ -243,7 +240,7 @@ public class ACLManager
});
}
- public boolean authoriseDelete(final AMQProtocolSession session, final AMQQueue queue)
+ public boolean authoriseDelete(final PrincipalHolder session, final AMQQueue queue)
{
return checkAllPlugins(new AccessCheck()
{
@@ -257,7 +254,7 @@ public class ACLManager
});
}
- public boolean authoriseDelete(final AMQProtocolSession session, final Exchange exchange)
+ public boolean authoriseDelete(final PrincipalHolder session, final Exchange exchange)
{
return checkAllPlugins(new AccessCheck()
{
@@ -270,8 +267,8 @@ public class ACLManager
});
}
-
- public boolean authorisePublish(final AMQProtocolSession session, final boolean immediate, final boolean mandatory,
+
+ public boolean authorisePublish(final PrincipalHolder session, final boolean immediate, final boolean mandatory,
final AMQShortString routingKey, final Exchange e)
{
return checkAllPlugins(new AccessCheck()
@@ -286,7 +283,7 @@ public class ACLManager
});
}
- public boolean authorisePurge(final AMQProtocolSession session, final AMQQueue queue)
+ public boolean authorisePurge(final PrincipalHolder session, final AMQQueue queue)
{
return checkAllPlugins(new AccessCheck()
{
@@ -300,7 +297,7 @@ public class ACLManager
});
}
- public boolean authoriseUnbind(final AMQProtocolSession session, final Exchange exch,
+ public boolean authoriseUnbind(final PrincipalHolder session, final Exchange exch,
final AMQShortString routingKey, final AMQQueue queue)
{
return checkAllPlugins(new AccessCheck()
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java
index 032184ec39..cf8a3fede9 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java
@@ -24,9 +24,9 @@ import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.security.PrincipalHolder;
public interface ACLPlugin
{
@@ -34,37 +34,37 @@ public interface ACLPlugin
{
ALLOWED,
DENIED,
- ABSTAIN
+ ABSTAIN
}
void setConfiguration(Configuration config) throws ConfigurationException;
- // These return true if the plugin thinks the action should be allowed, and false if not.
-
- AuthzResult authoriseBind(AMQProtocolSession session, Exchange exch, AMQQueue queue, AMQShortString routingKey);
+ // These return true if the plugin thinks the action should be allowed, and false if not.
- AuthzResult authoriseCreateExchange(AMQProtocolSession session, boolean autoDelete, boolean durable,
+ AuthzResult authoriseBind(PrincipalHolder session, Exchange exch, AMQQueue queue, AMQShortString routingKey);
+
+ AuthzResult authoriseCreateExchange(PrincipalHolder session, boolean autoDelete, boolean durable,
AMQShortString exchangeName, boolean internal, boolean nowait, boolean passive, AMQShortString exchangeType);
- AuthzResult authoriseCreateQueue(AMQProtocolSession session, boolean autoDelete, boolean durable, boolean exclusive,
+ AuthzResult authoriseCreateQueue(PrincipalHolder session, boolean autoDelete, boolean durable, boolean exclusive,
boolean nowait, boolean passive, AMQShortString queue);
- AuthzResult authoriseConnect(AMQProtocolSession session, VirtualHost virtualHost);
+ AuthzResult authoriseConnect(PrincipalHolder session, VirtualHost virtualHost);
- AuthzResult authoriseConsume(AMQProtocolSession session, boolean noAck, AMQQueue queue);
+ AuthzResult authoriseConsume(PrincipalHolder session, boolean noAck, AMQQueue queue);
- AuthzResult authoriseConsume(AMQProtocolSession session, boolean exclusive, boolean noAck, boolean noLocal,
+ AuthzResult authoriseConsume(PrincipalHolder session, boolean exclusive, boolean noAck, boolean noLocal,
boolean nowait, AMQQueue queue);
- AuthzResult authoriseDelete(AMQProtocolSession session, AMQQueue queue);
+ AuthzResult authoriseDelete(PrincipalHolder session, AMQQueue queue);
- AuthzResult authoriseDelete(AMQProtocolSession session, Exchange exchange);
+ AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange);
- AuthzResult authorisePublish(AMQProtocolSession session, boolean immediate, boolean mandatory,
+ AuthzResult authorisePublish(PrincipalHolder session, boolean immediate, boolean mandatory,
AMQShortString routingKey, Exchange e);
- AuthzResult authorisePurge(AMQProtocolSession session, AMQQueue queue);
+ AuthzResult authorisePurge(PrincipalHolder session, AMQQueue queue);
- AuthzResult authoriseUnbind(AMQProtocolSession session, Exchange exch, AMQShortString routingKey, AMQQueue queue);
+ AuthzResult authoriseUnbind(PrincipalHolder session, Exchange exch, AMQShortString routingKey, AMQQueue queue);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java
index 6d35d7ae48..a299907e42 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java
@@ -425,8 +425,9 @@ public class PrincipalPermissions
// This will allow consumption from any temporary queue including ones not owned by this user.
// Of course the exclusivity will not be broken.
{
+
// if not limited to ownQueuesOnly then ok else check queue Owner.
- return (!ownQueuesOnly || queue.getOwner().equals(_user)) ? AuthzResult.ALLOWED : AuthzResult.DENIED;
+ return (!ownQueuesOnly || new AMQShortString(queue.getPrincipalHolder().getPrincipal().getName()).equals(_user)) ? AuthzResult.ALLOWED : AuthzResult.DENIED;
}
}
//if this is a temporary queue and the user does not have permissions for temporary queues then deny
@@ -441,7 +442,7 @@ public class PrincipalPermissions
// if no queues are listed then ALL are ok othereise it must be specified.
if (ownQueuesOnly)
{
- if (queue.getOwner().equals(_user))
+ if ( new AMQShortString(queue.getPrincipalHolder().getPrincipal().getName()).equals(_user))
{
return (queues.size() == 0 || queues.contains(queue.getName())) ? AuthzResult.ALLOWED : AuthzResult.DENIED;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java
index 682135bc25..f99f3a60f7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java
@@ -22,76 +22,76 @@ package org.apache.qpid.server.security.access.plugins;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.security.access.ACLPlugin;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.security.PrincipalHolder;
/**
- * This ACLPlugin abstains from all votes. Useful if your plugin only cares about a few operations.
+ * This ACLPlugin abstains from all votes. Useful if your plugin only cares about a few operations.
*/
public abstract class AbstractACLPlugin implements ACLPlugin
{
private static final AuthzResult DEFAULT_ANSWER = AuthzResult.ABSTAIN;
- public AuthzResult authoriseBind(AMQProtocolSession session, Exchange exch, AMQQueue queue,
+ public AuthzResult authoriseBind(PrincipalHolder session, Exchange exch, AMQQueue queue,
AMQShortString routingKey)
{
return DEFAULT_ANSWER;
}
- public AuthzResult authoriseConnect(AMQProtocolSession session, VirtualHost virtualHost)
+ public AuthzResult authoriseConnect(PrincipalHolder session, VirtualHost virtualHost)
{
return DEFAULT_ANSWER;
}
- public AuthzResult authoriseConsume(AMQProtocolSession session, boolean noAck, AMQQueue queue)
+ public AuthzResult authoriseConsume(PrincipalHolder session, boolean noAck, AMQQueue queue)
{
return DEFAULT_ANSWER;
}
- public AuthzResult authoriseConsume(AMQProtocolSession session, boolean exclusive, boolean noAck, boolean noLocal,
+ public AuthzResult authoriseConsume(PrincipalHolder session, boolean exclusive, boolean noAck, boolean noLocal,
boolean nowait, AMQQueue queue)
{
return DEFAULT_ANSWER;
}
- public AuthzResult authoriseCreateExchange(AMQProtocolSession session, boolean autoDelete, boolean durable,
+ public AuthzResult authoriseCreateExchange(PrincipalHolder session, boolean autoDelete, boolean durable,
AMQShortString exchangeName, boolean internal, boolean nowait, boolean passive, AMQShortString exchangeType)
{
// TODO Auto-generated method stub
return null;
}
- public AuthzResult authoriseCreateQueue(AMQProtocolSession session, boolean autoDelete, boolean durable,
+ public AuthzResult authoriseCreateQueue(PrincipalHolder session, boolean autoDelete, boolean durable,
boolean exclusive, boolean nowait, boolean passive, AMQShortString queue)
{
return DEFAULT_ANSWER;
}
- public AuthzResult authoriseDelete(AMQProtocolSession session, AMQQueue queue)
+ public AuthzResult authoriseDelete(PrincipalHolder session, AMQQueue queue)
{
return DEFAULT_ANSWER;
}
- public AuthzResult authoriseDelete(AMQProtocolSession session, Exchange exchange)
+ public AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange)
{
return DEFAULT_ANSWER;
}
- public AuthzResult authorisePublish(AMQProtocolSession session, boolean immediate, boolean mandatory,
+ public AuthzResult authorisePublish(PrincipalHolder session, boolean immediate, boolean mandatory,
AMQShortString routingKey, Exchange e)
{
return DEFAULT_ANSWER;
}
- public AuthzResult authorisePurge(AMQProtocolSession session, AMQQueue queue)
+ public AuthzResult authorisePurge(PrincipalHolder session, AMQQueue queue)
{
return DEFAULT_ANSWER;
}
- public AuthzResult authoriseUnbind(AMQProtocolSession session, Exchange exch, AMQShortString routingKey,
+ public AuthzResult authoriseUnbind(PrincipalHolder session, Exchange exch, AMQShortString routingKey,
AMQQueue queue)
{
return DEFAULT_ANSWER;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java
index ca6b68dafa..d0df354d78 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java
@@ -21,46 +21,45 @@
package org.apache.qpid.server.security.access.plugins;
import org.apache.commons.configuration.Configuration;
-import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.security.access.ACLPlugin;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.virtualhost.VirtualHost;
public abstract class BasicACLPlugin implements ACLPlugin
{
- // Returns true or false if the plugin should authorise or deny the request
+ // Returns true or false if the plugin should authorise or deny the request
protected abstract AuthzResult getResult();
-
- public AuthzResult authoriseBind(AMQProtocolSession session, Exchange exch,
+
+ public AuthzResult authoriseBind(PrincipalHolder session, Exchange exch,
AMQQueue queue, AMQShortString routingKey)
{
return getResult();
}
- public AuthzResult authoriseConnect(AMQProtocolSession session,
+ public AuthzResult authoriseConnect(PrincipalHolder session,
VirtualHost virtualHost)
{
return getResult();
}
- public AuthzResult authoriseConsume(AMQProtocolSession session, boolean noAck,
+ public AuthzResult authoriseConsume(PrincipalHolder session, boolean noAck,
AMQQueue queue)
{
- return getResult();
+ return getResult();
}
- public AuthzResult authoriseConsume(AMQProtocolSession session,
+ public AuthzResult authoriseConsume(PrincipalHolder session,
boolean exclusive, boolean noAck, boolean noLocal, boolean nowait,
AMQQueue queue)
{
return getResult();
}
- public AuthzResult authoriseCreateExchange(AMQProtocolSession session,
+ public AuthzResult authoriseCreateExchange(PrincipalHolder session,
boolean autoDelete, boolean durable, AMQShortString exchangeName,
boolean internal, boolean nowait, boolean passive,
AMQShortString exchangeType)
@@ -68,36 +67,36 @@ public abstract class BasicACLPlugin implements ACLPlugin
return getResult();
}
- public AuthzResult authoriseCreateQueue(AMQProtocolSession session,
+ public AuthzResult authoriseCreateQueue(PrincipalHolder session,
boolean autoDelete, boolean durable, boolean exclusive,
boolean nowait, boolean passive, AMQShortString queue)
{
return getResult();
}
- public AuthzResult authoriseDelete(AMQProtocolSession session, AMQQueue queue)
+ public AuthzResult authoriseDelete(PrincipalHolder session, AMQQueue queue)
{
return getResult();
}
- public AuthzResult authoriseDelete(AMQProtocolSession session, Exchange exchange)
+ public AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange)
{
return getResult();
}
- public AuthzResult authorisePublish(AMQProtocolSession session,
+ public AuthzResult authorisePublish(PrincipalHolder session,
boolean immediate, boolean mandatory, AMQShortString routingKey,
Exchange e)
{
return getResult();
}
- public AuthzResult authorisePurge(AMQProtocolSession session, AMQQueue queue)
+ public AuthzResult authorisePurge(PrincipalHolder session, AMQQueue queue)
{
return getResult();
}
- public AuthzResult authoriseUnbind(AMQProtocolSession session, Exchange exch,
+ public AuthzResult authoriseUnbind(PrincipalHolder session, Exchange exch,
AMQShortString routingKey, AMQQueue queue)
{
return getResult();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/DenyAll.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/DenyAll.java
index 26a76c9af1..77d3c4bcdf 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/DenyAll.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/DenyAll.java
@@ -54,7 +54,7 @@ public class DenyAll extends BasicACLPlugin
if (ACLManager.getLogger().isInfoEnabled())
{
ACLManager.getLogger().info(
- "Denying user:" + session.getAuthorizedID());
+ "Denying user:" + session.getPrincipal());
}
throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
"DenyAll Plugin");
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java
index e299ce99c4..a5bdf662af 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java
@@ -22,24 +22,16 @@
package org.apache.qpid.server.security.access.plugins;
import org.apache.commons.configuration.Configuration;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQConnectionException;
-import org.apache.qpid.framing.AMQMethodBody;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.BasicConsumeBody;
-import org.apache.qpid.framing.BasicPublishBody;
-import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.security.access.ACLManager;
import org.apache.qpid.server.security.access.ACLPlugin;
import org.apache.qpid.server.security.access.ACLPluginFactory;
import org.apache.qpid.server.security.access.AccessResult;
import org.apache.qpid.server.security.access.Permission;
import org.apache.qpid.server.security.access.PrincipalPermissions;
-import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Map;
@@ -64,7 +56,7 @@ public class SimpleXML implements ACLPlugin
return plugin;
}
};
-
+
private Map<String, PrincipalPermissions> _users;
private final AccessResult GRANTED = new AccessResult(this, AccessResult.AccessStatus.GRANTED);
@@ -110,7 +102,7 @@ public class SimpleXML implements ACLPlugin
/**
* Publish format takes Exchange + Routing Key Pairs
- *
+ *
* @param config
* XML Configuration
*/
@@ -349,9 +341,9 @@ public class SimpleXML implements ACLPlugin
return "Simple";
}
- public AuthzResult authoriseBind(AMQProtocolSession session, Exchange exch, AMQQueue queue, AMQShortString routingKey)
+ public AuthzResult authoriseBind(PrincipalHolder session, Exchange exch, AMQQueue queue, AMQShortString routingKey)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
@@ -362,9 +354,9 @@ public class SimpleXML implements ACLPlugin
}
}
- public AuthzResult authoriseConnect(AMQProtocolSession session, VirtualHost virtualHost)
+ public AuthzResult authoriseConnect(PrincipalHolder session, VirtualHost virtualHost)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
@@ -375,9 +367,9 @@ public class SimpleXML implements ACLPlugin
}
}
- public AuthzResult authoriseConsume(AMQProtocolSession session, boolean noAck, AMQQueue queue)
+ public AuthzResult authoriseConsume(PrincipalHolder session, boolean noAck, AMQQueue queue)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
@@ -388,16 +380,16 @@ public class SimpleXML implements ACLPlugin
}
}
- public AuthzResult authoriseConsume(AMQProtocolSession session, boolean exclusive, boolean noAck, boolean noLocal,
+ public AuthzResult authoriseConsume(PrincipalHolder session, boolean exclusive, boolean noAck, boolean noLocal,
boolean nowait, AMQQueue queue)
{
return authoriseConsume(session, noAck, queue);
}
- public AuthzResult authoriseCreateExchange(AMQProtocolSession session, boolean autoDelete, boolean durable,
+ public AuthzResult authoriseCreateExchange(PrincipalHolder session, boolean autoDelete, boolean durable,
AMQShortString exchangeName, boolean internal, boolean nowait, boolean passive, AMQShortString exchangeType)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
@@ -408,10 +400,10 @@ public class SimpleXML implements ACLPlugin
}
}
- public AuthzResult authoriseCreateQueue(AMQProtocolSession session, boolean autoDelete, boolean durable, boolean exclusive,
+ public AuthzResult authoriseCreateQueue(PrincipalHolder session, boolean autoDelete, boolean durable, boolean exclusive,
boolean nowait, boolean passive, AMQShortString queue)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
@@ -422,9 +414,9 @@ public class SimpleXML implements ACLPlugin
}
}
- public AuthzResult authoriseDelete(AMQProtocolSession session, AMQQueue queue)
+ public AuthzResult authoriseDelete(PrincipalHolder session, AMQQueue queue)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
@@ -435,9 +427,9 @@ public class SimpleXML implements ACLPlugin
}
}
- public AuthzResult authoriseDelete(AMQProtocolSession session, Exchange exchange)
+ public AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
@@ -448,10 +440,10 @@ public class SimpleXML implements ACLPlugin
}
}
- public AuthzResult authorisePublish(AMQProtocolSession session, boolean immediate, boolean mandatory,
+ public AuthzResult authorisePublish(PrincipalHolder session, boolean immediate, boolean mandatory,
AMQShortString routingKey, Exchange e)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
@@ -462,9 +454,9 @@ public class SimpleXML implements ACLPlugin
}
}
- public AuthzResult authorisePurge(AMQProtocolSession session, AMQQueue queue)
+ public AuthzResult authorisePurge(PrincipalHolder session, AMQQueue queue)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
@@ -475,9 +467,9 @@ public class SimpleXML implements ACLPlugin
}
}
- public AuthzResult authoriseUnbind(AMQProtocolSession session, Exchange exch, AMQShortString routingKey, AMQQueue queue)
+ public AuthzResult authoriseUnbind(PrincipalHolder session, Exchange exch, AMQShortString routingKey, AMQQueue queue)
{
- PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
+ PrincipalPermissions principalPermissions = _users.get(session.getPrincipal().getName());
if (principalPermissions == null)
{
return AuthzResult.DENIED;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java
index 7450322130..17d80c63fa 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/network/FirewallPlugin.java
@@ -31,10 +31,11 @@ import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.server.security.access.ACLPlugin;
import org.apache.qpid.server.security.access.ACLPluginFactory;
import org.apache.qpid.server.security.access.plugins.AbstractACLPlugin;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.util.NetMatcher;
@@ -57,7 +58,7 @@ public class FirewallPlugin extends AbstractACLPlugin
return plugin;
}
};
-
+
public class FirewallRule
{
@@ -69,13 +70,13 @@ public class FirewallPlugin extends AbstractACLPlugin
public FirewallRule(String access, List networks, List hostnames)
{
_access = (access.equals("allow")) ? AuthzResult.ALLOWED : AuthzResult.DENIED;
-
+
if (networks != null && networks.size() > 0)
{
String[] networkStrings = objListToStringArray(networks);
_network = new NetMatcher(networkStrings);
}
-
+
if (hostnames != null && hostnames.size() > 0)
{
int i = 0;
@@ -85,7 +86,7 @@ public class FirewallPlugin extends AbstractACLPlugin
_hostnamePatterns[i++] = Pattern.compile(hostname);
}
}
-
+
}
private String[] objListToStringArray(List objList)
@@ -147,7 +148,7 @@ public class FirewallPlugin extends AbstractACLPlugin
thread.run();
long endTime = System.currentTimeMillis() + DNS_TIMEOUT;
-
+
while (System.currentTimeMillis() < endTime && !done.get())
{
try
@@ -176,8 +177,15 @@ public class FirewallPlugin extends AbstractACLPlugin
private FirewallRule[] _rules;
@Override
- public AuthzResult authoriseConnect(AMQProtocolSession session, VirtualHost virtualHost)
+ public AuthzResult authoriseConnect(PrincipalHolder principalHolder, VirtualHost virtualHost)
{
+ if(!(principalHolder instanceof ProtocolEngine))
+ {
+ return AuthzResult.ABSTAIN; // We only deal with tcp sessions
+ }
+
+ ProtocolEngine session = (ProtocolEngine) principalHolder;
+
SocketAddress sockAddr = session.getRemoteAddress();
if (!(sockAddr instanceof InetSocketAddress))
{
@@ -228,7 +236,7 @@ public class FirewallPlugin extends AbstractACLPlugin
_default = AuthzResult.DENIED;
}
CompositeConfiguration finalConfig = new CompositeConfiguration(config);
-
+
List subFiles = config.getList("xml[@fileName]");
for (Object subFile : subFiles)
{
@@ -236,7 +244,7 @@ public class FirewallPlugin extends AbstractACLPlugin
}
// all rules must have an access attribute
- int numRules = finalConfig.getList("rule[@access]").size();
+ int numRules = finalConfig.getList("rule[@access]").size();
_rules = new FirewallRule[numRules];
for (int i = 0; i < numRules; i++)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
index e0d4c49af1..2619a69cfd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
@@ -215,14 +215,7 @@ public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatab
_logger.warn("Unable to load access file:" + jmxaccesssFile);
}
- try
- {
- _mbean.register();
- }
- catch (AMQException e)
- {
- _logger.warn("Unable to register user management MBean");
- }
+ _mbean.register();
}
catch (JMException e)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java
index fd2d09b777..f8bc530aa6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMessageStore.java
@@ -31,12 +31,12 @@ public abstract class AbstractMessageStore implements MessageStore
{
protected LogSubject _logSubject;
- public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration hostConfig) throws Exception
+ public void configure(VirtualHost virtualHost) throws Exception
{
_logSubject = new MessageStoreLogSubject(virtualHost, this);
CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1001(this.getClass().getName()));
}
-
+
public void close() throws Exception
{
CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1003());
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
new file mode 100755
index 0000000000..c7606832d0
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
@@ -0,0 +1,57 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.store;
+
+import java.nio.ByteBuffer;
+import org.apache.qpid.framing.FieldTable;
+
+public interface ConfigurationRecoveryHandler
+{
+ QueueRecoveryHandler begin(MessageStore store);
+
+ public static interface QueueRecoveryHandler
+ {
+ void queue(String queueName, String owner, FieldTable arguments);
+ ExchangeRecoveryHandler completeQueueRecovery();
+ }
+
+ public static interface ExchangeRecoveryHandler
+ {
+ void exchange(String exchangeName, String type, boolean autoDelete);
+ BindingRecoveryHandler completeExchangeRecovery();
+ }
+
+ public static interface BindingRecoveryHandler
+ {
+ void binding(String exchangeName, String queueName, String bindingKey, ByteBuffer buf);
+ void completeBindingRecovery();
+ }
+
+ public static interface QueueEntryRecoveryHandler
+ {
+ void complete();
+
+ void queueEntry(String queueName, long messageId);
+ }
+
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
index c014739324..ba5574d1fa 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
@@ -21,28 +21,18 @@
package org.apache.qpid.server.store;
import org.apache.log4j.Logger;
-import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.logging.actors.BrokerActor;
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.queue.AMQMessage;
+import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
+import org.apache.qpid.server.logging.messages.TransactionLogMessages;
+import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-import org.apache.qpid.server.queue.MessageHandleFactory;
-import org.apache.qpid.server.queue.MessageMetaData;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.txn.NonTransactionalContext;
-import org.apache.qpid.server.txn.TransactionalContext;
-import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.commons.configuration.Configuration;
+
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -56,15 +46,14 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import java.lang.ref.WeakReference;
+import java.nio.ByteBuffer;
-public class DerbyMessageStore extends AbstractMessageStore
+public class DerbyMessageStore implements MessageStore
{
private static final Logger _logger = Logger.getLogger(DerbyMessageStore.class);
@@ -80,57 +69,66 @@ public class DerbyMessageStore extends AbstractMessageStore
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 MESSAGE_META_DATA_TABLE_NAME = "QPID_MESSAGE_META_DATA";
+
+ private static final String META_DATA_TABLE_NAME = "QPID_META_DATA";
private static final String MESSAGE_CONTENT_TABLE_NAME = "QPID_MESSAGE_CONTENT";
private static final int DB_VERSION = 1;
- private VirtualHost _virtualHost;
private static Class<Driver> DRIVER_CLASS;
- private final AtomicLong _messageId = new AtomicLong(1);
+ private final AtomicLong _messageId = new AtomicLong(0);
private AtomicBoolean _closed = new AtomicBoolean(false);
private String _connectionURL;
- Map<AMQShortString, Integer> _queueRecoveries = new TreeMap<AMQShortString, Integer>();
-
+ private static final String TABLE_EXISTANCE_QUERY = "SELECT 1 FROM SYS.SYSTABLES WHERE TABLENAME = ?";
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), 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 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 CREATE_MESSAGE_META_DATA_TABLE = "CREATE TABLE "+MESSAGE_META_DATA_TABLE_NAME+" ( message_id bigint not null, exchange_name varchar(255) not null, routing_key varchar(255), flag_mandatory smallint not null, flag_immediate smallint not null, content_header blob, chunk_count int not null, PRIMARY KEY ( message_id ) )";
- private static final String CREATE_MESSAGE_CONTENT_TABLE = "CREATE TABLE "+MESSAGE_CONTENT_TABLE_NAME+" ( message_id bigint not null, chunk_id int not null, content_chunk blob , PRIMARY KEY (message_id, chunk_id) )";
private static final String SELECT_FROM_QUEUE = "SELECT name, owner FROM " + QUEUE_TABLE_NAME;
private static final String FIND_QUEUE = "SELECT name, owner FROM " + QUEUE_TABLE_NAME + " 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 queue_name, binding_key, arguments FROM " + BINDINGS_TABLE_NAME + " WHERE exchange_name = ?";
+ "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 DELETE_FROM_MESSAGE_META_DATA = "DELETE FROM " + MESSAGE_META_DATA_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_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 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) 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 INSERT_INTO_MESSAGE_CONTENT = "INSERT INTO " + MESSAGE_CONTENT_TABLE_NAME + "( message_id, chunk_id, content_chunk ) values (?, ?, ?)";
- private static final String INSERT_INTO_MESSAGE_META_DATA = "INSERT INTO " + MESSAGE_META_DATA_TABLE_NAME + "( message_id , exchange_name , routing_key , flag_mandatory , flag_immediate , content_header , chunk_count ) values (?, ?, ?, ?, ?, ?, ?)";
- private static final String SELECT_FROM_MESSAGE_META_DATA =
- "SELECT exchange_name , routing_key , flag_mandatory , flag_immediate , content_header , chunk_count FROM " + MESSAGE_META_DATA_TABLE_NAME + " WHERE 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 content_chunk FROM " + MESSAGE_CONTENT_TABLE_NAME + " WHERE message_id = ? and chunk_id = ?";
- private static final String SELECT_FROM_QUEUE_ENTRY = "SELECT queue_name, message_id FROM " + QUEUE_ENTRY_TABLE_NAME;
- private static final String TABLE_EXISTANCE_QUERY = "SELECT 1 FROM SYS.SYSTABLES WHERE TABLENAME = ?";
+ "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 INSERT_INTO_META_DATA = "INSERT INTO " + META_DATA_TABLE_NAME + "( message_id , meta_data ) values (?, ?)";;
+ private static final String SELECT_FROM_META_DATA =
+ "SELECT meta_data FROM " + META_DATA_TABLE_NAME + " WHERE message_id = ?";
+ private static final String DELETE_FROM_META_DATA = "DELETE FROM " + META_DATA_TABLE_NAME + " WHERE message_id = ?";
+ private static final String SELECT_ALL_FROM_META_DATA = "SELECT message_id, meta_data FROM " + META_DATA_TABLE_NAME;
+
+
+ private LogSubject _logSubject;
+ private boolean _configured;
private enum State
@@ -146,21 +144,82 @@ public class DerbyMessageStore extends AbstractMessageStore
private State _state = State.INITIAL;
- public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception
+ public void configureConfigStore(String name,
+ ConfigurationRecoveryHandler recoveryHandler,
+ Configuration storeConfiguration,
+ LogSubject logSubject) throws Exception
{
- super.configure(virtualHost,base,config);
-
stateTransition(State.INITIAL, State.CONFIGURING);
+ _logSubject = logSubject;
+ CurrentActor.get().message(_logSubject, ConfigStoreMessages.CFG_1001(this.getClass().getName()));
- initialiseDriver();
+ if(!_configured)
+ {
+ commonConfiguration(name, storeConfiguration, logSubject);
+ _configured = true;
+ }
+
+ // this recovers durable exchanges, queues, and bindings
+ recover(recoveryHandler);
- _virtualHost = virtualHost;
- _logger.info("Configuring Derby message store for virtual host " + virtualHost.getName());
- QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
+ stateTransition(State.RECOVERING, State.STARTED);
+
+ }
+
+
+ public void configureMessageStore(String name,
+ MessageStoreRecoveryHandler recoveryHandler,
+ Configuration storeConfiguration,
+ LogSubject logSubject) throws Exception
+ {
+ CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1001(this.getClass().getName()));
+
+ if(!_configured)
+ {
+
+ _logSubject = logSubject;
+
+ commonConfiguration(name, storeConfiguration, logSubject);
+ _configured = true;
+ }
+
+ recoverMessages(recoveryHandler);
+
+ }
+
+
+
+ public void configureTransactionLog(String name,
+ TransactionLogRecoveryHandler recoveryHandler,
+ Configuration storeConfiguration,
+ LogSubject logSubject) throws Exception
+ {
+ CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1001(this.getClass().getName()));
+
+ if(!_configured)
+ {
+
+ _logSubject = logSubject;
+
+ commonConfiguration(name, storeConfiguration, logSubject);
+ _configured = true;
+ }
+
+ recoverQueueEntries(recoveryHandler);
+
+ }
+
+
+
+ private void commonConfiguration(String name, Configuration storeConfiguration, LogSubject logSubject)
+ throws ClassNotFoundException, SQLException
+ {
+ initialiseDriver();
//Update to pick up QPID_WORK and use that as the default location not just derbyDB
- final String databasePath = config.getStoreConfiguration().getString(ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK")+"/derbyDB");
+
+ final String databasePath = storeConfiguration.getString(ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK")+"/derbyDB");
File environmentPath = new File(databasePath);
if (!environmentPath.exists())
@@ -172,17 +231,9 @@ public class DerbyMessageStore extends AbstractMessageStore
}
}
- CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1002(environmentPath.getAbsolutePath()));
-
- createOrOpenDatabase(databasePath);
-
- // this recovers durable queues and persistent messages
-
- recover();
-
-
- stateTransition(State.RECOVERING, State.STARTED);
+ CurrentActor.get().message(logSubject, MessageStoreMessages.MST_1002(environmentPath.getAbsolutePath()));
+ createOrOpenDatabase(name, databasePath);
}
private static synchronized void initialiseDriver() throws ClassNotFoundException
@@ -193,10 +244,10 @@ public class DerbyMessageStore extends AbstractMessageStore
}
}
- private void createOrOpenDatabase(final String environmentPath) throws SQLException
+ private void createOrOpenDatabase(String name, final String environmentPath) throws SQLException
{
//fixme this the _vhost name should not be added here.
- _connectionURL = "jdbc:derby:" + environmentPath + "/" + _virtualHost.getName() + ";create=true";
+ _connectionURL = "jdbc:derby:" + environmentPath + "/" + name + ";create=true";
Connection conn = newConnection();
@@ -205,7 +256,7 @@ public class DerbyMessageStore extends AbstractMessageStore
createQueueTable(conn);
createBindingsTable(conn);
createQueueEntryTable(conn);
- createMessageMetaDataTable(conn);
+ createMetaDataTable(conn);
createMessageContentTable(conn);
conn.close();
@@ -276,12 +327,12 @@ public class DerbyMessageStore extends AbstractMessageStore
}
- private void createMessageMetaDataTable(final Connection conn) throws SQLException
+ private void createMetaDataTable(final Connection conn) throws SQLException
{
- if(!tableExists(MESSAGE_META_DATA_TABLE_NAME, conn))
+ if(!tableExists(META_DATA_TABLE_NAME, conn))
{
Statement stmt = conn.createStatement();
- stmt.execute(CREATE_MESSAGE_META_DATA_TABLE);
+ stmt.execute(CREATE_META_DATA_TABLE);
stmt.close();
}
@@ -314,38 +365,22 @@ public class DerbyMessageStore extends AbstractMessageStore
return exists;
}
- public void recover() throws AMQException
+ public void recover(ConfigurationRecoveryHandler recoveryHandler) throws AMQException
{
stateTransition(State.CONFIGURING, State.RECOVERING);
- CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1004(null, false));
-
- StoreContext context = new StoreContext();
try
{
- Map<AMQShortString, AMQQueue> queues = loadQueues();
-
- recoverExchanges();
-
- try
- {
-
- beginTran(context);
+ ConfigurationRecoveryHandler.QueueRecoveryHandler qrh = recoveryHandler.begin(this);
+ List<String> queues = loadQueues(qrh);
- deliverMessages(context, queues);
- commitTran(context);
+ ConfigurationRecoveryHandler.ExchangeRecoveryHandler erh = qrh.completeQueueRecovery();
+ List<String> exchanges = loadExchanges(erh);
+ ConfigurationRecoveryHandler.BindingRecoveryHandler brh = erh.completeExchangeRecovery();
+ recoverBindings(brh, exchanges);
+ brh.completeBindingRecovery();
- //Recovery Complete
- CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1006(null, false));
- }
- finally
- {
- if(inTran(context))
- {
- abortTran(context);
- }
- }
}
catch (SQLException e)
@@ -357,53 +392,34 @@ public class DerbyMessageStore extends AbstractMessageStore
}
- private Map<AMQShortString, AMQQueue> loadQueues() throws SQLException, AMQException
+ private List<String> loadQueues(ConfigurationRecoveryHandler.QueueRecoveryHandler qrh) throws SQLException, AMQException
{
Connection conn = newConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE);
- Map<AMQShortString, AMQQueue> queueMap = new HashMap<AMQShortString, AMQQueue>();
+ List<String> queues = new ArrayList<String>();
+
while(rs.next())
{
String queueName = rs.getString(1);
String owner = rs.getString(2);
- AMQShortString queueNameShortString = new AMQShortString(queueName);
+ qrh.queue(queueName, owner, null);
- AMQQueue q = _virtualHost.getQueueRegistry().getQueue(queueNameShortString);
+ queues.add(queueName);
- if (q == null)
- {
- q = AMQQueueFactory.createAMQQueueImpl(queueNameShortString, true, owner == null ? null : new AMQShortString(owner), false, _virtualHost,
- null);
- _virtualHost.getQueueRegistry().registerQueue(q);
- }
-
- queueMap.put(queueNameShortString,q);
-
- CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1004(String.valueOf(q.getName()), true));
- //Record that we have a queue for recovery
- _queueRecoveries.put(new AMQShortString(queueName), 0);
-
- }
- return queueMap;
- }
- private void recoverExchanges() throws AMQException, SQLException
- {
- for (Exchange exchange : loadExchanges())
- {
- recoverExchange(exchange);
}
+ return queues;
}
- private List<Exchange> loadExchanges() throws AMQException, SQLException
+ private List<String> loadExchanges(ConfigurationRecoveryHandler.ExchangeRecoveryHandler erh) throws AMQException, SQLException
{
- List<Exchange> exchanges = new ArrayList<Exchange>();
+ List<String> exchanges = new ArrayList<String>();
Connection conn = null;
try
{
@@ -413,21 +429,15 @@ public class DerbyMessageStore extends AbstractMessageStore
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(SELECT_FROM_EXCHANGE);
- Exchange exchange;
while(rs.next())
{
String exchangeName = rs.getString(1);
String type = rs.getString(2);
boolean autoDelete = rs.getShort(3) != 0;
- AMQShortString exchangeNameSS = new AMQShortString(exchangeName);
- exchange = _virtualHost.getExchangeRegistry().getExchange(exchangeNameSS);
- if (exchange == null)
- {
- exchange = _virtualHost.getExchangeFactory().createExchange(exchangeNameSS, new AMQShortString(type), true, autoDelete, 0);
- _virtualHost.getExchangeRegistry().registerExchange(exchange);
- }
- exchanges.add(exchange);
+ exchanges.add(exchangeName);
+
+ erh.exchange(exchangeName, type, autoDelete);
}
return exchanges;
@@ -443,11 +453,13 @@ public class DerbyMessageStore extends AbstractMessageStore
}
- private void recoverExchange(Exchange exchange) throws AMQException, SQLException
+ private void recoverBindings(ConfigurationRecoveryHandler.BindingRecoveryHandler brh, List<String> exchanges) throws AMQException, SQLException
{
- _logger.info("Recovering durable exchange " + exchange.getName() + " of type " + exchange.getType() + "...");
- QueueRegistry queueRegistry = _virtualHost.getQueueRegistry();
+
+ _logger.info("Recovering bindings...");
+
+
Connection conn = null;
try
@@ -455,41 +467,29 @@ public class DerbyMessageStore extends AbstractMessageStore
conn = newConnection();
PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_BINDINGS);
- stmt.setString(1, exchange.getName().toString());
ResultSet rs = stmt.executeQuery();
while(rs.next())
{
- String queueName = rs.getString(1);
- String bindingKey = rs.getString(2);
- Blob arguments = rs.getBlob(3);
-
+ String exchangeName = rs.getString(1);
+ String queueName = rs.getString(2);
+ String bindingKey = rs.getString(3);
+ Blob arguments = rs.getBlob(4);
+ java.nio.ByteBuffer buf;
- AMQQueue queue = queueRegistry.getQueue(new AMQShortString(queueName));
- if (queue == null)
+ if(arguments != null && arguments.length() != 0)
{
- _logger.error("Unkown queue: " + queueName + " cannot be bound to exchange: "
- + exchange.getName());
+ byte[] argumentBytes = arguments.getBytes(1, (int) arguments.length());
+ buf = java.nio.ByteBuffer.wrap(argumentBytes);
}
else
{
- _logger.info("Restoring binding: (Exchange: " + exchange.getName() + ", Queue: " + queueName
- + ", Routing Key: " + bindingKey + ", Arguments: " + arguments
- + ")");
-
- FieldTable argumentsFT = null;
- if(arguments != null)
- {
- byte[] argumentBytes = arguments.getBytes(0, (int) arguments.length());
- ByteBuffer buf = ByteBuffer.wrap(argumentBytes);
- argumentsFT = new FieldTable(buf,arguments.length());
- }
-
- queue.bind(exchange, bindingKey == null ? null : new AMQShortString(bindingKey), argumentsFT);
-
+ buf = null;
}
+
+ brh.binding(exchangeName, queueName, bindingKey, buf);
}
}
finally
@@ -501,44 +501,48 @@ public class DerbyMessageStore extends AbstractMessageStore
}
}
+
+
public void close() throws Exception
{
+ CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1003());
_closed.getAndSet(true);
-
- super.close();
}
- public void removeMessage(StoreContext storeContext, Long messageId) throws AMQException
+ public StoredMessage addMessage(StorableMessageMetaData metaData)
{
-
- boolean localTx = getOrCreateTransaction(storeContext);
-
- Connection conn = getConnection(storeContext);
- ConnectionWrapper wrapper = (ConnectionWrapper) storeContext.getPayload();
-
-
- if (_logger.isDebugEnabled())
+ if(metaData.isPersistent())
{
- _logger.debug("Message Id: " + messageId + " Removing");
+ return new StoredDerbyMessage(_messageId.incrementAndGet(), metaData);
}
+ else
+ {
+ return new StoredMemoryMessage(_messageId.incrementAndGet(), metaData);
+ }
+ }
- // first we need to look up the header to get the chunk count
- MessageMetaData mmd = getMessageMetaData(storeContext, messageId);
+ public StoredMessage getMessage(long messageNumber)
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void removeMessage(long messageId)
+ {
+ Connection conn = null;
try
{
- PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_MESSAGE_META_DATA);
+
+
+ conn = newConnection();
+ PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_META_DATA);
stmt.setLong(1,messageId);
- wrapper.setRequiresCommit();
int results = stmt.executeUpdate();
if (results == 0)
{
- if (localTx)
- {
- abortTran(storeContext);
- }
- throw new AMQException("Message metadata not found for message id " + messageId);
+
+ throw new RuntimeException("Message metadata not found for message id " + messageId);
}
stmt.close();
@@ -551,29 +555,27 @@ public class DerbyMessageStore extends AbstractMessageStore
stmt.setLong(1,messageId);
results = stmt.executeUpdate();
- if(results != mmd.getContentChunkCount())
- {
- if (localTx)
- {
- abortTran(storeContext);
- }
- throw new AMQException("Unexpected number of content chunks when deleting message. Expected " + mmd.getContentChunkCount() + " but found " + results);
- }
- if (localTx)
- {
- commitTran(storeContext);
- }
+ conn.commit();
+ conn.close();
}
catch (SQLException e)
{
- if ((conn != null) && localTx)
+ if ((conn != null))
{
- abortTran(storeContext);
+ try
+ {
+ conn.rollback();
+ conn.close();
+ }
+ catch (SQLException e1)
+ {
+
+ }
}
- throw new AMQException("Error writing AMQMessage with id " + messageId + " to database: " + e, e);
+ throw new RuntimeException("Error removing Message with id " + messageId + " to database: " + e, e);
}
}
@@ -802,8 +804,14 @@ public class DerbyMessageStore extends AbstractMessageStore
{
stmt = conn.prepareStatement(INSERT_INTO_QUEUE);
+ String owner = queue.getPrincipalHolder() == null
+ ? null
+ : queue.getPrincipalHolder().getPrincipal() == null
+ ? null
+ : queue.getPrincipalHolder().getPrincipal().getName();
+
stmt.setString(1, queue.getName().toString());
- stmt.setString(2, queue.getOwner() == null ? null : queue.getOwner().toString());
+ stmt.setString(2, owner);
stmt.execute();
@@ -873,29 +881,26 @@ public class DerbyMessageStore extends AbstractMessageStore
}
- public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
+ public Transaction newTransaction()
{
- AMQShortString name = queue.getName();
+ return new DerbyTransaction();
+ }
+
+ public void enqueueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQException
+ {
+ String name = queue.getResourceName();
+
+ Connection conn = connWrapper.getConnection();
- boolean localTx = getOrCreateTransaction(context);
- Connection conn = getConnection(context);
- ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload();
try
{
PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_QUEUE_ENTRY);
- stmt.setString(1,name.toString());
+ stmt.setString(1,name);
stmt.setLong(2,messageId);
stmt.executeUpdate();
connWrapper.requiresCommit();
- if(localTx)
- {
- commitTran(context);
- }
-
-
-
if (_logger.isDebugEnabled())
{
_logger.debug("Enqueuing message " + messageId + " on queue " + name + "[Connection" + conn + "]");
@@ -903,10 +908,6 @@ public class DerbyMessageStore extends AbstractMessageStore
}
catch (SQLException e)
{
- if(localTx)
- {
- abortTran(context);
- }
_logger.error("Failed to enqueue: " + e, e);
throw new AMQException("Error writing enqueued message with id " + messageId + " for queue " + name
+ " to database", e);
@@ -914,18 +915,18 @@ public class DerbyMessageStore extends AbstractMessageStore
}
- public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
+ public void dequeueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQException
{
- AMQShortString name = queue.getName();
+ String name = queue.getResourceName();
+
+
+ Connection conn = connWrapper.getConnection();
- boolean localTx = getOrCreateTransaction(context);
- Connection conn = getConnection(context);
- ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload();
try
{
PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_QUEUE_ENTRY);
- stmt.setString(1,name.toString());
+ stmt.setString(1,name);
stmt.setLong(2,messageId);
int results = stmt.executeUpdate();
@@ -936,13 +937,6 @@ public class DerbyMessageStore extends AbstractMessageStore
throw new AMQException("Unable to find message with id " + messageId + " on queue " + name);
}
- if(localTx)
- {
- commitTran(context);
- }
-
-
-
if (_logger.isDebugEnabled())
{
_logger.debug("Dequeuing message " + messageId + " on queue " + name );//+ "[Connection" + conn + "]");
@@ -950,10 +944,6 @@ public class DerbyMessageStore extends AbstractMessageStore
}
catch (SQLException e)
{
- if(localTx)
- {
- abortTran(context);
- }
_logger.error("Failed to dequeue: " + e, e);
throw new AMQException("Error deleting enqueued message with id " + messageId + " for queue " + name
+ " from database", e);
@@ -987,51 +977,20 @@ public class DerbyMessageStore extends AbstractMessageStore
}
}
- public void beginTran(StoreContext context) throws AMQException
- {
- if (context.getPayload() != null)
- {
- throw new AMQException("Fatal internal error: transactional context is not empty at beginTran: "
- + context.getPayload());
- }
- else
- {
- try
- {
- Connection conn = newConnection();
-
- context.setPayload(new ConnectionWrapper(conn));
- }
- catch (SQLException e)
- {
- throw new AMQException("Error starting transaction: " + e, e);
- }
- }
- }
-
- public void commitTran(StoreContext context) throws AMQException
+ public void commitTran(ConnectionWrapper connWrapper) throws AMQException
{
- ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload();
-
- if (connWrapper == null)
- {
- throw new AMQException("Fatal internal error: transactional context is empty at commitTran");
- }
try
{
Connection conn = connWrapper.getConnection();
- if(connWrapper.requiresCommit())
- {
- conn.commit();
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("commit tran completed");
- }
+ conn.commit();
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("commit tran completed");
}
+
conn.close();
}
catch (SQLException e)
@@ -1040,14 +999,30 @@ public class DerbyMessageStore extends AbstractMessageStore
}
finally
{
- context.setPayload(null);
+
}
}
- public void abortTran(StoreContext context) throws AMQException
+ public StoreFuture commitTranAsync(ConnectionWrapper connWrapper) throws AMQException
{
- ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload();
+ commitTran(connWrapper);
+ return new StoreFuture()
+ {
+ public boolean isComplete()
+ {
+ return true;
+ }
+
+ public void waitForCompletion()
+ {
+ }
+ };
+
+ }
+
+ public void abortTran(ConnectionWrapper connWrapper) throws AMQException
+ {
if (connWrapper == null)
{
throw new AMQException("Fatal internal error: transactional context is empty at abortTran");
@@ -1072,272 +1047,261 @@ public class DerbyMessageStore extends AbstractMessageStore
{
throw new AMQException("Error aborting transaction: " + e, e);
}
- finally
- {
- context.setPayload(null);
- }
+
}
- public boolean inTran(StoreContext context)
+ public Long getNewMessageId()
{
- return context.getPayload() != null;
+ return _messageId.incrementAndGet();
}
- public Long getNewMessageId()
+
+ private void storeMetaData(Connection conn, long messageId, StorableMessageMetaData metaData)
+ throws SQLException
{
- return _messageId.getAndIncrement();
+ PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_META_DATA);
+ stmt.setLong(1,messageId);
+
+ final int bodySize = 1 + metaData.getStorableSize();
+ byte[] underlying = new byte[bodySize];
+ underlying[0] = (byte) metaData.getType().ordinal();
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(underlying);
+ buf.position(1);
+ buf = buf.slice();
+
+ metaData.writeToBuffer(0, buf);
+ ByteArrayInputStream bis = new ByteArrayInputStream(underlying);
+ stmt.setBinaryStream(2,bis,underlying.length);
+ stmt.executeUpdate();
+
}
- public void storeContentBodyChunk(StoreContext context,
- Long messageId,
- int index,
- ContentChunk contentBody,
- boolean lastContentBody) throws AMQException
+
+
+
+ private void recoverMessages(MessageStoreRecoveryHandler recoveryHandler) throws SQLException
{
- boolean localTx = getOrCreateTransaction(context);
- Connection conn = getConnection(context);
- ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload();
+ Connection conn = newConnection();
- try
- {
- PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_MESSAGE_CONTENT);
- stmt.setLong(1,messageId);
- stmt.setInt(2, index);
- byte[] chunkData = new byte[contentBody.getSize()];
- contentBody.getData().duplicate().get(chunkData);
- /* this would be the Java 6 way of doing things
- Blob dataAsBlob = conn.createBlob();
- dataAsBlob.setBytes(1L, chunkData);
- stmt.setBlob(3, dataAsBlob);
- */
- ByteArrayInputStream bis = new ByteArrayInputStream(chunkData);
- stmt.setBinaryStream(3, bis, chunkData.length);
- stmt.executeUpdate();
- connWrapper.requiresCommit();
+ MessageStoreRecoveryHandler.StoredMessageRecoveryHandler messageHandler = recoveryHandler.begin();
- if(localTx)
- {
- commitTran(context);
- }
- }
- catch (SQLException e)
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery(SELECT_ALL_FROM_META_DATA);
+
+ long maxId = 0;
+
+ while(rs.next())
{
- if(localTx)
+
+ long messageId = rs.getLong(1);
+ Blob dataAsBlob = rs.getBlob(2);
+
+ if(messageId > maxId)
{
- abortTran(context);
+ maxId = messageId;
}
- throw new AMQException("Error writing AMQMessage with id " + messageId + " to database: " + e, e);
+ byte[] dataAsBytes = dataAsBlob.getBytes(1,(int) dataAsBlob.length());
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(dataAsBytes);
+ buf.position(1);
+ buf = buf.slice();
+ MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]];
+ StorableMessageMetaData metaData = type.getFactory().createMetaData(buf);
+ StoredDerbyMessage message = new StoredDerbyMessage(messageId, metaData, false);
+ messageHandler.message(message);
+
+
}
+ _messageId.set(maxId);
+
+ messageHandler.completeMessageRecovery();
}
- public void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData mmd)
- throws AMQException
- {
- boolean localTx = getOrCreateTransaction(context);
- Connection conn = getConnection(context);
- ConnectionWrapper connWrapper = (ConnectionWrapper) context.getPayload();
- try
- {
+ private void recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) throws SQLException
+ {
+ Connection conn = newConnection();
- PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_MESSAGE_META_DATA);
- stmt.setLong(1,messageId);
- stmt.setString(2, mmd.getMessagePublishInfo().getExchange().toString());
- stmt.setString(3, mmd.getMessagePublishInfo().getRoutingKey().toString());
- stmt.setShort(4, mmd.getMessagePublishInfo().isMandatory() ? (short) 1 : (short) 0);
- stmt.setShort(5, mmd.getMessagePublishInfo().isImmediate() ? (short) 1 : (short) 0);
-
- ContentHeaderBody headerBody = mmd.getContentHeaderBody();
- final int bodySize = headerBody.getSize();
- byte[] underlying = new byte[bodySize];
- ByteBuffer buf = ByteBuffer.wrap(underlying);
- headerBody.writePayload(buf);
-/*
- Blob dataAsBlob = conn.createBlob();
- dataAsBlob.setBytes(1L, underlying);
- stmt.setBlob(6, dataAsBlob);
-*/
- ByteArrayInputStream bis = new ByteArrayInputStream(underlying);
- stmt.setBinaryStream(6,bis,underlying.length);
+ TransactionLogRecoveryHandler.QueueEntryRecoveryHandler queueEntryHandler = recoveryHandler.begin(this);
- stmt.setInt(7, mmd.getContentChunkCount());
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE_ENTRY);
- stmt.executeUpdate();
- connWrapper.requiresCommit();
- if(localTx)
- {
- commitTran(context);
- }
- }
- catch (SQLException e)
+ while(rs.next())
{
- if(localTx)
- {
- abortTran(context);
- }
- throw new AMQException("Error writing AMQMessage with id " + messageId + " to database: " + e, e);
+ String queueName = rs.getString(1);
+ long messageId = rs.getLong(2);
+ queueEntryHandler.queueEntry(queueName,messageId);
}
+
+ queueEntryHandler.completeQueueEntryRecovery();
+
}
- public MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException
+ StorableMessageMetaData getMetaData(long messageId) throws SQLException
{
- boolean localTx = getOrCreateTransaction(context);
- Connection conn = getConnection(context);
-
+ Connection conn = newConnection();
try
{
-
- PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_MESSAGE_META_DATA);
+ PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_META_DATA);
stmt.setLong(1,messageId);
ResultSet rs = stmt.executeQuery();
if(rs.next())
{
- final AMQShortString exchange = new AMQShortString(rs.getString(1));
- final AMQShortString routingKey = rs.getString(2) == null ? null : new AMQShortString(rs.getString(2));
- final boolean mandatory = (rs.getShort(3) != (short)0);
- final boolean immediate = (rs.getShort(4) != (short)0);
- MessagePublishInfo info = new MessagePublishInfo()
- {
- public AMQShortString getExchange()
- {
- return exchange;
- }
+ Blob dataAsBlob = rs.getBlob(1);
- public void setExchange(AMQShortString exchange)
- {
+ byte[] dataAsBytes = dataAsBlob.getBytes(1,(int) dataAsBlob.length());
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(dataAsBytes);
+ buf.position(1);
+ buf = buf.slice();
+ MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]];
+ StorableMessageMetaData metaData = type.getFactory().createMetaData(buf);
- }
+ return metaData;
+ }
+ else
+ {
+ throw new RuntimeException("Meta data not found for message with id " + messageId);
+ }
- public boolean isImmediate()
- {
- return immediate;
- }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
- public boolean isMandatory()
- {
- return mandatory;
- }
- public AMQShortString getRoutingKey()
- {
- return routingKey;
- }
- } ;
+ private void addContent(Connection conn, long messageId, int offset, ByteBuffer src)
+ {
- Blob dataAsBlob = rs.getBlob(5);
- byte[] dataAsBytes = dataAsBlob.getBytes(1,(int) dataAsBlob.length());
- ByteBuffer buf = ByteBuffer.wrap(dataAsBytes);
- ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(buf, dataAsBytes.length);
+ try
+ {
+ final boolean newConnection = conn == null;
- if(localTx)
- {
- commitTran(context);
- }
+ if(newConnection)
+ {
+ conn = newConnection();
+ }
- return new MessageMetaData(info, chb, rs.getInt(6));
+ src = src.slice();
- }
- else
+ byte[] chunkData = new byte[src.limit()];
+ src.duplicate().get(chunkData);
+
+ PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_MESSAGE_CONTENT);
+ stmt.setLong(1,messageId);
+ stmt.setInt(2, offset);
+ stmt.setInt(3, offset+chunkData.length);
+
+
+ /* this would be the Java 6 way of doing things
+ Blob dataAsBlob = conn.createBlob();
+ dataAsBlob.setBytes(1L, chunkData);
+ stmt.setBlob(3, dataAsBlob);
+ */
+ ByteArrayInputStream bis = new ByteArrayInputStream(chunkData);
+ stmt.setBinaryStream(4, bis, chunkData.length);
+ stmt.executeUpdate();
+
+ if(newConnection)
{
- if(localTx)
- {
- abortTran(context);
- }
- throw new AMQException("Metadata not found for message with id " + messageId);
+ conn.commit();
+ conn.close();
}
}
catch (SQLException e)
{
- if(localTx)
+ if(conn != null)
{
- abortTran(context);
+ try
+ {
+ conn.close();
+ }
+ catch (SQLException e1)
+ {
+
+ }
}
- throw new AMQException("Error reading AMQMessage with id " + messageId + " from database: " + e, e);
+ throw new RuntimeException("Error reading AMQMessage with id " + messageId + " from database: " + e, e);
}
}
- public ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException
- {
- boolean localTx = getOrCreateTransaction(context);
- Connection conn = getConnection(context);
-
-
- try
- {
- PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_MESSAGE_CONTENT);
- stmt.setLong(1,messageId);
- stmt.setInt(2, index);
- ResultSet rs = stmt.executeQuery();
+ public int getContent(long messageId, int offset, ByteBuffer dst)
+ {
+ Connection conn = null;
- if(rs.next())
- {
- Blob dataAsBlob = rs.getBlob(1);
- final int size = (int) dataAsBlob.length();
- byte[] dataAsBytes = dataAsBlob.getBytes(1, size);
- final ByteBuffer buf = ByteBuffer.wrap(dataAsBytes);
+ try
+ {
+ conn = newConnection();
- ContentChunk cb = new ContentChunk()
- {
+ PreparedStatement 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();
- public int getSize()
- {
- return size;
- }
+ int written = 0;
- public ByteBuffer getData()
- {
- return buf;
- }
+ while(rs.next())
+ {
+ int offsetInMessage = rs.getInt(1);
+ Blob dataAsBlob = rs.getBlob(2);
- public void reduceToFit()
- {
+ 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())
+ {
+ count = dst.remaining();
+ }
+ dst.put(dataAsBytes,posInArray,count);
+ written+=count;
- if(localTx)
- {
- commitTran(context);
- }
+ if(dst.remaining() == 0)
+ {
+ break;
+ }
+ }
- return cb;
+ conn.close();
+ return written;
- }
- else
- {
- if(localTx)
- {
- abortTran(context);
- }
- throw new AMQException("Message not found for message with id " + messageId);
- }
+ }
+ catch (SQLException e)
+ {
+ if(conn != null)
+ {
+ try
+ {
+ conn.close();
}
- catch (SQLException e)
+ catch (SQLException e1)
{
- if(localTx)
- {
- abortTran(context);
- }
- throw new AMQException("Error reading AMQMessage with id " + messageId + " from database: " + e, e);
}
+ }
+
+ throw new RuntimeException("Error reading AMQMessage with id " + messageId + " from database: " + e, e);
+ }
@@ -1348,173 +1312,158 @@ public class DerbyMessageStore extends AbstractMessageStore
return true;
}
- private void checkNotClosed() throws MessageStoreClosedException
- {
- if (_closed.get())
- {
- throw new MessageStoreClosedException();
- }
- }
-
- private static final class ProcessAction
+ private synchronized void stateTransition(State requiredState, State newState) throws AMQException
{
- private final AMQQueue _queue;
- private final StoreContext _context;
- private final AMQMessage _message;
-
- public ProcessAction(AMQQueue queue, StoreContext context, AMQMessage message)
- {
- _queue = queue;
- _context = context;
- _message = message;
- }
-
- public void process() throws AMQException
+ if (_state != requiredState)
{
- _queue.enqueue(_context, _message);
+ throw new AMQException("Cannot transition to the state: " + newState + "; need to be in state: " + requiredState
+ + "; currently in state: " + _state);
}
+ _state = newState;
}
- private void deliverMessages(final StoreContext context, Map<AMQShortString, AMQQueue> queues)
- throws SQLException, AMQException
+ private class DerbyTransaction implements Transaction
{
- Map<Long, AMQMessage> msgMap = new HashMap<Long,AMQMessage>();
- List<ProcessAction> actions = new ArrayList<ProcessAction>();
+ private final ConnectionWrapper _connWrapper;
- final boolean inLocaltran = inTran(context);
- Connection conn = null;
- try
+ private DerbyTransaction()
{
- if(inLocaltran)
+ try
{
- conn = getConnection(context);
+ _connWrapper = new ConnectionWrapper(newConnection());
}
- else
+ catch (SQLException e)
{
- conn = newConnection();
+ throw new RuntimeException(e);
}
+ }
- MessageHandleFactory messageHandleFactory = new MessageHandleFactory();
- long maxId = 1;
+ public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQException
+ {
+ DerbyMessageStore.this.enqueueMessage(_connWrapper, queue, messageId);
+ }
- TransactionalContext txnContext = new NonTransactionalContext(this, new StoreContext(), null, null);
+ public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQException
+ {
+ DerbyMessageStore.this.dequeueMessage(_connWrapper, queue, messageId);
- Statement stmt = conn.createStatement();
- ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE_ENTRY);
+ }
- while (rs.next())
- {
- AMQShortString queueName = new AMQShortString(rs.getString(1));
+ public void commitTran() throws AMQException
+ {
+ DerbyMessageStore.this.commitTran(_connWrapper);
+ }
- AMQQueue queue = queues.get(queueName);
- if (queue == null)
- {
- queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, null, false, _virtualHost, null);
+ public StoreFuture commitTranAsync() throws AMQException
+ {
+ return DerbyMessageStore.this.commitTranAsync(_connWrapper);
+ }
- _virtualHost.getQueueRegistry().registerQueue(queue);
- queues.put(queueName, queue);
+ public void abortTran() throws AMQException
+ {
+ DerbyMessageStore.this.abortTran(_connWrapper);
+ }
+ }
- //Log Recovery Start
- CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1004(String.valueOf(queue.getName()), true));
- }
+ private class StoredDerbyMessage implements StoredMessage
+ {
- long messageId = rs.getLong(2);
- maxId = Math.max(maxId, messageId);
- AMQMessage message = msgMap.get(messageId);
+ private final long _messageId;
+ private volatile WeakReference<StorableMessageMetaData> _metaDataRef;
+ private Connection _conn;
- if(message != null)
- {
- message.incrementReference();
- }
- else
- {
- message = new AMQMessage(messageId, this, messageHandleFactory, txnContext);
- msgMap.put(messageId,message);
- }
+ StoredDerbyMessage(long messageId, StorableMessageMetaData metaData)
+ {
+ this(messageId, metaData, true);
+ }
- if (_logger.isDebugEnabled())
- {
- _logger.debug("On recovery, delivering " + message.getMessageId() + " to " + queue.getName());
- }
- Integer count = _queueRecoveries.get(queueName);
- if (count == null)
+ StoredDerbyMessage(long messageId,
+ StorableMessageMetaData metaData, boolean persist)
+ {
+ try
+ {
+ _messageId = messageId;
+
+ _metaDataRef = new WeakReference(metaData);
+ if(persist)
{
- count = 0;
+ _conn = newConnection();
+ storeMetaData(_conn, messageId, metaData);
}
-
- _queueRecoveries.put(queueName, ++count);
-
- actions.add(new ProcessAction(queue, context, message));
}
-
- for(ProcessAction action : actions)
+ catch (SQLException e)
{
- action.process();
+ throw new RuntimeException(e);
}
- _messageId.set(maxId + 1);
- }
- catch (SQLException e)
- {
- _logger.error("Error: " + e, e);
- throw e;
}
- finally
+
+ public StorableMessageMetaData getMetaData()
{
- if (inLocaltran && conn != null)
+ StorableMessageMetaData metaData = _metaDataRef.get();
+ if(metaData == null)
{
- conn.close();
+ try
+ {
+ metaData = DerbyMessageStore.this.getMetaData(_messageId);
+ }
+ catch (SQLException e)
+ {
+ throw new RuntimeException(e);
+ }
+ _metaDataRef = new WeakReference(metaData);
}
+
+ return metaData;
}
- if (_logger.isInfoEnabled())
+ public long getMessageNumber()
{
- _logger.info("Recovered message counts: " + _queueRecoveries);
+ return _messageId;
}
- for(Map.Entry<AMQShortString,Integer> entry : _queueRecoveries.entrySet())
+ public void addContent(int offsetInMessage, java.nio.ByteBuffer src)
{
- CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1005(entry.getValue(), String.valueOf(entry.getKey())));
-
- CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1006(String.valueOf(entry.getKey()), true));
+ DerbyMessageStore.this.addContent(_conn, _messageId, offsetInMessage, src);
}
- // Free the memory
- _queueRecoveries = null;
-
- }
-
- private Connection getConnection(final StoreContext context)
- {
- return ((ConnectionWrapper)context.getPayload()).getConnection();
- }
-
- private boolean getOrCreateTransaction(StoreContext context) throws AMQException
- {
-
- ConnectionWrapper tx = (ConnectionWrapper) context.getPayload();
- if (tx == null)
+ public int getContent(int offsetInMessage, java.nio.ByteBuffer dst)
{
- beginTran(context);
- return true;
+ return DerbyMessageStore.this.getContent(_messageId, offsetInMessage, dst);
}
- return false;
- }
-
- private synchronized void stateTransition(State requiredState, State newState) throws AMQException
- {
- if (_state != requiredState)
+ public StoreFuture flushToStore()
{
- throw new AMQException("Cannot transition to the state: " + newState + "; need to be in state: " + requiredState
- + "; currently in state: " + _state);
+ try
+ {
+ if(_conn != null)
+ {
+ _conn.commit();
+ _conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ _conn = null;
+ }
+ return IMMEDIATE_FUTURE;
}
- _state = newState;
+ public void remove()
+ {
+ flushToStore();
+ DerbyMessageStore.this.removeMessage(_messageId);
+ }
}
+
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java
new file mode 100755
index 0000000000..cfbacd28c8
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java
@@ -0,0 +1,116 @@
+/*
+ *
+ * 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.exchange.Exchange;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.commons.configuration.Configuration;
+
+public interface DurableConfigurationStore
+{
+
+ /**
+ * 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 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;
+ /**
+ * Makes the specified exchange persistent.
+ *
+ * @param exchange The exchange to persist.
+ *
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void createExchange(Exchange exchange) throws AMQException;
+
+ /**
+ * Removes the specified persistent exchange.
+ *
+ * @param exchange The exchange to remove.
+ *
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void removeExchange(Exchange exchange) throws AMQException;
+
+ /**
+ * Binds the specified queue to an exchange with a routing key.
+ *
+ * @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.
+ *
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException;
+
+ /**
+ * Unbinds the specified from an exchange under a particular routing key.
+ *
+ * @param exchange The exchange to unbind from.
+ * @param routingKey The routing key to unbind.
+ * @param queue The queue to unbind.
+ * @param args Additonal parameters.
+ *
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException;
+
+ /**
+ * Makes the specified queue persistent.
+ *
+ * @param queue The queue to store.
+ *
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void createQueue(AMQQueue queue) throws AMQException;
+
+ /**
+ * Makes the specified queue persistent.
+ *
+ * @param queue The queue to store.
+ *
+ * @param arguments The additional arguments to the binding
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException;
+
+ /**
+ * Removes the specified queue from the persistent store.
+ *
+ * @param queue The queue to remove.
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void removeQueue(AMQQueue queue) throws AMQException;
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
index 87ec66030d..f43177bfc1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
@@ -20,21 +20,20 @@
*/
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.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.server.queue.MessageMetaData;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.messages.MessageStoreMessages;
-import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject;
+import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.commons.configuration.Configuration;
import java.util.ArrayList;
import java.util.Collections;
@@ -43,9 +42,10 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import java.nio.ByteBuffer;
/** A simple message store that stores the messages in a threadsafe structure in memory. */
-public class MemoryMessageStore extends AbstractMessageStore
+public class MemoryMessageStore implements MessageStore
{
private static final Logger _log = Logger.getLogger(MemoryMessageStore.class);
@@ -53,52 +53,74 @@ public class MemoryMessageStore extends AbstractMessageStore
private static final String HASHTABLE_CAPACITY_CONFIG = "hashtable-capacity";
- protected ConcurrentMap<Long, MessageMetaData> _metaDataMap;
-
- protected ConcurrentMap<Long, List<ContentChunk>> _contentBodyMap;
private final AtomicLong _messageId = new AtomicLong(1);
private AtomicBoolean _closed = new AtomicBoolean(false);
private LogSubject _logSubject;
- public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception
+ private static final Transaction IN_MEMORY_TRANSACTION = new Transaction()
{
- super.configure(virtualHost,base,config);
+ public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQException
+ {
+ }
- int hashtableCapacity = config.getStoreConfiguration().getInt(base + "." + HASHTABLE_CAPACITY_CONFIG, DEFAULT_HASHTABLE_CAPACITY);
- _log.info("Using capacity " + hashtableCapacity + " for hash tables");
- _metaDataMap = new ConcurrentHashMap<Long, MessageMetaData>(hashtableCapacity);
- _contentBodyMap = new ConcurrentHashMap<Long, List<ContentChunk>>(hashtableCapacity);
- }
+ public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQException
+ {
+ }
- public void close() throws Exception
- {
- _closed.getAndSet(true);
- if (_metaDataMap != null)
+ public void commitTran() throws AMQException
{
- _metaDataMap.clear();
- _metaDataMap = null;
}
- if (_contentBodyMap != null)
+
+ public StoreFuture commitTranAsync() throws AMQException
+ {
+ return IMMEDIATE_FUTURE;
+ }
+
+ public void abortTran() throws AMQException
{
- _contentBodyMap.clear();
- _contentBodyMap = null;
}
- super.close();
+ };
+
+ public void configureConfigStore(String name, ConfigurationRecoveryHandler handler, Configuration configuration, LogSubject logSubject) throws Exception
+ {
+ _logSubject = logSubject;
+ CurrentActor.get().message(_logSubject, ConfigStoreMessages.CFG_1001(this.getClass().getName()));
+
+
}
- public void removeMessage(StoreContext context, Long messageId) throws AMQException
+ public void configureMessageStore(String name,
+ MessageStoreRecoveryHandler recoveryHandler,
+ Configuration config,
+ LogSubject logSubject) throws Exception
{
- checkNotClosed();
- if (_log.isDebugEnabled())
+ if(_logSubject == null)
{
- _log.debug("Removing message with id " + messageId);
+ _logSubject = logSubject;
}
- _metaDataMap.remove(messageId);
- _contentBodyMap.remove(messageId);
+ int hashtableCapacity = config.getInt(name + "." + HASHTABLE_CAPACITY_CONFIG, DEFAULT_HASHTABLE_CAPACITY);
+ _log.info("Using capacity " + hashtableCapacity + " for hash tables");
+ CurrentActor.get().message(_logSubject, MessageStoreMessages.MST_1001(this.getClass().getName()));
+ }
+
+ public void close() throws Exception
+ {
+ _closed.getAndSet(true);
+ CurrentActor.get().message(_logSubject,MessageStoreMessages.MST_1003());
+
}
+ public StoredMessage addMessage(StorableMessageMetaData metaData)
+ {
+ final long id = _messageId.getAndIncrement();
+ StoredMemoryMessage message = new StoredMemoryMessage(id, metaData);
+
+ return message;
+ }
+
+
public void createExchange(Exchange exchange) throws AMQException
{
@@ -135,35 +157,19 @@ public class MemoryMessageStore extends AbstractMessageStore
// Not required to do anything
}
- public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
+ public void configureTransactionLog(String name,
+ TransactionLogRecoveryHandler recoveryHandler,
+ Configuration storeConfiguration,
+ LogSubject logSubject) throws Exception
{
- // Not required to do anything
+ //To change body of implemented methods use File | Settings | File Templates.
}
- public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
+ public Transaction newTransaction()
{
- // Not required to do anything
+ return IN_MEMORY_TRANSACTION;
}
- public void beginTran(StoreContext context) throws AMQException
- {
- // Not required to do anything
- }
-
- public void commitTran(StoreContext context) throws AMQException
- {
- // Not required to do anything
- }
-
- public void abortTran(StoreContext context) throws AMQException
- {
- // Not required to do anything
- }
-
- public boolean inTran(StoreContext context)
- {
- return false;
- }
public List<AMQQueue> createQueues() throws AMQException
{
@@ -175,48 +181,6 @@ public class MemoryMessageStore extends AbstractMessageStore
return _messageId.getAndIncrement();
}
- public void storeContentBodyChunk(StoreContext context, Long messageId, int index, ContentChunk contentBody, boolean lastContentBody)
- throws AMQException
- {
- checkNotClosed();
- List<ContentChunk> bodyList = _contentBodyMap.get(messageId);
-
- if (bodyList == null && lastContentBody)
- {
- _contentBodyMap.put(messageId, Collections.singletonList(contentBody));
- }
- else
- {
- if (bodyList == null)
- {
- bodyList = new ArrayList<ContentChunk>();
- _contentBodyMap.put(messageId, bodyList);
- }
-
- bodyList.add(index, contentBody);
- }
- }
-
- public void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData messageMetaData)
- throws AMQException
- {
- checkNotClosed();
- _metaDataMap.put(messageId, messageMetaData);
- }
-
- public MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException
- {
- checkNotClosed();
- return _metaDataMap.get(messageId);
- }
-
- public ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException
- {
- checkNotClosed();
- List<ContentChunk> bodyList = _contentBodyMap.get(messageId);
- return bodyList.get(index);
- }
-
public boolean isPersistent()
{
return false;
@@ -229,4 +193,6 @@ public class MemoryMessageStore extends AbstractMessageStore
throw new MessageStoreClosedException();
}
}
+
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java
new file mode 100755
index 0000000000..428bb1e41b
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import org.apache.qpid.server.message.MessageMetaData;
+import org.apache.qpid.server.message.MessageMetaData_0_10;
+
+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; } };
+
+
+ public static interface Factory<M extends StorableMessageMetaData>
+ {
+ M createMetaData(ByteBuffer buf);
+ }
+
+ abstract public Factory<? extends StorableMessageMetaData> getFactory();
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
index 5a1b54b298..e2fca2f9c7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
@@ -20,53 +20,43 @@
*/
package org.apache.qpid.server.store;
+import org.apache.qpid.server.logging.LogSubject;
import org.apache.commons.configuration.Configuration;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.queue.MessageMetaData;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
/**
- * MessageStore defines the interface to a storage area, which can be used to preserve the state of messages, queues
- * and exchanges in a transactional manner.
- *
- * <p/>All message store, remove, enqueue and dequeue operations are carried out against a {@link StoreContext} which
- * encapsulates the transactional context they are performed in. Many such operations can be carried out in a single
- * transaction.
+ * MessageStore defines the interface to a storage area, which can be used to preserve the state of messages.
*
- * <p/>The storage and removal of queues and exchanges, are not carried out in a transactional context.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Accept transaction boundary demarcations: Begin, Commit, Abort.
- * <tr><td> Store and remove queues.
- * <tr><td> Store and remove exchanges.
- * <tr><td> Store and remove messages.
- * <tr><td> Bind and unbind queues to exchanges.
- * <tr><td> Enqueue and dequeue messages to queues.
- * <tr><td> Generate message identifiers.
- * </table>
*/
-public interface MessageStore
+public interface MessageStore extends DurableConfigurationStore, TransactionLog
{
+ 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 virtualHost The virtual host using by this store
- * @param base The base element identifier from which all configuration items are relative. For example, if
- * the base element is "store", the all elements used by concrete classes will be "store.foo" etc.
- * @param hostConfig The apache commons configuration object.
+ * @param name The name to be used by this storem
+ * @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 configure(VirtualHost virtualHost, String base, VirtualHostConfiguration hostConfig) throws Exception;
+ void configureMessageStore(String name,
+ MessageStoreRecoveryHandler recoveryHandler,
+ Configuration config,
+ LogSubject logSubject) throws Exception;
/**
* Called to close and cleanup any resources used by the message store.
@@ -75,203 +65,16 @@ public interface MessageStore
*/
void close() throws Exception;
- /**
- * Removes the specified message from the store in the given transactional store context.
- *
- * @param storeContext The transactional context to remove the message in.
- * @param messageId Identifies the message to remove.
- *
- * @throws AMQException If the operation fails for any reason.
- */
- void removeMessage(StoreContext storeContext, Long messageId) throws AMQException;
-
- /**
- * Makes the specified exchange persistent.
- *
- * @param exchange The exchange to persist.
- *
- * @throws AMQException If the operation fails for any reason.
- */
- void createExchange(Exchange exchange) throws AMQException;
-
- /**
- * Removes the specified persistent exchange.
- *
- * @param exchange The exchange to remove.
- *
- * @throws AMQException If the operation fails for any reason.
- */
- void removeExchange(Exchange exchange) throws AMQException;
-
- /**
- * Binds the specified queue to an exchange with a routing key.
- *
- * @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.
- *
- * @throws AMQException If the operation fails for any reason.
- */
- void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException;
-
- /**
- * Unbinds the specified from an exchange under a particular routing key.
- *
- * @param exchange The exchange to unbind from.
- * @param routingKey The routing key to unbind.
- * @param queue The queue to unbind.
- * @param args Additonal parameters.
- *
- * @throws AMQException If the operation fails for any reason.
- */
- void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException;
- /**
- * Makes the specified queue persistent.
- *
- * @param queue The queue to store.
- *
- * @throws AMQException If the operation fails for any reason.
- */
- void createQueue(AMQQueue queue) throws AMQException;
+ public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(T metaData);
- /**
- * Makes the specified queue persistent.
- *
- * @param queue The queue to store.
- *
- * @param arguments The additional arguments to the binding
- * @throws AMQException If the operation fails for any reason.
- */
- void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException;
-
- /**
- * Removes the specified queue from the persistent store.
- *
- * @param queue The queue to remove.
- * @throws AMQException If the operation fails for any reason.
- */
- void removeQueue(final AMQQueue queue) throws AMQException;
-
- /**
- * Places a message onto a specified queue, in a given transactional context.
- *
- * @param context The transactional context for the operation.
- * @param queue The queue to place the message on.
- * @param messageId The message to enqueue.
- * @throws AMQException If the operation fails for any reason.
- */
- void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException;
-
- /**
- * Extracts a message from a specified queue, in a given transactional context.
- *
- * @param context The transactional context for the operation.
- * @param queue The queue to place the message on.
- * @param messageId The message to dequeue.
- * @throws AMQException If the operation fails for any reason, or if the specified message does not exist.
- */
- void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException;
-
- /**
- * Begins a transactional context.
- *
- * @param context The transactional context to begin.
- *
- * @throws AMQException If the operation fails for any reason.
- */
- void beginTran(StoreContext context) throws AMQException;
-
- /**
- * Commits all operations performed within a given transactional context.
- *
- * @param context The transactional context to commit all operations for.
- *
- * @throws AMQException If the operation fails for any reason.
- */
- void commitTran(StoreContext context) throws AMQException;
-
- /**
- * Abandons all operations performed within a given transactional context.
- *
- * @param context The transactional context to abandon.
- *
- * @throws AMQException If the operation fails for any reason.
- */
- void abortTran(StoreContext context) throws AMQException;
-
- /**
- * Tests a transactional context to see if it has been begun but not yet committed or aborted.
- *
- * @param context The transactional context to test.
- *
- * @return <tt>true</tt> if the transactional context is live, <tt>false</tt> otherwise.
- */
- boolean inTran(StoreContext context);
-
- /**
- * Return a valid, currently unused message id.
- *
- * @return A fresh message id.
- */
- Long getNewMessageId();
-
- /**
- * Stores a chunk of message data.
- *
- * @param context The transactional context for the operation.
- * @param messageId The message to store the data for.
- * @param index The index of the data chunk.
- * @param contentBody The content of the data chunk.
- * @param lastContentBody Flag to indicate that this is the last such chunk for the message.
- *
- * @throws AMQException If the operation fails for any reason, or if the specified message does not exist.
- */
- void storeContentBodyChunk(StoreContext context, Long messageId, int index, ContentChunk contentBody,
- boolean lastContentBody) throws AMQException;
-
- /**
- * Stores message meta-data.
- *
- * @param context The transactional context for the operation.
- * @param messageId The message to store the data for.
- * @param messageMetaData The message meta data to store.
- *
- * @throws AMQException If the operation fails for any reason, or if the specified message does not exist.
- */
- void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData messageMetaData) throws AMQException;
-
- /**
- * Retrieves message meta-data.
- *
- * @param context The transactional context for the operation.
- * @param messageId The message to get the meta-data for.
- *
- * @return The message meta data.
- *
- * @throws AMQException If the operation fails for any reason, or if the specified message does not exist.
- */
- MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException;
-
- /**
- * Retrieves a chunk of message data.
- *
- * @param context The transactional context for the operation.
- * @param messageId The message to get the data chunk for.
- * @param index The offset index of the data chunk within the message.
- *
- * @return A chunk of message data.
- *
- * @throws AMQException If the operation fails for any reason, or if the specified message does not exist.
- */
- ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException;
/**
* Is this store capable of persisting the data
- *
+ *
* @return true if this store is capable of persisting data
*/
boolean isPersistent();
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreRecoveryHandler.java
new file mode 100755
index 0000000000..ba65b8e1ec
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreRecoveryHandler.java
@@ -0,0 +1,33 @@
+/*
+*
+* 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 MessageStoreRecoveryHandler
+{
+ StoredMessageRecoveryHandler begin();
+
+ public static interface StoredMessageRecoveryHandler
+ {
+ void message(StoredMessage message);
+
+ void completeMessageRecovery();
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java
new file mode 100755
index 0000000000..12d2a6a6c7
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java
@@ -0,0 +1,36 @@
+/*
+ *
+ * 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;
+
+public interface StorableMessageMetaData
+{
+ MessageMetaDataType getType();
+
+ int getStorableSize();
+
+ int writeToBuffer(int offsetInMetaData, ByteBuffer dest);
+
+ int getContentSize();
+
+ boolean isPersistent();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java
index fdb56a1a55..88cc68bc71 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java
@@ -35,6 +35,7 @@ public class StoreContext
private String _name;
private Object _payload;
+
public StoreContext()
{
_name = "StoreContext";
@@ -68,4 +69,5 @@ public class StoreContext
{
return "<_name = " + _name + ", _payload = " + _payload + ">";
}
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java
new file mode 100755
index 0000000000..867fb4f9c7
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMemoryMessage.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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;
+
+public class StoredMemoryMessage implements StoredMessage
+{
+ private final long _messageNumber;
+ private final ByteBuffer _content;
+ private final StorableMessageMetaData _metaData;
+
+ StoredMemoryMessage(long messageNumber, StorableMessageMetaData metaData)
+ {
+ _messageNumber = messageNumber;
+ _metaData = metaData;
+ _content = ByteBuffer.allocate(metaData.getContentSize());
+
+ }
+
+ public long getMessageNumber()
+ {
+ return _messageNumber;
+ }
+
+ public void addContent(int offsetInMessage, ByteBuffer src)
+ {
+ src = src.duplicate();
+ ByteBuffer dst = _content.duplicate();
+ dst.position(offsetInMessage);
+ dst.put(src);
+ }
+
+ public int getContent(int offset, ByteBuffer dst)
+ {
+ ByteBuffer src = _content.duplicate();
+ src.position(offset);
+ src = src.slice();
+ if(dst.remaining() < src.limit())
+ {
+ src.limit(dst.remaining());
+ }
+ dst.put(src);
+ return src.limit();
+ }
+
+ public TransactionLog.StoreFuture flushToStore()
+ {
+ return MessageStore.IMMEDIATE_FUTURE;
+ }
+
+
+ public StorableMessageMetaData getMetaData()
+ {
+ return _metaData;
+ }
+
+ public void remove()
+ {
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.java
new file mode 100755
index 0000000000..0bc45c6718
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StoredMessage.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;
+
+import java.nio.ByteBuffer;
+
+public interface StoredMessage<M extends StorableMessageMetaData>
+{
+ M getMetaData();
+
+ public long getMessageNumber();
+
+ void addContent(int offsetInMessage, ByteBuffer src);
+
+ int getContent(int offsetInMessage, ByteBuffer dst);
+
+ TransactionLog.StoreFuture flushToStore();
+
+ void remove();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java
new file mode 100755
index 0000000000..e6a33e23d6
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLog.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.queue.AMQQueue;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.AMQException;
+import org.apache.commons.configuration.Configuration;
+
+public interface TransactionLog
+{
+
+ 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 messageId The message to enqueue.
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQException;
+
+ /**
+ * Extracts a message from a specified queue, in a given transactional context.
+ *
+ * @param queue The queue to place the message on.
+ * @param messageId The message to dequeue.
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason, or if the specified message does not exist.
+ */
+ void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQException;
+
+
+ /**
+ * Commits all operations performed within a given transactional context.
+ *
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void commitTran() throws AMQException;
+
+ /**
+ * Commits all operations performed within a given transactional context.
+ *
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ StoreFuture commitTranAsync() throws AMQException;
+
+ /**
+ * Abandons all operations performed within a given transactional context.
+ *
+ * @throws org.apache.qpid.AMQException If the operation fails for any reason.
+ */
+ void abortTran() throws AMQException;
+
+
+
+ }
+
+ public void configureTransactionLog(String name,
+ TransactionLogRecoveryHandler recoveryHandler,
+ Configuration storeConfiguration,
+ LogSubject logSubject) throws Exception;
+
+ Transaction newTransaction();
+
+
+
+ public static interface StoreFuture
+ {
+ boolean isComplete();
+
+ void waitForCompletion();
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java
new file mode 100755
index 0000000000..7781c52df3
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogRecoveryHandler.java
@@ -0,0 +1,33 @@
+/*
+*
+* 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 TransactionLogRecoveryHandler
+{
+ QueueEntryRecoveryHandler begin(TransactionLog log);
+
+ public static interface QueueEntryRecoveryHandler
+ {
+ void queueEntry(String queuename, long messageId);
+
+ void completeQueueEntryRecovery();
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.java
new file mode 100755
index 0000000000..0d81dd151d
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/TransactionLogResource.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.store;
+
+public interface TransactionLogResource
+{
+ public String getResourceName();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java
new file mode 100755
index 0000000000..b49b12fb79
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java
@@ -0,0 +1,93 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.subscription;
+
+import org.apache.qpid.server.transport.ServerSession;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.log4j.Logger;
+
+
+class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener
+{
+ private static final Logger _logger = Logger.getLogger(ExplicitAcceptDispositionChangeListener.class);
+
+
+ private final QueueEntry _entry;
+ private final Subscription_0_10 _sub;
+
+ public ExplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10)
+ {
+ _entry = entry;
+ _sub = subscription_0_10;
+ }
+
+ public void onAccept()
+ {
+ final Subscription_0_10 subscription = getSubscription();
+ if(subscription != null && _entry.isAcquiredBy(_sub))
+ {
+ subscription.getSession().acknowledge(subscription, _entry);
+ }
+ else
+ {
+ _logger.warn("MessageAccept received for message which has not been acquired (likely client error)");
+ }
+
+ }
+
+ public void onRelease()
+ {
+ final Subscription_0_10 subscription = getSubscription();
+ if(subscription != null && _entry.isAcquiredBy(_sub))
+ {
+ subscription.release(_entry);
+ }
+ else
+ {
+ _logger.warn("MessageRelease received for message which has not been acquired (likely client error)");
+ }
+ }
+
+ public void onReject()
+ {
+ final Subscription_0_10 subscription = getSubscription();
+ if(subscription != null && _entry.isAcquiredBy(_sub))
+ {
+ subscription.reject(_entry);
+ }
+ else
+ {
+ _logger.warn("MessageReject received for message which has not been acquired (likely client error)");
+ }
+
+ }
+
+ public boolean acquire()
+ {
+ return _entry.acquire(getSubscription());
+ }
+
+
+ private Subscription_0_10 getSubscription()
+ {
+ return _sub;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java
new file mode 100755
index 0000000000..b5bb2014b5
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java
@@ -0,0 +1,86 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.subscription;
+
+import org.apache.qpid.server.transport.ServerSession;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.log4j.Logger;
+
+class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener
+{
+ private static final Logger _logger = Logger.getLogger(ImplicitAcceptDispositionChangeListener.class);
+
+
+ private final QueueEntry _entry;
+ private Subscription_0_10 _sub;
+
+ public ImplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10)
+ {
+ _entry = entry;
+ _sub = subscription_0_10;
+ }
+
+ public void onAccept()
+ {
+ _logger.warn("MessageAccept received for message which is using NONE as the accept mode (likely client error)");
+ }
+
+ public void onRelease()
+ {
+ if(_entry.isAcquiredBy(_sub))
+ {
+ getSubscription().release(_entry);
+ }
+ else
+ {
+ _logger.warn("MessageRelease received for message which has not been acquired (likely client error)");
+ }
+ }
+
+ public void onReject()
+ {
+ if(_entry.isAcquiredBy(_sub))
+ {
+ getSubscription().reject(_entry);
+ }
+ else
+ {
+ _logger.warn("MessageReject received for message which has not been acquired (likely client error)");
+ }
+
+ }
+
+ public boolean acquire()
+ {
+ boolean acquired = _entry.acquire(getSubscription());
+ //TODO - why acknowledge here??? seems bizarre...
+ // getSubscription().getSession().acknowledge(getSubscription(), _entry);
+ return acquired;
+
+ }
+
+ public Subscription_0_10 getSubscription()
+ {
+ return _sub;
+ }
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java
new file mode 100755
index 0000000000..8a2a370236
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.subscription;
+
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.transport.ServerSession;
+import org.apache.qpid.transport.Method;
+
+public class MessageAcceptCompletionListener implements Method.CompletionListener
+{
+ private final Subscription_0_10 _sub;
+ private final QueueEntry _entry;
+ private final ServerSession _session;
+ private boolean _restoreCredit;
+
+ public MessageAcceptCompletionListener(Subscription_0_10 sub, ServerSession session, QueueEntry entry, boolean restoreCredit)
+ {
+ super();
+ _sub = sub;
+ _entry = entry;
+ _session = session;
+ _restoreCredit = restoreCredit;
+ }
+
+ public void onComplete(Method method)
+ {
+ if(_restoreCredit)
+ {
+ _sub.restoreCredit(_entry);
+ }
+ if(_entry.isAcquiredBy(_sub))
+ {
+ _session.acknowledge(_sub, _entry);
+ }
+
+ _session.removeDispositionListener(method);
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
index c9042325bf..4db9c305b2 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
@@ -46,10 +46,12 @@ public interface Subscription
AMQQueue getQueue();
QueueEntry.SubscriptionAcquiredState getOwningState();
+ QueueEntry.SubscriptionAssignedState getAssignedState();
+
void setQueue(AMQQueue queue, boolean exclusive);
- AMQChannel getChannel();
+ void setNoLocal(boolean noLocal);
AMQShortString getConsumerTag();
@@ -63,23 +65,24 @@ public interface Subscription
boolean isClosed();
- boolean isBrowser();
+ boolean acquires();
- void close();
+ boolean seesRequeues();
- boolean filtersMessages();
+ void close();
void send(QueueEntry msg) throws AMQException;
- void queueDeleted(AMQQueue queue);
+ void queueDeleted(AMQQueue queue);
boolean wouldSuspend(QueueEntry msg);
void getSendLock();
+
void releaseSendLock();
- void resend(final QueueEntry entry) throws AMQException;
+ void onDequeue(final QueueEntry queueEntry);
void restoreCredit(final QueueEntry queueEntry);
@@ -87,13 +90,17 @@ public interface Subscription
public State getState();
- QueueEntry getLastSeenEntry();
+ AMQQueue.Context getQueueContext();
- boolean setLastSeenEntry(QueueEntry expected, QueueEntry newValue);
+ void setQueueContext(AMQQueue.Context queueContext);
boolean isActive();
+ void confirmAutoClose();
+
+ public void set(String key, Object value);
+ public Object get(String key);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
index 2893e916cc..bb2e5ae918 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
@@ -25,6 +25,8 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Map;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
@@ -33,6 +35,8 @@ import org.apache.qpid.common.ClientProperties;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.SubscriptionActor;
import org.apache.qpid.server.logging.messages.SubscriptionMessages;
@@ -45,7 +49,6 @@ import org.apache.qpid.server.flow.FlowCreditManager;
import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.filter.FilterManagerFactory;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.store.StoreContext;
/**
* Encapsulation of a supscription to a queue. <p/> Ties together the protocol session of a subscriber, the consumer tag
@@ -65,11 +68,16 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE);
- private final AtomicReference<QueueEntry> _queueContext = new AtomicReference<QueueEntry>(null);
+ private AMQQueue.Context _queueContext;
+
private final ClientDeliveryMethod _deliveryMethod;
private final RecordDeliveryMethod _recordMethod;
- private QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
+ private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
+ private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this);
+
+ private final Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
+
private final Lock _stateChangeLock;
private static final AtomicLong idGenerator = new AtomicLong(0);
@@ -78,6 +86,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
private LogSubject _logSubject;
private LogActor _logActor;
+
static final class BrowserSubscription extends SubscriptionImpl
{
public BrowserSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
@@ -153,38 +162,28 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
@Override
public void send(QueueEntry entry) throws AMQException
{
+ // if we do not need to wait for client acknowledgements
+ // we can decrement the reference count immediately.
- StoreContext storeContext = getChannel().getStoreContext();
- try
- { // if we do not need to wait for client acknowledgements
- // we can decrement the reference count immediately.
-
- // By doing this _before_ the send we ensure that it
- // doesn't get sent if it can't be dequeued, preventing
- // duplicate delivery on recovery.
+ // By doing this _before_ the send we ensure that it
+ // doesn't get sent if it can't be dequeued, preventing
+ // duplicate delivery on recovery.
- // The send may of course still fail, in which case, as
- // the message is unacked, it will be lost.
- entry.dequeue(storeContext);
+ // The send may of course still fail, in which case, as
+ // the message is unacked, it will be lost.
+ entry.dequeue();
- synchronized (getChannel())
- {
- long deliveryTag = getChannel().getNextDeliveryTag();
+ synchronized (getChannel())
+ {
+ long deliveryTag = getChannel().getNextDeliveryTag();
- sendToClient(entry, deliveryTag);
+ sendToClient(entry, deliveryTag);
- }
- entry.dispose(storeContext);
}
- finally
- {
- //Only set delivered if it actually was writen successfully..
- // using a try->finally would set it even if an error occured.
- // Is this what we want?
+ entry.dispose();
+
- entry.setDeliveredToSubscription();
- }
}
@Override
@@ -225,39 +224,30 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
public void send(QueueEntry entry) throws AMQException
{
- try
- { // if we do not need to wait for client acknowledgements
- // we can decrement the reference count immediately.
+ // if we do not need to wait for client acknowledgements
+ // we can decrement the reference count immediately.
- // By doing this _before_ the send we ensure that it
- // doesn't get sent if it can't be dequeued, preventing
- // duplicate delivery on recovery.
+ // By doing this _before_ the send we ensure that it
+ // doesn't get sent if it can't be dequeued, preventing
+ // duplicate delivery on recovery.
- // The send may of course still fail, in which case, as
- // the message is unacked, it will be lost.
+ // The send may of course still fail, in which case, as
+ // the message is unacked, it will be lost.
- synchronized (getChannel())
- {
- long deliveryTag = getChannel().getNextDeliveryTag();
+ synchronized (getChannel())
+ {
+ long deliveryTag = getChannel().getNextDeliveryTag();
- recordMessageDelivery(entry, deliveryTag);
- sendToClient(entry, deliveryTag);
+ recordMessageDelivery(entry, deliveryTag);
+ sendToClient(entry, deliveryTag);
- }
- }
- finally
- {
- //Only set delivered if it actually was writen successfully..
- // using a try->finally would set it even if an error occured.
- // Is this what we want?
-
- entry.setDeliveredToSubscription();
}
}
+
}
@@ -268,7 +258,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
private final AMQShortString _consumerTag;
- private final boolean _noLocal;
+ private boolean _noLocal;
private final FlowCreditManager _creditManager;
@@ -423,43 +413,35 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
public boolean hasInterest(QueueEntry entry)
{
+
+
+
+
//check that the message hasn't been rejected
if (entry.isRejectedBy(this))
{
if (_logger.isDebugEnabled())
{
- _logger.debug("Subscription:" + debugIdentity() + " rejected message:" + entry.debugIdentity());
+ _logger.debug("Subscription:" + this + " rejected message:" + entry);
}
// return false;
}
if (_noLocal)
{
- //todo - client id should be recoreded so we don't have to handle
+
+ AMQMessage message = (AMQMessage) entry.getMessage();
+
+ //todo - client id should be recorded so we don't have to handle
// the case where this is null.
- final Object publisherId = entry.getMessage().getPublisherClientInstance();
+ final Object publisher = message.getPublisherIdentifier();
// We don't want local messages so check to see if message is one we sent
- Object localInstance;
+ Object localInstance = getProtocolSession();
- if (publisherId != null && (getProtocolSession().getClientProperties() != null) &&
- (localInstance = getProtocolSession().getClientProperties().getObject(CLIENT_PROPERTIES_INSTANCE)) != null)
+ if(publisher.equals(localInstance))
{
- if(publisherId.equals(localInstance))
- {
- return false;
- }
- }
- else
- {
-
- localInstance = getProtocolSession().getClientIdentifier();
-
- //todo - client id should be recoreded so we don't have to do the null check
- if (localInstance != null && localInstance.equals(entry.getMessage().getPublisherIdentifier()))
- {
- return false;
- }
+ return false;
}
@@ -468,7 +450,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
if (_logger.isDebugEnabled())
{
- _logger.debug("(" + debugIdentity() + ") checking filters for message (" + entry.debugIdentity());
+ _logger.debug("(" + this + ") checking filters for message (" + entry);
}
return checkFilters(entry);
@@ -483,7 +465,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
private boolean checkFilters(QueueEntry msg)
{
- return (_filters == null) || _filters.allAllow(msg.getMessage());
+ return (_filters == null) || _filters.allAllow(msg);
}
public boolean isAutoClose()
@@ -550,11 +532,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
_stateChangeLock.unlock();
}
- public void resend(final QueueEntry entry) throws AMQException
- {
- _queue.resend(entry, this);
- }
-
public AMQChannel getChannel()
{
return _channel;
@@ -585,12 +562,18 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
return _queue;
}
+ public void onDequeue(final QueueEntry queueEntry)
+ {
+ restoreCredit(queueEntry);
+ }
+
public void restoreCredit(final QueueEntry queueEntry)
{
- _creditManager.addCredit(1, queueEntry.getSize());
+ _creditManager.restoreCredit(1, queueEntry.getSize());
}
+
public void creditStateChanged(boolean hasCredit)
{
@@ -628,22 +611,14 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
}
- public QueueEntry getLastSeenEntry()
+ public AMQQueue.Context getQueueContext()
{
- QueueEntry entry = _queueContext.get();
-
- if(_logger.isDebugEnabled())
- {
- _logger.debug(_logActor + ": lastSeenEntry: " + (entry == null ? "null" : entry.debugIdentity()));
- }
-
- return entry;
+ return _queueContext;
}
- public boolean setLastSeenEntry(QueueEntry expected, QueueEntry newvalue)
+ public void setQueueContext(AMQQueue.Context context)
{
- _logger.debug(debugIdentity() + " Setting Last Seen To:" + (newvalue == null ? "nullNV" : newvalue.debugIdentity()));
- return _queueContext.compareAndSet(expected,newvalue);
+ _queueContext = context;
}
@@ -670,4 +645,43 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
return _owningState;
}
+ public QueueEntry.SubscriptionAssignedState getAssignedState()
+ {
+ return _assignedState;
+ }
+
+
+ public void confirmAutoClose()
+ {
+ ProtocolOutputConverter converter = getChannel().getProtocolSession().getProtocolOutputConverter();
+ converter.confirmConsumerAutoClose(getChannel().getChannelId(), getConsumerTag());
+ }
+
+ public boolean acquires()
+ {
+ return !isBrowser();
+ }
+
+ public boolean seesRequeues()
+ {
+ return !isBrowser();
+ }
+
+ public void set(String key, Object value)
+ {
+ _properties.put(key, value);
+ }
+
+ public Object get(String key)
+ {
+ return _properties.get(key);
+ }
+
+
+ public void setNoLocal(boolean noLocal)
+ {
+ _noLocal = noLocal;
+ }
+
+ abstract boolean isBrowser();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
new file mode 100644
index 0000000000..fb0a5cf2c7
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
@@ -0,0 +1,658 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.subscription;
+
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.flow.CreditCreditManager;
+import org.apache.qpid.server.flow.WindowCreditManager;
+import org.apache.qpid.server.flow.FlowCreditManager_0_10;
+import org.apache.qpid.server.filter.FilterManager;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.SubscriptionActor;
+import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.MessageTransferMessage;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.transport.ServerSession;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ContentHeaderProperties;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.AMQTypedValue;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.transport.*;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.nio.ByteBuffer;
+
+public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener
+{
+
+ private static final AtomicLong idGenerator = new AtomicLong(0);
+ // Create a simple ID that increments for ever new Subscription
+ private final long _subscriptionID = idGenerator.getAndIncrement();
+
+ private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
+ private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this);
+
+ private final Lock _stateChangeLock = new ReentrantLock();
+
+ private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE);
+ private AMQQueue.Context _queueContext;
+ private final AtomicBoolean _deleted = new AtomicBoolean(false);
+
+
+ private FlowCreditManager_0_10 _creditManager;
+
+
+ private StateListener _stateListener = new StateListener()
+ {
+
+ public void stateChange(Subscription sub, State oldState, State newState)
+ {
+
+ }
+ };
+ private AMQQueue _queue;
+ private final String _destination;
+ private boolean _noLocal;
+ private final FilterManager _filters;
+ private final MessageAcceptMode _acceptMode;
+ private final MessageAcquireMode _acquireMode;
+ private MessageFlowMode _flowMode;
+ private final ServerSession _session;
+ private AtomicBoolean _stopped = new AtomicBoolean(true);
+ private ConcurrentHashMap<Integer, QueueEntry> _sentMap = new ConcurrentHashMap<Integer, QueueEntry>();
+ private static final Struct[] EMPTY_STRUCT_ARRAY = new Struct[0];
+
+ private LogSubject _logSubject;
+ private LogActor _logActor;
+ private Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
+
+
+ public Subscription_0_10(ServerSession session, String destination, MessageAcceptMode acceptMode,
+ MessageAcquireMode acquireMode,
+ MessageFlowMode flowMode,
+ FlowCreditManager_0_10 creditManager,
+ FilterManager filters)
+ {
+ _session = session;
+ _destination = destination;
+ _acceptMode = acceptMode;
+ _acquireMode = acquireMode;
+ _creditManager = creditManager;
+ _flowMode = flowMode;
+ _filters = filters;
+ _creditManager.addStateListener(this);
+ _state.set(_creditManager.hasCredit() ? State.ACTIVE : State.SUSPENDED);
+
+
+ }
+
+ public void setNoLocal(boolean noLocal)
+ {
+ _noLocal = noLocal;
+ }
+
+ public AMQQueue getQueue()
+ {
+ return _queue;
+ }
+
+ public QueueEntry.SubscriptionAcquiredState getOwningState()
+ {
+ return _owningState;
+ }
+
+ public QueueEntry.SubscriptionAssignedState getAssignedState()
+ {
+ return _assignedState;
+ }
+
+ public void setQueue(AMQQueue queue, boolean exclusive)
+ {
+ if(getQueue() != null)
+ {
+ throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue());
+ }
+ _queue = queue;
+ _logSubject = new SubscriptionLogSubject(this);
+ _logActor = new SubscriptionActor(CurrentActor.get().getRootMessageLogger(), this);
+
+ }
+
+ public AMQShortString getConsumerTag()
+ {
+ return new AMQShortString(_destination);
+ }
+
+ public boolean isSuspended()
+ {
+ return !isActive() || _deleted.get(); // TODO check for Session suspension
+ }
+
+ public boolean hasInterest(QueueEntry entry)
+ {
+
+
+
+ //check that the message hasn't been rejected
+ if (entry.isRejectedBy(this))
+ {
+
+ return false;
+ }
+
+
+
+ if (_noLocal
+ && (entry.getMessage() instanceof MessageTransferMessage)
+ && ((MessageTransferMessage)entry.getMessage()).getSession() == _session)
+ {
+ return false;
+ }
+
+
+ return checkFilters(entry);
+
+
+ }
+
+ private boolean checkFilters(QueueEntry entry)
+ {
+ return (_filters == null) || _filters.allAllow(entry);
+ }
+
+ public boolean isAutoClose()
+ {
+ // no such thing in 0-10
+ return false;
+ }
+
+ public boolean isClosed()
+ {
+ return getState() == State.CLOSED;
+ }
+
+ public boolean isBrowser()
+ {
+ return _acquireMode == MessageAcquireMode.NOT_ACQUIRED;
+ }
+
+ public boolean seesRequeues()
+ {
+ return _acquireMode != MessageAcquireMode.NOT_ACQUIRED || _acceptMode == MessageAcceptMode.EXPLICIT;
+ }
+
+ public void close()
+ {
+ boolean closed = false;
+ State state = getState();
+
+ _stateChangeLock.lock();
+ try
+ {
+ while(!closed && state != State.CLOSED)
+ {
+ closed = _state.compareAndSet(state, State.CLOSED);
+ if(!closed)
+ {
+ state = getState();
+ }
+ else
+ {
+ _stateListener.stateChange(this,state, State.CLOSED);
+ }
+ }
+ _creditManager.removeListener(this);
+ }
+ finally
+ {
+ _stateChangeLock.unlock();
+ }
+
+
+
+ }
+
+ public void creditStateChanged(boolean hasCredit)
+ {
+
+ if(hasCredit)
+ {
+ if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE))
+ {
+ _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE);
+ }
+ else
+ {
+ // this is a hack to get round the issue of increasing bytes credit
+ _stateListener.stateChange(this, State.ACTIVE, State.ACTIVE);
+ }
+ }
+ else
+ {
+ if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
+ {
+ _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
+ }
+ }
+ }
+
+
+ private class AddMessageDispositionListnerAction implements Runnable
+ {
+ public MessageTransfer _xfr;
+ public ServerSession.MessageDispositionChangeListener _action;
+
+ public void run()
+ {
+ _session.onMessageDispositionChange(_xfr, _action);
+ }
+ }
+
+ private final AddMessageDispositionListnerAction _postIdSettingAction = new AddMessageDispositionListnerAction();
+
+ public void send(final QueueEntry entry) throws AMQException
+ {
+ ServerMessage serverMsg = entry.getMessage();
+
+
+ MessageTransfer xfr;
+
+ if(serverMsg instanceof MessageTransferMessage)
+ {
+
+ MessageTransferMessage msg = (MessageTransferMessage) serverMsg;
+
+
+ Struct[] headers;
+ if(msg.getHeader() == null)
+ {
+ headers = EMPTY_STRUCT_ARRAY;
+ }
+ else
+ {
+ headers = msg.getHeader().getStructs();
+ }
+
+ ArrayList<Struct> newHeaders = new ArrayList<Struct>(headers.length);
+ DeliveryProperties origDeliveryProps = null;
+ for(Struct header : headers)
+ {
+ if(header instanceof DeliveryProperties)
+ {
+ origDeliveryProps = (DeliveryProperties) header;
+ }
+ else
+ {
+ newHeaders.add(header);
+ }
+ }
+
+ DeliveryProperties deliveryProps = new DeliveryProperties();
+ if(origDeliveryProps != null)
+ {
+ if(origDeliveryProps.hasDeliveryMode())
+ {
+ deliveryProps.setDeliveryMode(origDeliveryProps.getDeliveryMode());
+ }
+ if(origDeliveryProps.hasExchange())
+ {
+ deliveryProps.setExchange(origDeliveryProps.getExchange());
+ }
+ if(origDeliveryProps.hasExpiration())
+ {
+ deliveryProps.setExpiration(origDeliveryProps.getExpiration());
+ }
+ if(origDeliveryProps.hasPriority())
+ {
+ deliveryProps.setPriority(origDeliveryProps.getPriority());
+ }
+ if(origDeliveryProps.hasRoutingKey())
+ {
+ deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey());
+ }
+
+ }
+
+ deliveryProps.setRedelivered(entry.isRedelivered());
+
+ newHeaders.add(deliveryProps);
+ Header header = new Header(newHeaders);
+
+ xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody());
+ }
+ else
+ {
+ AMQMessage message_0_8 = (AMQMessage) serverMsg;
+ DeliveryProperties deliveryProps = new DeliveryProperties();
+ MessageProperties messageProps = new MessageProperties();
+
+ int size = (int) message_0_8.getSize();
+ ByteBuffer body = ByteBuffer.allocate(size);
+ message_0_8.getContent(body, 0);
+ body.flip();
+
+ Struct[] headers = new Struct[] { deliveryProps, messageProps };
+
+ BasicContentHeaderProperties properties =
+ (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().properties;
+ final AMQShortString exchange = message_0_8.getMessagePublishInfo().getExchange();
+ if(exchange != null)
+ {
+ deliveryProps.setExchange(exchange.toString());
+ }
+ deliveryProps.setExpiration(message_0_8.getExpiration());
+ deliveryProps.setImmediate(message_0_8.isImmediate());
+ deliveryProps.setPriority(MessageDeliveryPriority.get(properties.getPriority()));
+ deliveryProps.setRedelivered(entry.isRedelivered());
+ deliveryProps.setRoutingKey(message_0_8.getRoutingKey());
+ deliveryProps.setTimestamp(properties.getTimestamp());
+
+ messageProps.setContentEncoding(properties.getEncodingAsString());
+ messageProps.setContentLength(size);
+ if(properties.getAppId() != null)
+ {
+ messageProps.setAppId(properties.getAppId().getBytes());
+ }
+ messageProps.setContentType(properties.getContentTypeAsString());
+ if(properties.getCorrelationId() != null)
+ {
+ messageProps.setCorrelationId(properties.getCorrelationId().getBytes());
+ }
+
+ // TODO - ReplyTo
+
+ if(properties.getUserId() != null)
+ {
+ messageProps.setUserId(properties.getUserId().getBytes());
+ }
+
+ final Map<String, Object> appHeaders = new HashMap<String, Object>();
+
+ properties.getHeaders().processOverElements(
+ new FieldTable.FieldTableElementProcessor()
+ {
+
+ public boolean processElement(String propertyName, AMQTypedValue value)
+ {
+ Object val = value.getValue();
+ if(val instanceof AMQShortString)
+ {
+ val = val.toString();
+ }
+ appHeaders.put(propertyName, val);
+ return true;
+ }
+
+ public Object getResult()
+ {
+ return appHeaders;
+ }
+ });
+
+
+ messageProps.setApplicationHeaders(appHeaders);
+
+ Header header = new Header(headers);
+ xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body);
+ }
+
+ if(_acceptMode == MessageAcceptMode.NONE)
+ {
+ xfr.setCompletionListener(new MessageAcceptCompletionListener(this, _session, entry, _flowMode == MessageFlowMode.WINDOW));
+ }
+ else if(_flowMode == MessageFlowMode.WINDOW)
+ {
+ xfr.setCompletionListener(new Method.CompletionListener()
+ {
+ public void onComplete(Method method)
+ {
+ restoreCredit(entry);
+ }
+ });
+ }
+
+
+ _postIdSettingAction._xfr = xfr;
+ if(_acceptMode == MessageAcceptMode.EXPLICIT)
+ {
+ _postIdSettingAction._action = new ExplicitAcceptDispositionChangeListener(entry, this);
+ }
+ else
+ {
+ _postIdSettingAction._action = new ImplicitAcceptDispositionChangeListener(entry, this);
+ }
+
+ _session.sendMessage(xfr, _postIdSettingAction);
+
+ }
+
+ void reject(QueueEntry entry)
+ {
+ entry.setRedelivered();
+ entry.routeToAlternate();
+
+ }
+
+ void release(QueueEntry entry)
+ {
+ entry.setRedelivered();
+ entry.release();
+ }
+
+ public void queueDeleted(AMQQueue queue)
+ {
+ _deleted.set(true);
+ }
+
+ public boolean wouldSuspend(QueueEntry msg)
+ {
+ return !_creditManager.useCreditForMessage(msg.getMessage());
+ }
+
+ public void getSendLock()
+ {
+ _stateChangeLock.lock();
+ }
+
+ public void releaseSendLock()
+ {
+ _stateChangeLock.unlock();
+ }
+
+ public void restoreCredit(QueueEntry queueEntry)
+ {
+ _creditManager.restoreCredit(1, queueEntry.getSize());
+ }
+
+ public void onDequeue(QueueEntry queueEntry)
+ {
+
+ }
+
+ public void setStateListener(StateListener listener)
+ {
+ _stateListener = listener;
+ }
+
+ public State getState()
+ {
+ return _state.get();
+ }
+
+ public AMQQueue.Context getQueueContext()
+ {
+ return _queueContext;
+ }
+
+ public void setQueueContext(AMQQueue.Context queueContext)
+ {
+ _queueContext = queueContext;
+ }
+
+ public boolean isActive()
+ {
+ return getState() == State.ACTIVE;
+ }
+
+ public void confirmAutoClose()
+ {
+ //No such thing in 0-10
+ }
+
+ public void set(String key, Object value)
+ {
+ _properties.put(key, value);
+ }
+
+ public Object get(String key)
+ {
+ return _properties.get(key);
+ }
+
+
+ public FlowCreditManager_0_10 getCreditManager()
+ {
+ return _creditManager;
+ }
+
+
+ public void stop()
+ {
+ if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
+ {
+ _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
+ }
+ _stopped.set(true);
+ FlowCreditManager_0_10 creditManager = getCreditManager();
+ creditManager.clearCredit();
+ }
+
+ public void addCredit(MessageCreditUnit unit, long value)
+ {
+ FlowCreditManager_0_10 creditManager = getCreditManager();
+
+ switch (unit)
+ {
+ case MESSAGE:
+
+ creditManager.addCredit(value, 0L);
+ break;
+ case BYTE:
+ creditManager.addCredit(0l, value);
+ break;
+ }
+
+ _stopped.set(false);
+
+ if(creditManager.hasCredit())
+ {
+ if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE))
+ {
+ _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE);
+ }
+ }
+
+ }
+
+ public void setFlowMode(MessageFlowMode flowMode)
+ {
+
+
+ _creditManager.removeListener(this);
+
+ switch(flowMode)
+ {
+ case CREDIT:
+ _creditManager = new CreditCreditManager(0l,0l);
+ break;
+ case WINDOW:
+ _creditManager = new WindowCreditManager(0l,0l);
+ break;
+ default:
+ throw new RuntimeException("Unknown message flow mode: " + flowMode);
+ }
+ _flowMode = flowMode;
+ if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
+ {
+ _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
+ }
+
+ _creditManager.addStateListener(this);
+
+ }
+
+ public boolean isStopped()
+ {
+ return _stopped.get();
+ }
+
+ public boolean acquires()
+ {
+ return _acquireMode == MessageAcquireMode.PRE_ACQUIRED;
+ }
+
+ public void acknowledge(QueueEntry entry)
+ {
+ // TODO Fix Store Context / cleanup
+ if(entry.isAcquiredBy(this))
+ {
+ entry.discard();
+ }
+ }
+
+ public void flush() throws AMQException
+ {
+ _queue.flushSubscription(this);
+ stop();
+ }
+
+ public long getSubscriptionID()
+ {
+ return _subscriptionID;
+ }
+
+ public LogActor getLogActor()
+ {
+ return _logActor;
+ }
+
+ ServerSession getSession()
+ {
+ return _session;
+ }
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
new file mode 100644
index 0000000000..2a8b99ddac
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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 org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.Method;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+public class ServerConnection extends Connection
+{
+ @Override
+ protected void invoke(Method method)
+ {
+ super.invoke(method);
+ }
+
+ @Override
+ protected void setState(State state)
+ {
+ super.setState(state);
+ }
+
+ @Override
+ public ServerConnectionDelegate getConnectionDelegate()
+ {
+ return (ServerConnectionDelegate) super.getConnectionDelegate();
+ }
+
+ public void setConnectionDelegate(ServerConnectionDelegate delegate)
+ {
+ super.setConnectionDelegate(delegate);
+ }
+
+ private VirtualHost _virtualHost;
+
+
+ public VirtualHost getVirtualHost()
+ {
+ return _virtualHost;
+ }
+
+ public void setVirtualHost(VirtualHost virtualHost)
+ {
+ _virtualHost = virtualHost;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
new file mode 100644
index 0000000000..cfc5bb3a72
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
@@ -0,0 +1,120 @@
+/*
+ *
+ * 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 org.apache.qpid.transport.*;
+
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslException;
+import java.util.*;
+
+
+public class ServerConnectionDelegate extends ServerDelegate
+{
+
+ private String _localFQDN;
+ private final IApplicationRegistry _appRegistry;
+
+
+ public ServerConnectionDelegate(IApplicationRegistry appRegistry,
+ String localFQDN)
+ {
+ this(Collections.EMPTY_MAP, Collections.singletonList((Object)"en_US"), appRegistry, localFQDN);
+ }
+
+
+ public ServerConnectionDelegate(Map<String, Object> properties,
+ List<Object> locales,
+ IApplicationRegistry appRegistry,
+ String localFQDN)
+ {
+ super(properties, parseToList(appRegistry.getAuthenticationManager().getMechanisms()), locales);
+ _appRegistry = appRegistry;
+ _localFQDN = localFQDN;
+ }
+
+ private static List<Object> parseToList(String mechanisms)
+ {
+ List<Object> list = new ArrayList<Object>();
+ StringTokenizer tokenizer = new StringTokenizer(mechanisms, " ");
+ while(tokenizer.hasMoreTokens())
+ {
+ list.add(tokenizer.nextToken());
+ }
+ return list;
+ }
+
+ @Override public ServerSession getSession(Connection conn, SessionAttach atc)
+ {
+
+ SessionDelegate serverSessionDelegate = new ServerSessionDelegate(_appRegistry);
+
+ ServerSession ssn = new ServerSession(conn, serverSessionDelegate, new Binary(atc.getName()), 0);
+ //ssn.setSessionListener(new Echo());
+ return ssn;
+ }
+
+
+
+
+ @Override
+ protected SaslServer createSaslServer(String mechanism) throws SaslException
+ {
+ return _appRegistry.getAuthenticationManager().createSaslServer(mechanism, _localFQDN);
+
+ }
+
+
+ @Override public void connectionOpen(Connection conn, ConnectionOpen open)
+ {
+ ServerConnection sconn = (ServerConnection) conn;
+
+ VirtualHost vhost;
+ String vhostName;
+ if(open.hasVirtualHost())
+ {
+ vhostName = open.getVirtualHost();
+ }
+ else
+ {
+ vhostName = "";
+ }
+ vhost = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhostName);
+
+ if(vhost != null)
+ {
+ sconn.setVirtualHost(vhost);
+
+ sconn.invoke(new ConnectionOpenOk(Collections.EMPTY_LIST));
+
+ sconn.setState(Connection.State.OPEN);
+ }
+ else
+ {
+ sconn.invoke(new ConnectionClose(ConnectionCloseCode.INVALID_PATH, "Unknown vistrulhost '"+vhostName+"'"));
+ sconn.setState(Connection.State.CLOSING);
+ }
+
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
new file mode 100644
index 0000000000..77dfbc0376
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
@@ -0,0 +1,398 @@
+/*
+ *
+ * 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 org.apache.qpid.transport.*;
+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_0_10;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.LocalTransaction;
+import org.apache.qpid.server.security.PrincipalHolder;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.AMQException;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+import java.security.Principal;
+import java.lang.ref.WeakReference;
+
+import static org.apache.qpid.util.Serial.*;
+import com.sun.security.auth.UserPrincipal;
+
+public class ServerSession extends Session implements PrincipalHolder
+{
+ private static final String NULL_DESTINTATION = UUID.randomUUID().toString();
+
+ public static interface MessageDispositionChangeListener
+ {
+ public void onAccept();
+
+ public void onRelease();
+
+ public void onReject();
+
+ public boolean acquire();
+
+
+ }
+
+ public static interface Task
+ {
+ public void doTask(ServerSession session);
+ }
+
+
+ private final SortedMap<Integer, MessageDispositionChangeListener> _messageDispositionListenerMap =
+ new ConcurrentSkipListMap<Integer, MessageDispositionChangeListener>();
+
+ private ServerTransaction _transaction;
+
+ private Principal _principal;
+
+ private Map<String, Subscription_0_10> _subscriptions = new ConcurrentHashMap<String, Subscription_0_10>();
+
+ private final List<Task> _taskList = new CopyOnWriteArrayList<Task>();
+
+ private final WeakReference<Session> _reference;
+
+
+ ServerSession(Connection connection, Binary name, long expiry)
+ {
+ super(connection, name, expiry);
+
+ _transaction = new AutoCommitTransaction(this.getMessageStore());
+ _principal = new UserPrincipal(connection.getAuthorizationID());
+ _reference = new WeakReference(this);
+ }
+
+ ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry)
+ {
+ super(connection, delegate, name, expiry);
+ _transaction = new AutoCommitTransaction(this.getMessageStore());
+ _principal = new UserPrincipal(connection.getAuthorizationID());
+ _reference = new WeakReference(this);
+ }
+
+ @Override
+ protected boolean isFull(int id)
+ {
+ return isCommandsFull(id);
+ }
+
+ public void enqueue(final ServerMessage message, final ArrayList<AMQQueue> queues)
+ {
+
+ _transaction.enqueue(queues,message, new ServerTransaction.Action()
+ {
+
+ AMQQueue[] _queues = queues.toArray(new AMQQueue[queues.size()]);
+
+ public void postCommit()
+ {
+ for(int i = 0; i < _queues.length; i++)
+ {
+ try
+ {
+ _queues[i].enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ // TODO
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public void onRollback()
+ {
+ // NO-OP
+ }
+ });
+
+
+ }
+
+
+ public void sendMessage(MessageTransfer xfr,
+ Runnable postIdSettingAction)
+ {
+ invoke(xfr, postIdSettingAction);
+ }
+
+ public void onMessageDispositionChange(MessageTransfer xfr, MessageDispositionChangeListener acceptListener)
+ {
+ _messageDispositionListenerMap.put(xfr.getId(), acceptListener);
+ }
+
+
+ private static interface MessageDispositionAction
+ {
+ void performAction(MessageDispositionChangeListener listener);
+ }
+
+ public void accept(RangeSet ranges)
+ {
+ dispositionChange(ranges, new MessageDispositionAction()
+ {
+ public void performAction(MessageDispositionChangeListener listener)
+ {
+ listener.onAccept();
+ }
+ });
+ }
+
+
+ public void release(RangeSet ranges)
+ {
+ dispositionChange(ranges, new MessageDispositionAction()
+ {
+ public void performAction(MessageDispositionChangeListener listener)
+ {
+ listener.onRelease();
+ }
+ });
+ }
+
+ public void reject(RangeSet ranges)
+ {
+ dispositionChange(ranges, new MessageDispositionAction()
+ {
+ public void performAction(MessageDispositionChangeListener listener)
+ {
+ listener.onReject();
+ }
+ });
+ }
+
+ public RangeSet acquire(RangeSet transfers)
+ {
+ RangeSet acquired = new RangeSet();
+
+ if(!_messageDispositionListenerMap.isEmpty())
+ {
+ Iterator<Integer> unacceptedMessages = _messageDispositionListenerMap.keySet().iterator();
+ Iterator<Range> rangeIter = transfers.iterator();
+
+ if(rangeIter.hasNext())
+ {
+ Range range = rangeIter.next();
+
+ while(range != null && unacceptedMessages.hasNext())
+ {
+ int next = unacceptedMessages.next();
+ while(gt(next, range.getUpper()))
+ {
+ if(rangeIter.hasNext())
+ {
+ range = rangeIter.next();
+ }
+ else
+ {
+ range = null;
+ break;
+ }
+ }
+ if(range != null && range.includes(next))
+ {
+ MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.get(next);
+ if(changeListener.acquire())
+ {
+ acquired.add(next);
+ }
+ }
+
+
+ }
+
+ }
+
+
+ }
+
+ return acquired;
+ }
+
+ public void dispositionChange(RangeSet ranges, MessageDispositionAction action)
+ {
+ if(ranges != null && !_messageDispositionListenerMap.isEmpty())
+ {
+ Iterator<Integer> unacceptedMessages = _messageDispositionListenerMap.keySet().iterator();
+ Iterator<Range> rangeIter = ranges.iterator();
+
+ if(rangeIter.hasNext())
+ {
+ Range range = rangeIter.next();
+
+ while(range != null && unacceptedMessages.hasNext())
+ {
+ int next = unacceptedMessages.next();
+ while(gt(next, range.getUpper()))
+ {
+ if(rangeIter.hasNext())
+ {
+ range = rangeIter.next();
+ }
+ else
+ {
+ range = null;
+ break;
+ }
+ }
+ if(range != null && range.includes(next))
+ {
+ MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.remove(next);
+ action.performAction(changeListener);
+ }
+
+
+ }
+
+ }
+
+ }
+ }
+
+ public void removeDispositionListener(Method method)
+ {
+ _messageDispositionListenerMap.remove(method.getId());
+ }
+
+ public void onClose()
+ {
+ _transaction.rollback();
+ for(MessageDispositionChangeListener listener : _messageDispositionListenerMap.values())
+ {
+ listener.onRelease();
+ }
+ _messageDispositionListenerMap.clear();
+
+ for (Task task : _taskList)
+ {
+ task.doTask(this);
+ }
+
+ }
+
+ public void acknowledge(final Subscription_0_10 sub, final QueueEntry entry)
+ {
+ _transaction.dequeue(entry.getQueue(), entry.getMessage(),
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ sub.acknowledge(entry);
+ }
+
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+ }
+
+ public Collection<Subscription_0_10> getSubscriptions()
+ {
+ return _subscriptions.values();
+ }
+
+ public void register(String destination, Subscription_0_10 sub)
+ {
+ _subscriptions.put(destination == null ? NULL_DESTINTATION : destination, sub);
+ }
+
+ public Subscription_0_10 getSubscription(String destination)
+ {
+ return _subscriptions.get(destination == null ? NULL_DESTINTATION : destination);
+ }
+
+ public void unregister(Subscription_0_10 sub)
+ {
+ _subscriptions.remove(sub.getConsumerTag().toString());
+ try
+ {
+ sub.getSendLock();
+ AMQQueue queue = sub.getQueue();
+ if(queue != null)
+ {
+ queue.unregisterSubscription(sub);
+ }
+
+ }
+ catch (AMQException e)
+ {
+ // TODO
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ }
+ finally
+ {
+ sub.releaseSendLock();
+ }
+ }
+
+ public void selectTx()
+ {
+ _transaction = new LocalTransaction(this.getMessageStore());
+ }
+
+ public void commit()
+ {
+ _transaction.commit();
+ }
+
+ public void rollback()
+ {
+ _transaction.rollback();
+ }
+
+ public Principal getPrincipal()
+ {
+ return _principal;
+ }
+
+ public void addSessionCloseTask(Task task)
+ {
+ _taskList.add(task);
+ }
+
+ public void removeSessionCloseTask(Task task)
+ {
+ _taskList.remove(task);
+ }
+
+ public WeakReference<Session> getReference()
+ {
+ return _reference;
+ }
+
+ public MessageStore getMessageStore()
+ {
+ return ((ServerConnection)getConnection()).getVirtualHost().getMessageStore();
+ }
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
new file mode 100644
index 0000000000..df2754c16b
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
@@ -0,0 +1,1193 @@
+/*
+ *
+ * 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 org.apache.qpid.transport.*;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.exchange.*;
+import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.message.MessageTransferMessage;
+import org.apache.qpid.server.message.MessageMetaData_0_10;
+import org.apache.qpid.server.subscription.Subscription_0_10;
+import org.apache.qpid.server.flow.*;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQUnknownExchangeType;
+import org.apache.qpid.framing.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+public class ServerSessionDelegate extends SessionDelegate
+{
+ private final IApplicationRegistry _appRegistry;
+
+ public ServerSessionDelegate(IApplicationRegistry appRegistry)
+ {
+ _appRegistry = appRegistry;
+ }
+
+ @Override
+ public void command(Session session, Method method)
+ {
+ super.command(session, method);
+ if (method.isSync())
+ {
+ session.flushProcessed();
+ }
+ }
+
+ @Override
+ public void messageAccept(Session session, MessageAccept method)
+ {
+ ((ServerSession)session).accept(method.getTransfers());
+ }
+
+
+
+ @Override
+ public void messageReject(Session session, MessageReject method)
+ {
+ ((ServerSession)session).reject(method.getTransfers());
+ }
+
+ @Override
+ public void messageRelease(Session session, MessageRelease method)
+ {
+ ((ServerSession)session).release(method.getTransfers());
+ }
+
+ @Override
+ public void messageAcquire(Session session, MessageAcquire method)
+ {
+ RangeSet acquiredRanges = ((ServerSession)session).acquire(method.getTransfers());
+
+ Acquired result = new Acquired(acquiredRanges);
+
+
+ session.executionResult((int) method.getId(), result);
+
+
+ }
+
+ @Override
+ public void messageResume(Session session, MessageResume method)
+ {
+ super.messageResume(session, method);
+ }
+
+ @Override
+ public void messageSubscribe(Session session, MessageSubscribe method)
+ {
+
+ //TODO - work around broken Python tests
+ if(!method.hasAcceptMode())
+ {
+ method.setAcceptMode(MessageAcceptMode.EXPLICIT);
+ }
+ if(!method.hasAcquireMode())
+ {
+ method.setAcquireMode(MessageAcquireMode.PRE_ACQUIRED);
+
+ }
+
+ /* if(!method.hasAcceptMode())
+ {
+ exception(session,method,ExecutionErrorCode.ILLEGAL_ARGUMENT, "Accept-mode not supplied");
+ }
+ else if(!method.hasAcquireMode())
+ {
+ exception(session,method,ExecutionErrorCode.ILLEGAL_ARGUMENT, "Acquire-mode not supplied");
+ }
+ else */if(!method.hasQueue())
+ {
+ exception(session,method,ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not supplied");
+ }
+ else
+ {
+ String destination = method.getDestination();
+
+ if(((ServerSession)session).getSubscription(destination)!=null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Subscription already exists with destaination: '"+destination+"'");
+ }
+ else
+ {
+ String queueName = method.getQueue();
+ QueueRegistry queueRegistry = getQueueRegistry(session);
+
+
+ AMQQueue queue = queueRegistry.getQueue(queueName);
+
+ if(queue == null)
+ {
+ exception(session,method,ExecutionErrorCode.NOT_FOUND, "Queue: " + queueName + " not found");
+ }
+ else if(queue.getPrincipalHolder() != null && queue.getPrincipalHolder() != session)
+ {
+ exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
+ }
+ else
+ {
+
+ FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L);
+
+ // TODO filters
+
+ Subscription_0_10 sub = new Subscription_0_10((ServerSession)session,
+ destination,
+ method.getAcceptMode(),
+ method.getAcquireMode(),
+ MessageFlowMode.WINDOW,
+ creditManager, null);
+
+ ((ServerSession)session).register(destination, sub);
+ try
+ {
+ queue.registerSubscription(sub, method.getExclusive());
+ }
+ catch (AMQQueue.ExistingExclusiveSubscription existing)
+ {
+ exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an exclusive consumer");
+ }
+ catch (AMQQueue.ExistingSubscriptionPreventsExclusive exclusive)
+ {
+ exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an existing consumer - can't subscribe exclusively");
+ }
+ catch (AMQException e)
+ {
+ // TODO
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+ }
+
+
+ @Override
+ public void messageTransfer(Session ssn, MessageTransfer xfr)
+ {
+ ExchangeRegistry exchangeRegistry = getExchangeRegistry(ssn);
+ Exchange exchange;
+ if(xfr.hasDestination())
+ {
+ exchange = exchangeRegistry.getExchange(xfr.getDestination());
+ if(exchange == null)
+ {
+ exchange = exchangeRegistry.getDefaultExchange();
+ }
+ }
+ else
+ {
+ exchange = exchangeRegistry.getDefaultExchange();
+ }
+
+
+ DeliveryProperties delvProps = null;
+ if(xfr.getHeader() != null && (delvProps = xfr.getHeader().get(DeliveryProperties.class)) != null && delvProps.hasTtl() && !delvProps.hasExpiration())
+ {
+ delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl());
+ }
+
+ MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr);
+ final MessageStore store = getVirtualHost(ssn).getMessageStore();
+ StoredMessage<MessageMetaData_0_10> storeMessage = store.addMessage(messageMetaData);
+ storeMessage.addContent(0,xfr.getBody());
+ storeMessage.flushToStore();
+ MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)ssn).getReference());
+
+ ArrayList<AMQQueue> queues = exchange.route(message);
+
+
+
+ if(queues != null && queues.size() != 0)
+ {
+ ((ServerSession) ssn).enqueue(message, queues);
+ }
+ else
+ {
+ if(delvProps == null || !delvProps.hasDiscardUnroutable() || !delvProps.getDiscardUnroutable())
+ {
+ if(xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT)
+ {
+ RangeSet rejects = new RangeSet();
+ rejects.add(xfr.getId());
+ MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable");
+ ssn.invoke(reject);
+ }
+ else
+ {
+ Exchange alternate = exchange.getAlternateExchange();
+ if(alternate != null)
+ {
+ queues = alternate.route(message);
+ if(queues != null && queues.size() != 0)
+ {
+ ((ServerSession) ssn).enqueue(message, queues);
+ }
+ else
+ {
+ //TODO - log the message discard
+ }
+ }
+ else
+ {
+ //TODO - log the message discard
+ }
+
+
+ }
+ }
+
+
+ }
+
+ ssn.processed(xfr);
+
+ }
+
+ @Override
+ public void messageCancel(Session session, MessageCancel method)
+ {
+ String destination = method.getDestination();
+
+ Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+
+ if(sub == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'");
+ }
+ else
+ {
+ ((ServerSession)session).unregister(sub);
+ }
+ }
+
+ @Override
+ public void messageFlush(Session session, MessageFlush method)
+ {
+ String destination = method.getDestination();
+
+ Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+
+ if(sub == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'");
+ }
+ else
+ {
+
+ try
+ {
+ sub.flush();
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ public void txSelect(Session session, TxSelect method)
+ {
+ // TODO - check current tx mode
+ ((ServerSession)session).selectTx();
+ }
+
+ @Override
+ public void txCommit(Session session, TxCommit method)
+ {
+ // TODO - check current tx mode
+ ((ServerSession)session).commit();
+ }
+
+ @Override
+ public void txRollback(Session session, TxRollback method)
+ {
+ // TODO - check current tx mode
+ ((ServerSession)session).rollback();
+ }
+
+
+ @Override
+ public void exchangeDeclare(Session session, ExchangeDeclare method)
+ {
+ String exchangeName = method.getExchange();
+ VirtualHost virtualHost = getVirtualHost(session);
+ Exchange exchange = getExchange(session, exchangeName);
+
+ if(method.getPassive())
+ {
+ if(exchange == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: exchange-name '"+exchangeName+"'");
+
+ }
+ else
+ {
+ // TODO - check exchange has same properties
+ if(!exchange.getType().toString().equals(method.getType()))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Cannot redeclare with a different exchange type");
+ }
+ }
+
+ }
+ else
+ {
+ if (!virtualHost.getAccessManager().authoriseCreateExchange((ServerSession)session, method.getAutoDelete(),
+ method.getDurable(), new AMQShortString(method.getExchange()), false, false, method.getPassive(),
+ new AMQShortString(method.getType())))
+ {
+
+ ExecutionErrorCode errorCode = ExecutionErrorCode.NOT_ALLOWED;
+ String description = "permission denied: exchange-name '" + exchangeName + "'";
+
+ exception(session, method, errorCode, description);
+
+
+ }
+ else if(exchange == null)
+ {
+ ExchangeRegistry exchangeRegistry = getExchangeRegistry(session);
+ ExchangeFactory exchangeFactory = virtualHost.getExchangeFactory();
+
+
+
+ try
+ {
+
+ exchange = exchangeFactory.createExchange(method.getExchange(),
+ method.getType(),
+ method.getDurable(),
+ method.getAutoDelete());
+
+ String alternateExchangeName = method.getAlternateExchange();
+ if(alternateExchangeName != null && alternateExchangeName.length() != 0)
+ {
+ Exchange alternate = getExchange(session, alternateExchangeName);
+ exchange.setAlternateExchange(alternate);
+ }
+
+ if (exchange.isDurable() && !exchange.isAutoDelete())
+ {
+ DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+ store.createExchange(exchange);
+ }
+
+ exchangeRegistry.registerExchange(exchange);
+ }
+ catch(AMQUnknownExchangeType e)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "Unknown Exchange Type: " + method.getType());
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ throw new RuntimeException(e);
+ }
+
+ }
+ else
+ {
+ if(!exchange.getType().toString().equals(method.getType()))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Cannot redeclare with a different exchange type");
+ }
+ }
+
+ }
+ }
+
+ private void exception(Session session, Method method, ExecutionErrorCode errorCode, String description)
+ {
+ ExecutionException ex = new ExecutionException();
+ ex.setErrorCode(errorCode);
+ ex.setCommandId(method.getId());
+ ex.setDescription(description);
+
+ session.invoke(ex);
+
+ }
+
+ private Exchange getExchange(Session session, String exchangeName)
+ {
+ ExchangeRegistry exchangeRegistry = getExchangeRegistry(session);
+ return exchangeRegistry.getExchange(exchangeName);
+ }
+
+ private ExchangeRegistry getExchangeRegistry(Session session)
+ {
+ VirtualHost virtualHost = getVirtualHost(session);
+ return virtualHost.getExchangeRegistry();
+
+ }
+
+ private VirtualHost getVirtualHost(Session session)
+ {
+ ServerConnection conn = getServerConnection(session);
+ VirtualHost vhost = conn.getVirtualHost();
+ return vhost;
+ }
+
+ private ServerConnection getServerConnection(Session session)
+ {
+ ServerConnection conn = (ServerConnection) session.getConnection();
+ return conn;
+ }
+
+ @Override
+ public void exchangeDelete(Session session, ExchangeDelete method)
+ {
+ VirtualHost virtualHost = getVirtualHost(session);
+ ExchangeRegistry exchangeRegistry = virtualHost.getExchangeRegistry();
+
+ //Perform ACLs
+ if (!virtualHost.getAccessManager().authoriseDelete((ServerSession)session,
+ exchangeRegistry.getExchange(method.getExchange())))
+ {
+ exception(session,method, ExecutionErrorCode.NOT_ALLOWED, "Permission denied");
+
+ }
+ else
+ {
+
+ try
+ {
+ Exchange exchange = getExchange(session, method.getExchange());
+
+ if(exchange != null && exchange.hasReferrers())
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Exchange in use as an alternate exchange");
+ }
+ else
+ {
+ exchangeRegistry.unregisterExchange(method.getExchange(), method.getIfUnused());
+
+ if (exchange.isDurable() && !exchange.isAutoDelete())
+ {
+ DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+ store.removeExchange(exchange);
+ }
+
+ }
+ }
+ catch (ExchangeInUseException e)
+ {
+ exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Exchange in use");
+ }
+ catch (AMQException e)
+ {
+ // TODO
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+ @Override
+ public void exchangeQuery(Session session, ExchangeQuery method)
+ {
+
+ ExchangeQueryResult result = new ExchangeQueryResult();
+
+ Exchange exchange = getExchange(session, method.getName());
+
+ if(exchange != null)
+ {
+ result.setDurable(exchange.isDurable());
+ result.setType(exchange.getType().toString());
+ result.setNotFound(false);
+ }
+ else
+ {
+ result.setNotFound(true);
+ }
+
+ session.executionResult((int) method.getId(), result);
+ }
+
+ @Override
+ public void exchangeBind(Session session, ExchangeBind method)
+ {
+
+ VirtualHost virtualHost = getVirtualHost(session);
+ ExchangeRegistry exchangeRegistry = virtualHost.getExchangeRegistry();
+ QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
+
+ if (!method.hasQueue())
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set");
+ }
+ else if (!method.hasExchange())
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "exchange not set");
+ }
+/*
+ else if (!method.hasBindingKey())
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "binding-key not set");
+ }
+*/
+ else
+ {
+ //TODO - here because of non-compiant python tests
+ if (!method.hasBindingKey())
+ {
+ method.setBindingKey(method.getQueue());
+ }
+ AMQQueue queue = queueRegistry.getQueue(method.getQueue());
+ Exchange exchange = exchangeRegistry.getExchange(method.getExchange());
+ if(queue == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "Queue: '" + method.getQueue() + "' not found");
+ }
+ else if(exchange == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "Exchange: '" + method.getExchange() + "' not found");
+ }
+ else if (!virtualHost.getAccessManager().authoriseBind((ServerSession)session, exchange,
+ queue, new AMQShortString(method.getBindingKey())))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Bind Exchange: '" + method.getExchange()
+ + "' to Queue: '" + method.getQueue()
+ + "' not allowed");
+ }
+ else if(exchange.getType().equals(HeadersExchange.TYPE.getName()) && (!method.hasArguments() || method.getArguments() == null || !method.getArguments().containsKey("x-match")))
+ {
+ exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Bindings to an exchange of type " + HeadersExchange.TYPE.getName() + " require an x-match header");
+ }
+ else
+ {
+ try
+ {
+ AMQShortString routingKey = new AMQShortString(method.getBindingKey());
+ FieldTable fieldTable = FieldTable.convertToFieldTable(method.getArguments());
+
+ if (!exchange.isBound(routingKey, fieldTable, queue))
+ {
+ queue.bind(exchange, routingKey, fieldTable);
+
+ }
+ else
+ {
+ // todo
+ }
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ }
+ }
+
+
+ }
+
+
+
+ }
+
+ @Override
+ public void exchangeUnbind(Session session, ExchangeUnbind method)
+ {
+ VirtualHost virtualHost = getVirtualHost(session);
+ ExchangeRegistry exchangeRegistry = virtualHost.getExchangeRegistry();
+ QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
+
+ if (!method.hasQueue())
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set");
+ }
+ else if (!method.hasExchange())
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "exchange not set");
+ }
+ else if (!method.hasBindingKey())
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "binding-key not set");
+ }
+ else
+ {
+ AMQQueue queue = queueRegistry.getQueue(method.getQueue());
+ Exchange exchange = exchangeRegistry.getExchange(method.getExchange());
+ if(queue == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "Queue: '" + method.getQueue() + "' not found");
+ }
+ else if(exchange == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "Exchange: '" + method.getExchange() + "' not found");
+ }
+ else
+ {
+ try
+ {
+ queue.unBind(exchange, new AMQShortString(method.getBindingKey()), null);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+
+ super.exchangeUnbind(session, method);
+ }
+
+ @Override
+ public void exchangeBound(Session session, ExchangeBound method)
+ {
+
+ ExchangeBoundResult result = new ExchangeBoundResult();
+ Exchange exchange;
+ AMQQueue queue;
+ if(method.hasExchange())
+ {
+ exchange = getExchange(session, method.getExchange());
+
+ if(exchange == null)
+ {
+ result.setExchangeNotFound(true);
+ }
+ }
+ else
+ {
+ exchange = getExchangeRegistry(session).getDefaultExchange();
+ }
+
+
+ if(method.hasQueue())
+ {
+
+ queue = getQueue(session, method.getQueue());
+ if(queue == null)
+ {
+ result.setQueueNotFound(true);
+ }
+
+
+ if(exchange != null && queue != null)
+ {
+
+ boolean queueMatched = exchange.isBound(queue);
+
+ result.setQueueNotMatched(!queueMatched);
+
+
+ if(method.hasBindingKey())
+ {
+
+ if(method.hasArguments())
+ {
+ // TODO
+ }
+ if(queueMatched)
+ {
+ result.setKeyNotMatched(!exchange.isBound(method.getBindingKey(), queue));
+ }
+ else
+ {
+ result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
+ }
+ }
+ else if (method.hasArguments())
+ {
+ // TODO
+
+ }
+
+ result.setQueueNotMatched(!exchange.isBound(queue));
+
+ }
+ else if(exchange != null && method.hasBindingKey())
+ {
+ if(method.hasArguments())
+ {
+ // TODO
+ }
+ result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
+
+ }
+
+ }
+ else if(exchange != null && method.hasBindingKey())
+ {
+ if(method.hasArguments())
+ {
+ // TODO
+ }
+ result.setKeyNotMatched(!exchange.isBound(method.getBindingKey()));
+
+ }
+
+
+ session.executionResult((int) method.getId(), result);
+
+
+ }
+
+ private AMQQueue getQueue(Session session, String queue)
+ {
+ QueueRegistry queueRegistry = getQueueRegistry(session);
+ return queueRegistry.getQueue(queue);
+ }
+
+ private QueueRegistry getQueueRegistry(Session session)
+ {
+ return getVirtualHost(session).getQueueRegistry();
+ }
+
+ @Override
+ public void queueDeclare(Session session, QueueDeclare method)
+ {
+
+ VirtualHost virtualHost = getVirtualHost(session);
+ DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+
+ String queueName = method.getQueue();
+
+ if (!method.getPassive())
+ {
+ // Perform ACL if request is not passive
+
+ if (!virtualHost.getAccessManager().authoriseCreateQueue(((ServerSession)session), method.getAutoDelete(), method.getDurable(),
+ method.getExclusive(), false, method.getPassive(), new AMQShortString(queueName)))
+ {
+ ExecutionErrorCode errorCode = ExecutionErrorCode.NOT_ALLOWED;
+ String description = "permission denied: queue-name '" + queueName + "'";
+
+ exception(session, method, errorCode, description);
+
+ // TODO control flow
+ return;
+ }
+ }
+
+
+ AMQQueue queue;
+ QueueRegistry queueRegistry = getQueueRegistry(session);
+ //TODO: do we need to check that the queue already exists with exactly the same "configuration"?
+
+ synchronized (queueRegistry)
+ {
+
+ if (((queue = queueRegistry.getQueue(queueName)) == null))
+ {
+
+ if (method.getPassive())
+ {
+ String description = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ").";
+ ExecutionErrorCode errorCode = ExecutionErrorCode.NOT_FOUND;
+
+ exception(session, method, errorCode, description);
+
+ return;
+ }
+ else
+ {
+ try
+ {
+ queue = createQueue(queueName, method, virtualHost, (ServerSession)session);
+ if(method.getExclusive())
+ {
+ queue.setPrincipalHolder((ServerSession)session);
+ queue.setExclusiveOwner(session);
+ }
+ final String alternateExchangeName = method.getAlternateExchange();
+ if(alternateExchangeName != null && alternateExchangeName.length() != 0)
+ {
+ Exchange alternate = getExchange(session, alternateExchangeName);
+ queue.setAlternateExchange(alternate);
+ }
+
+ if(method.hasArguments() && method.getArguments() != null)
+ {
+ if(method.getArguments().containsKey("no-local"))
+ {
+ Object no_local = method.getArguments().get("no-local");
+ if(no_local instanceof Boolean && ((Boolean)no_local))
+ {
+ queue.setNoLocal(true);
+ }
+ }
+ }
+
+
+ if (queue.isDurable() && !queue.isAutoDelete())
+ {
+ if(method.hasArguments() && method.getArguments() != null)
+ {
+ Map<String,Object> args = method.getArguments();
+ FieldTable ftArgs = new FieldTable();
+ for(Map.Entry<String, Object> entry : args.entrySet())
+ {
+ ftArgs.put(new AMQShortString(entry.getKey()), entry.getValue());
+ }
+ store.createQueue(queue, ftArgs);
+ }
+ else
+ {
+ store.createQueue(queue);
+ }
+ }
+ queueRegistry.registerQueue(queue);
+ boolean autoRegister = ApplicationRegistry.getInstance().getConfiguration().getQueueAutoRegister();
+
+ if (autoRegister)
+ {
+ ExchangeRegistry exchangeRegistry = getExchangeRegistry(session);
+
+ Exchange defaultExchange = exchangeRegistry.getDefaultExchange();
+
+ queue.bind(defaultExchange, new AMQShortString(queueName), null);
+
+ }
+
+ if(method.hasAutoDelete()
+ && method.getAutoDelete()
+ && method.hasExclusive()
+ && method.getExclusive())
+ {
+ final AMQQueue q = queue;
+ final ServerSession.Task deleteQueueTask = new ServerSession.Task()
+ {
+
+ public void doTask(ServerSession session)
+ {
+ try
+ {
+ q.delete();
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ final ServerSession s = (ServerSession) session;
+ s.addSessionCloseTask(deleteQueueTask);
+ queue.addQueueDeleteTask(new AMQQueue.Task()
+ {
+
+ public void doTask(AMQQueue queue) throws AMQException
+ {
+ s.removeSessionCloseTask(deleteQueueTask);
+ }
+ });
+ }
+ else if(method.getExclusive())
+ {
+ {
+ final AMQQueue q = queue;
+ final ServerSession.Task removeExclusive = new ServerSession.Task()
+ {
+
+ public void doTask(ServerSession session)
+ {
+ q.setPrincipalHolder(null);
+ }
+ };
+ final ServerSession s = (ServerSession) session;
+ s.addSessionCloseTask(removeExclusive);
+ queue.addQueueDeleteTask(new AMQQueue.Task()
+ {
+
+ public void doTask(AMQQueue queue) throws AMQException
+ {
+ s.removeSessionCloseTask(removeExclusive);
+ }
+ });
+ }
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ else if (method.getExclusive() && (queue.getPrincipalHolder() != null && !queue.getPrincipalHolder().equals(session)))
+ {
+
+ String description = "Cannot declare queue('" + queueName + "'),"
+ + " as exclusive queue with same name "
+ + "declared on another session";
+ ExecutionErrorCode errorCode = ExecutionErrorCode.RESOURCE_LOCKED;
+
+ exception(session, method, errorCode, description);
+
+ return;
+ }
+
+ }
+ }
+
+
+ protected AMQQueue createQueue(final String queueName,
+ QueueDeclare body,
+ VirtualHost virtualHost,
+ final ServerSession session)
+ throws AMQException
+ {
+ final QueueRegistry registry = virtualHost.getQueueRegistry();
+
+ String owner = body.getExclusive() ? session.getPrincipal().getName() : null;
+
+ final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, body.getDurable(), owner, body.getAutoDelete(), virtualHost,
+ body.getArguments());
+
+
+ if (body.getExclusive() && !body.getDurable())
+ {
+ final ServerSession.Task deleteQueueTask =
+ new ServerSession.Task()
+ {
+ public void doTask(ServerSession session)
+ {
+ if (registry.getQueue(queueName) == queue)
+ {
+ try
+ {
+ queue.delete();
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ };
+
+ session.addSessionCloseTask(deleteQueueTask);
+
+ queue.addQueueDeleteTask(new AMQQueue.Task()
+ {
+ public void doTask(AMQQueue queue)
+ {
+ session.removeSessionCloseTask(deleteQueueTask);
+ }
+ });
+ }// if exclusive and not durable
+
+ return queue;
+ }
+
+ @Override
+ public void queueDelete(Session session, QueueDelete method)
+ {
+
+ String queueName = method.getQueue();
+ if(queueName == null || queueName.length()==0)
+ {
+ exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "No queue name supplied");
+
+ }
+ else
+ {
+ AMQQueue queue = getQueue(session, queueName);
+
+
+ if (queue == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "No queue " + queueName + " found");
+ }
+ else
+ {
+ if(queue.getPrincipalHolder() != null && queue.getPrincipalHolder() != 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");
+ }
+ else if (method.getIfUnused() && !queue.isUnused())
+ {
+ // TODO - Error code
+ exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Queue " + queueName + " in use");
+
+ }
+ else
+ {
+ VirtualHost virtualHost = getVirtualHost(session);
+
+ //Perform ACLs
+ if (!virtualHost.getAccessManager().authoriseDelete(((ServerSession)session), queue))
+ {
+ exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Cannot delete queue " + queueName);
+ }
+ else
+ {
+ try
+ {
+ int purged = queue.delete();
+ if (queue.isDurable() && !queue.isAutoDelete())
+ {
+ DurableConfigurationStore store = virtualHost.getDurableConfigurationStore();
+ store.removeQueue(queue);
+ }
+
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public void queuePurge(Session session, QueuePurge method)
+ {
+ String queueName = method.getQueue();
+ if(queueName == null || queueName.length()==0)
+ {
+ exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "No queue name supplied");
+
+ }
+ else
+ {
+ AMQQueue queue = getQueue(session, queueName);
+
+
+ if (queue == null)
+ {
+ exception(session, method, ExecutionErrorCode.NOT_FOUND, "No queue " + queueName + " found");
+ }
+ else
+ {
+ //TODO
+ queue.clearQueue();
+ }
+ }
+
+ }
+
+ @Override
+ public void queueQuery(Session session, QueueQuery method)
+ {
+ QueueQueryResult result = new QueueQueryResult();
+
+ AMQQueue queue = getQueue(session, method.getQueue());
+
+ if(queue != null)
+ {
+ result.setQueue(queue.getName().toString());
+ result.setDurable(queue.isDurable());
+ result.setExclusive(queue.isExclusive());
+ result.setAutoDelete(queue.isAutoDelete());
+ result.setArguments(queue.getArguments());
+ result.setMessageCount(queue.getMessageCount());
+ result.setSubscriberCount(queue.getConsumerCount());
+
+ }
+
+
+ session.executionResult((int) method.getId(), result);
+
+ }
+
+ @Override
+ public void messageSetFlowMode(Session session, MessageSetFlowMode sfm)
+ {
+ String destination = sfm.getDestination();
+
+ Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+
+ if(sub == null)
+ {
+ exception(session, sfm, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'");
+ }
+
+ if(sub.isStopped())
+ {
+ sub.setFlowMode(sfm.getFlowMode());
+ }
+ }
+
+ @Override
+ public void messageStop(Session session, MessageStop stop)
+ {
+ String destination = stop.getDestination();
+
+ Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+
+ if(sub == null)
+ {
+ exception(session, stop, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'");
+ }
+
+ sub.stop();
+
+ }
+
+ @Override
+ public void messageFlow(Session session, MessageFlow flow)
+ {
+ String destination = flow.getDestination();
+
+ Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination);
+
+ if(sub == null)
+ {
+ exception(session, flow, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'");
+ }
+
+ sub.addCredit(flow.getUnit(), flow.getValue());
+
+ }
+
+ @Override
+ public void closed(Session session)
+ {
+ super.closed(session);
+ for(Subscription_0_10 sub : getSubscriptions(session))
+ {
+ ((ServerSession)session).unregister(sub);
+ }
+ ((ServerSession)session).onClose();
+ }
+
+ public Collection<Subscription_0_10> getSubscriptions(Session session)
+ {
+ return ((ServerSession)session).getSubscriptions();
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
new file mode 100755
index 0000000000..7b29106ba6
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
@@ -0,0 +1,170 @@
+/*
+ *
+ * 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.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.store.TransactionLog;
+import org.apache.qpid.AMQException;
+
+import java.util.List;
+import java.util.Collection;
+
+public class AutoCommitTransaction implements ServerTransaction
+{
+
+ private final TransactionLog _transactionLog;
+
+ public AutoCommitTransaction(TransactionLog transactionLog)
+ {
+ _transactionLog = transactionLog;
+ }
+
+
+ public void addPostCommitAction(Action postCommitAction)
+ {
+ postCommitAction.postCommit();
+ }
+
+ public void dequeue(AMQQueue queue, EnqueableMessage message, Action postCommitAction)
+ {
+
+ try
+ {
+ if(message.isPersistent() && queue.isDurable())
+ {
+
+ TransactionLog.Transaction txn = _transactionLog.newTransaction();
+ txn.dequeueMessage(queue, message.getMessageNumber());
+ // store.remove enqueue
+ // store.commit
+ txn.commitTran();
+ }
+ postCommitAction.postCommit();
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ postCommitAction.onRollback();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void dequeue(Collection<QueueEntry> ackedMessages, Action postCommitAction)
+ {
+ try
+ {
+ TransactionLog.Transaction txn = null;
+ for(QueueEntry entry : ackedMessages)
+ {
+ ServerMessage message = entry.getMessage();
+ AMQQueue queue = entry.getQueue();
+
+ if(message.isPersistent() && queue.isDurable())
+ {
+ if(txn == null)
+ {
+ txn = _transactionLog.newTransaction();
+ }
+ txn.dequeueMessage(queue, message.getMessageNumber());
+ }
+
+ }
+ if(txn != null)
+ {
+ txn.commitTran();
+ }
+ postCommitAction.postCommit();
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ postCommitAction.onRollback();
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ public void enqueue(AMQQueue queue, EnqueableMessage message, Action postCommitAction)
+ {
+ try
+ {
+ if(message.isPersistent() && queue.isDurable())
+ {
+
+ TransactionLog.Transaction txn = _transactionLog.newTransaction();
+ txn.enqueueMessage(queue, message.getMessageNumber());
+ txn.commitTran();
+ }
+ postCommitAction.postCommit();
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ e.printStackTrace();
+ postCommitAction.onRollback();
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction)
+ {
+ try
+ {
+
+ if(message.isPersistent())
+ {
+ TransactionLog.Transaction txn = _transactionLog.newTransaction();
+ Long id = message.getMessageNumber();
+ for(AMQQueue q : queues)
+ {
+ if(q.isDurable())
+ {
+ txn.enqueueMessage(q, id);
+ }
+ }
+ txn.commitTran();
+
+ }
+ postCommitAction.postCommit();
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ postCommitAction.onRollback();
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public void commit()
+ {
+
+ }
+
+ public void rollback()
+ {
+
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
new file mode 100755
index 0000000000..9997fbe767
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
@@ -0,0 +1,243 @@
+package org.apache.qpid.server.txn;
+
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.store.TransactionLog;
+import org.apache.qpid.AMQException;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class LocalTransaction implements ServerTransaction
+{
+ private final List<Action> _postCommitActions = new ArrayList<Action>();
+
+ private volatile TransactionLog.Transaction _transaction;
+ private TransactionLog _transactionLog;
+
+ public LocalTransaction(TransactionLog transactionLog)
+ {
+ _transactionLog = transactionLog;
+ }
+
+ public void addPostCommitAction(Action postCommitAction)
+ {
+ _postCommitActions.add(postCommitAction);
+ }
+
+ public void dequeue(AMQQueue queue, EnqueableMessage message, Action postCommitAction)
+ {
+ if(message.isPersistent() && queue.isDurable())
+ {
+ try
+ {
+
+ beginTranIfNecessary();
+ _transaction.dequeueMessage(queue, message.getMessageNumber());
+
+ }
+ catch(AMQException e)
+ {
+ tidyUpOnError(e);
+ }
+ }
+ _postCommitActions.add(postCommitAction);
+ }
+
+ public void dequeue(Collection<QueueEntry> queueEntries, Action postCommitAction)
+ {
+ try
+ {
+
+ for(QueueEntry entry : queueEntries)
+ {
+ ServerMessage message = entry.getMessage();
+ AMQQueue queue = entry.getQueue();
+ if(message.isPersistent() && queue.isDurable())
+ {
+ beginTranIfNecessary();
+ _transaction.dequeueMessage(queue, message.getMessageNumber());
+ }
+
+ }
+ }
+ catch(AMQException e)
+ {
+ tidyUpOnError(e);
+ }
+ _postCommitActions.add(postCommitAction);
+
+ }
+
+ private void tidyUpOnError(Exception e)
+ {
+ try
+ {
+ for(Action action : _postCommitActions)
+ {
+ action.onRollback();
+ }
+ }
+ finally
+ {
+ try
+ {
+ _transaction.abortTran();
+ }
+ catch (Exception e1)
+ {
+ // TODO could try to chain the information to the original error
+ }
+ _transaction = null;
+ _postCommitActions.clear();
+ }
+
+ throw new RuntimeException(e);
+ }
+
+ private void beginTranIfNecessary()
+ {
+ if(_transaction == null)
+ {
+ try
+ {
+ _transaction = _transactionLog.newTransaction();
+ }
+ catch (Exception e)
+ {
+ tidyUpOnError(e);
+ }
+ }
+ }
+
+ public void enqueue(AMQQueue queue, EnqueableMessage message, Action postCommitAction)
+ {
+ if(message.isPersistent() && queue.isDurable())
+ {
+ beginTranIfNecessary();
+ try
+ {
+ _transaction.enqueueMessage(queue, message.getMessageNumber());
+ }
+ catch (Exception e)
+ {
+ tidyUpOnError(e);
+ }
+ }
+ _postCommitActions.add(postCommitAction);
+
+
+ }
+
+ public void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction)
+ {
+
+
+ if(message.isPersistent())
+ {
+ if(_transaction == null)
+ {
+ for(AMQQueue queue : queues)
+ {
+ if(queue.isDurable())
+ {
+ beginTranIfNecessary();
+ break;
+ }
+ }
+
+
+ }
+
+
+ try
+ {
+ for(AMQQueue queue : queues)
+ {
+ if(queue.isDurable())
+ {
+ _transaction.enqueueMessage(queue, message.getMessageNumber());
+ }
+ }
+
+ }
+ catch (Exception e)
+ {
+ tidyUpOnError(e);
+ }
+ }
+ _postCommitActions.add(postCommitAction);
+
+
+ }
+
+ public void commit()
+ {
+ try
+ {
+ if(_transaction != null)
+ {
+
+ _transaction.commitTran();
+ }
+
+ for(Action action : _postCommitActions)
+ {
+ action.postCommit();
+ }
+ }
+ catch (Exception e)
+ {
+ for(Action action : _postCommitActions)
+ {
+ action.onRollback();
+ }
+ //TODO
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ _transaction = null;
+ _postCommitActions.clear();
+ }
+
+ }
+
+ public void rollback()
+ {
+
+ try
+ {
+
+ if(_transaction != null)
+ {
+
+ _transaction.abortTran();
+ }
+ }
+ catch (AMQException e)
+ {
+ //TODO
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ try
+ {
+ for(Action action : _postCommitActions)
+ {
+ action.onRollback();
+ }
+ }
+ finally
+ {
+ _transaction = null;
+ _postCommitActions.clear();
+ }
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java
deleted file mode 100644
index 450852cef7..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java
+++ /dev/null
@@ -1,294 +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.txn;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.ack.TxAck;
-import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.*;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
-
-import java.util.List;
-import java.util.ArrayList;
-
-/** A transactional context that only supports local transactions. */
-public class LocalTransactionalContext implements TransactionalContext
-{
- private static final Logger _log = Logger.getLogger(LocalTransactionalContext.class);
-
- private final TxnBuffer _txnBuffer = new TxnBuffer();
-
- private final List<DeliveryAction> _postCommitDeliveryList = new ArrayList<DeliveryAction>();
-
- /**
- * We keep hold of the ack operation so that we can consolidate acks, i.e. multiple acks within a txn are
- * consolidated into a single operation
- */
- private TxAck _ackOp;
-
- private boolean _inTran = false;
-
- /** Are there messages to deliver. NOT Has the message been delivered */
- private boolean _messageDelivered = false;
- private final AMQChannel _channel;
-
-
- private abstract class DeliveryAction
- {
-
- abstract public void process() throws AMQException;
-
- }
-
- private class RequeueAction extends DeliveryAction
- {
- public QueueEntry entry;
-
- public RequeueAction(QueueEntry entry)
- {
- this.entry = entry;
- }
-
- public void process() throws AMQException
- {
- entry.requeue(getStoreContext());
- }
- }
-
- private class PublishAction extends DeliveryAction
- {
- private final AMQQueue _queue;
- private final AMQMessage _message;
-
- public PublishAction(final AMQQueue queue, final AMQMessage message)
- {
- _queue = queue;
- _message = message;
- }
-
- public void process() throws AMQException
- {
-
- _message.incrementReference();
- try
- {
- QueueEntry entry = _queue.enqueue(getStoreContext(),_message);
- _queue.checkCapacity(_channel);
-
- if(entry.immediateAndNotDelivered())
- {
- getReturnMessages().add(new NoConsumersException(_message));
- }
- }
- finally
- {
- _message.decrementReference(getStoreContext());
- }
- }
- }
-
- public LocalTransactionalContext(final AMQChannel channel)
- {
- _channel = channel;
- }
-
- public StoreContext getStoreContext()
- {
- return _channel.getStoreContext();
- }
-
- public List<RequiredDeliveryException> getReturnMessages()
- {
- return _channel.getReturnMessages();
- }
-
- public MessageStore getMessageStore()
- {
- return _channel.getMessageStore();
- }
-
-
- public void rollback() throws AMQException
- {
- _txnBuffer.rollback(getStoreContext());
- // Hack to deal with uncommitted non-transactional writes
- if (getMessageStore().inTran(getStoreContext()))
- {
- getMessageStore().abortTran(getStoreContext());
- _inTran = false;
- }
-
- _postCommitDeliveryList.clear();
- }
-
- public void deliver(final AMQQueue queue, AMQMessage message) throws AMQException
- {
- // A publication will result in the enlisting of several
- // TxnOps. The first is an op that will store the message.
- // Following that (and ordering is important), an op will
- // be added for every queue onto which the message is
- // enqueued.
- _postCommitDeliveryList.add(new PublishAction(queue, message));
- _messageDelivered = true;
-
- }
-
- public void requeue(QueueEntry entry) throws AMQException
- {
- _postCommitDeliveryList.add(new RequeueAction(entry));
- _messageDelivered = true;
-
- }
-
-
- private void checkAck(long deliveryTag, UnacknowledgedMessageMap unacknowledgedMessageMap) throws AMQException
- {
- if (!unacknowledgedMessageMap.contains(deliveryTag))
- {
- throw new AMQException("Ack with delivery tag " + deliveryTag + " not known for channel");
- }
- }
-
- public void acknowledgeMessage(long deliveryTag, long lastDeliveryTag, boolean multiple,
- UnacknowledgedMessageMap unacknowledgedMessageMap) throws AMQException
- {
- // check that the tag exists to give early failure
- if (!multiple || (deliveryTag > 0))
- {
- checkAck(deliveryTag, unacknowledgedMessageMap);
- }
- // we use a single txn op for all acks and update this op
- // as new acks come in. If this is the first ack in the txn
- // we will need to create and enlist the op.
- if (_ackOp == null)
- {
- _ackOp = new TxAck(unacknowledgedMessageMap);
- _txnBuffer.enlist(_ackOp);
- }
- // update the op to include this ack request
- if (multiple && (deliveryTag == 0))
- {
- // if have signalled to ack all, that refers only
- // to all at this time
- _ackOp.update(lastDeliveryTag, multiple);
- }
- else
- {
- _ackOp.update(deliveryTag, multiple);
- }
- if(!_inTran && _ackOp.checkPersistent())
- {
- beginTranIfNecessary();
- }
- }
-
- public void messageFullyReceived(boolean persistent) throws AMQException
- {
- // Not required in this transactional context
- }
-
- public void messageProcessed(AMQProtocolSession protocolSession) throws AMQException
- {
- // Not required in this transactional context
- }
-
- public void beginTranIfNecessary() throws AMQException
- {
- if (!_inTran)
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Starting transaction on message store: " + this);
- }
-
- getMessageStore().beginTran(getStoreContext());
- _inTran = true;
- }
- }
-
- public void commit() throws AMQException
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Committing transactional context: " + this);
- }
-
- if (_ackOp != null)
- {
-
- _messageDelivered = true;
- _ackOp.consolidate();
- // already enlisted, after commit will reset regardless of outcome
- _ackOp = null;
- }
-
- if (_messageDelivered && _inTran)
- {
- _txnBuffer.enlist(new StoreMessageOperation(getMessageStore()));
- }
- // fixme fail commit here ... QPID-440
- try
- {
- _txnBuffer.commit(getStoreContext());
- }
- finally
- {
- _messageDelivered = false;
- _inTran = getMessageStore().inTran(getStoreContext());
- }
-
- try
- {
- postCommitDelivery();
- }
- catch (AMQException e)
- {
- // OK so what do we do now...?
- _log.error("Failed to deliver messages following txn commit: " + e, e);
- }
- }
-
- private void postCommitDelivery() throws AMQException
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Performing post commit delivery");
- }
-
- try
- {
- for (DeliveryAction dd : _postCommitDeliveryList)
- {
- dd.process();
- }
- }
- finally
- {
- _postCommitDeliveryList.clear();
- }
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java
deleted file mode 100644
index 10d6021d27..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java
+++ /dev/null
@@ -1,215 +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.txn;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.*;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
-
-/** @author Apache Software Foundation */
-public class NonTransactionalContext implements TransactionalContext
-{
- private static final Logger _log = Logger.getLogger(NonTransactionalContext.class);
-
- /** Channel is useful for logging */
- private final AMQChannel _channel;
-
- /** Where to put undeliverable messages */
- private final List<RequiredDeliveryException> _returnMessages;
-
-
-
- private final MessageStore _messageStore;
-
- private final StoreContext _storeContext;
-
- /** Whether we are in a transaction */
- private boolean _inTran;
-
- public NonTransactionalContext(MessageStore messageStore, StoreContext storeContext, AMQChannel channel,
- List<RequiredDeliveryException> returnMessages)
- {
- _channel = channel;
- _storeContext = storeContext;
- _returnMessages = returnMessages;
- _messageStore = messageStore;
-
- }
-
-
- public StoreContext getStoreContext()
- {
- return _storeContext;
- }
-
- public void beginTranIfNecessary() throws AMQException
- {
- if (!_inTran)
- {
- _messageStore.beginTran(_storeContext);
- _inTran = true;
- }
- }
-
- public void commit() throws AMQException
- {
- // Does not apply to this context
- }
-
- public void rollback() throws AMQException
- {
- // Does not apply to this context
- }
-
- public void deliver(final AMQQueue queue, AMQMessage message) throws AMQException
- {
- QueueEntry entry = queue.enqueue(_storeContext, message);
- queue.checkCapacity(_channel);
-
-
- //following check implements the functionality
- //required by the 'immediate' flag:
- if(entry.immediateAndNotDelivered())
- {
- _returnMessages.add(new NoConsumersException(entry.getMessage()));
- }
-
- }
-
- public void requeue(QueueEntry entry) throws AMQException
- {
- entry.requeue(_storeContext);
- }
-
- public void acknowledgeMessage(final long deliveryTag, long lastDeliveryTag,
- boolean multiple, final UnacknowledgedMessageMap unacknowledgedMessageMap)
- throws AMQException
- {
-
- final boolean debug = _log.isDebugEnabled();
- ;
- if (multiple)
- {
- if (deliveryTag == 0)
- {
-
- //Spec 2.1.6.11 ... If the multiple field is 1, and the delivery tag is zero,
- // tells the server to acknowledge all outstanding mesages.
- _log.info("Multiple ack on delivery tag 0. ACKing all messages. Current count:" +
- unacknowledgedMessageMap.size());
- unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor()
- {
- public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException
- {
- if (debug)
- {
- _log.debug("Discarding message: " + message.getMessage().getMessageId());
- }
- if(message.getMessage().isPersistent())
- {
- beginTranIfNecessary();
- }
- //Message has been ack so discard it. This will dequeue and decrement the reference.
- message.discard(_storeContext);
-
- return false;
- }
-
- public void visitComplete()
- {
- unacknowledgedMessageMap.clear();
- }
- });
- }
- else
- {
- if (!unacknowledgedMessageMap.contains(deliveryTag))
- {
- throw new AMQException("Multiple ack on delivery tag " + deliveryTag + " not known for channel");
- }
-
- unacknowledgedMessageMap.drainTo(deliveryTag, _storeContext);
- }
- }
- else
- {
- QueueEntry msg;
- msg = unacknowledgedMessageMap.get(deliveryTag);
-
- if (msg == null)
- {
- _log.info("Single ack on delivery tag " + deliveryTag + " not known for channel:" +
- _channel.getChannelId());
- throw new AMQException("Single ack on delivery tag " + deliveryTag + " not known for channel:" +
- _channel.getChannelId());
- }
-
- if (debug)
- {
- _log.debug("Discarding message: " + msg.getMessage().getMessageId());
- }
- if(msg.getMessage().isPersistent())
- {
- beginTranIfNecessary();
- }
-
- //Message has been ack so discard it. This will dequeue and decrement the reference.
- msg.discard(_storeContext);
-
- unacknowledgedMessageMap.remove(deliveryTag);
-
-
- if (debug)
- {
- _log.debug("Received non-multiple ack for messaging with delivery tag " + deliveryTag + " msg id " +
- msg.getMessage().getMessageId());
- }
- }
- if(_inTran)
- {
- _messageStore.commitTran(_storeContext);
- _inTran = false;
- }
- }
-
- public void messageFullyReceived(boolean persistent) throws AMQException
- {
- if (persistent)
- {
- _messageStore.commitTran(_storeContext);
- _inTran = false;
- }
- }
-
- public void messageProcessed(AMQProtocolSession protocolSession) throws AMQException
- {
- _channel.processReturns();
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
new file mode 100755
index 0000000000..88bdc363c4
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.AMQChannel;
+
+import java.util.List;
+import java.util.SortedSet;
+import java.util.Collection;
+
+public interface ServerTransaction
+{
+
+ void addPostCommitAction(Action postCommitAction);
+
+
+
+
+ public static interface Action
+ {
+ public void postCommit();
+
+ public void onRollback();
+ }
+
+ void dequeue(AMQQueue queue, EnqueableMessage message, Action postCommitAction);
+
+ void dequeue(Collection<QueueEntry> ackedMessages, Action postCommitAction);
+
+ void enqueue(AMQQueue queue, EnqueableMessage message, Action postCommitAction);
+
+ void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction);
+
+
+ void commit();
+
+ void rollback();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/StoreMessageOperation.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/StoreMessageOperation.java
deleted file mode 100644
index 0e4d6c2030..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/StoreMessageOperation.java
+++ /dev/null
@@ -1,58 +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.txn;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
-
-/**
- * A transactional operation to store messages in an underlying persistent store. When this operation
- * commits it will do everything to ensure that all messages are safely committed to persistent
- * storage.
- */
-public class StoreMessageOperation implements TxnOp
-{
- private final MessageStore _messsageStore;
-
- public StoreMessageOperation(MessageStore messageStore)
- {
- _messsageStore = messageStore;
- }
-
- public void prepare(StoreContext context) throws AMQException
- {
- }
-
- public void undoPrepare()
- {
- }
-
- public void commit(StoreContext context) throws AMQException
- {
- _messsageStore.commitTran(context);
- }
-
- public void rollback(StoreContext context) throws AMQException
- {
- _messsageStore.abortTran(context);
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java
deleted file mode 100644
index 647ba66fb4..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java
+++ /dev/null
@@ -1,179 +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.txn;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.store.StoreContext;
-
-/**
- * TransactionalContext provides a context in which transactional operations on {@link AMQMessage}s are performed.
- * Different levels of transactional support for the delivery of messages may be provided by different implementations
- * of this interface.
- *
- * <p/>The fundamental transactional operations that can be performed on a message queue are 'enqueue' and 'dequeue'.
- * In this interface, these have been recast as the {@link #messageFullyReceived} and {@link #acknowledgeMessage}
- * operations. This interface essentially provides a way to make enqueueing and dequeuing transactional.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Explicitly accept a transaction start notification.
- * <tr><td> Commit all pending operations in a transaction.
- * <tr><td> Rollback all pending operations in a transaction.
- * <tr><td> Deliver a message to a queue as part of a transaction.
- * <tr><td> Redeliver a message to a queue as part of a transaction.
- * <tr><td> Mark a message as acknowledged as part of a transaction.
- * <tr><td> Accept notification that a message has been completely received as part of a transaction.
- * <tr><td> Accept notification that a message has been fully processed as part of a transaction.
- * <tr><td> Associate a message store context with this transaction context.
- * </table>
- *
- * @todo The 'fullyReceived' and 'messageProcessed' events sit uncomfortably in the responsibilities of a transactional
- * context. They are non-transactional operations, used to trigger other side-effects. Consider moving them
- * somewhere else, a seperate interface for example.
- *
- * @todo This transactional context could be written as a wrapper extension to a Queue implementation, that provides
- * transactional management of the enqueue and dequeue operations, with added commit/rollback methods. Any
- * queue implementation could be made transactional by wrapping it as a transactional queue. This would mean
- * that the enqueue/dequeue operations do not need to be recast as deliver/acknowledge operations, which may be
- * conceptually neater.
- *
- * For example:
- * <pre>
- * public interface Transactional
- * {
- * public void commit();
- * public void rollback();
- * }
- *
- * public interface TransactionalQueue<E> extends Transactional, SizeableQueue<E>
- * {}
- *
- * public class Queues
- * {
- * ...
- * // For transactional messaging, take a transactional view onto the queue.
- * public static <E> TransactionalQueue<E> getTransactionalQueue(SizeableQueue<E> queue) { ... }
- *
- * // For non-transactional messaging, take a non-transactional view onto the queue.
- * public static <E> TransactionalQueue<E> getNonTransactionalQueue(SizeableQueue<E> queue) { ... }
- * }
- * </pre>
- */
-public interface TransactionalContext
-{
- /**
- * Explicitly begins the transaction, if it has not already been started. {@link #commit} or {@link #rollback}
- * should automatically begin the next transaction in the chain.
- *
- * @throws AMQException If the transaction cannot be started for any reason.
- */
- void beginTranIfNecessary() throws AMQException;
-
- /**
- * Makes all pending operations on the transaction permanent and visible.
- *
- * @throws AMQException If the transaction cannot be committed for any reason.
- */
- void commit() throws AMQException;
-
- /**
- * Erases all pending operations on the transaction.
- *
- * @throws AMQException If the transaction cannot be committed for any reason.
- */
- void rollback() throws AMQException;
-
- /**
- * Delivers the specified message to the specified queue.
- *
- * <p/>This is an 'enqueue' operation.
- *
- * @param queue
- * @param message The message to deliver
- * @throws AMQException If the message cannot be delivered for any reason.
- */
- void deliver(final AMQQueue queue, AMQMessage message) throws AMQException;
-
- /**
- * Requeues the specified message entry (message queue pair)
- *
- *
- * @param queueEntry The message,queue pair
- *
- * @throws AMQException If the message cannot be delivered for any reason.
- */
- void requeue(QueueEntry queueEntry) throws AMQException;
-
-
- /**
- * Acknowledges a message or many messages as delivered. All messages up to a specified one, may be acknowledged by
- * setting the 'multiple' flag. It is also possible for the acknowledged message id to be zero, when the 'multiple'
- * flag is set, in which case an acknowledgement up to the latest delivered message should be done.
- *
- * <p/>This is a 'dequeue' operation.
- *
- * @param deliveryTag The id of the message to acknowledge, or zero, if using multiple acknowledgement
- * up to the latest message.
- * @param lastDeliveryTag The latest message delivered.
- * @param multiple <tt>true</tt> if all message ids up the acknowledged one or latest delivered, are
- * to be acknowledged, <tt>false</tt> otherwise.
- * @param unacknowledgedMessageMap The unacknowledged messages in the transaction, to remove the acknowledged message
- * from.
- *
- * @throws AMQException If the message cannot be acknowledged for any reason.
- */
- void acknowledgeMessage(long deliveryTag, long lastDeliveryTag, boolean multiple,
- UnacknowledgedMessageMap unacknowledgedMessageMap) throws AMQException;
-
- /**
- * Notifies the transactional context that a message has been fully received. The actual message that was received
- * is not specified. This event may be used to trigger a process related to the receipt of the message, for example,
- * flushing its data to disk.
- *
- * @param persistent <tt>true</tt> if the received message is persistent, <tt>false</tt> otherwise.
- *
- * @throws AMQException If the fully received event cannot be processed for any reason.
- */
- void messageFullyReceived(boolean persistent) throws AMQException;
-
- /**
- * Notifies the transactional context that a message has been delivered, succesfully or otherwise. The actual
- * message that was delivered is not specified. This event may be used to trigger a process related to the
- * outcome of the delivery of the message, for example, cleaning up failed deliveries.
- *
- * @param protocolSession The protocol session of the deliverable message.
- *
- * @throws AMQException If the message processed event cannot be handled for any reason.
- */
- void messageProcessed(AMQProtocolSession protocolSession) throws AMQException;
-
- /**
- * Gets the message store context associated with this transactional context.
- *
- * @return The message store context associated with this transactional context.
- */
- StoreContext getStoreContext();
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java
deleted file mode 100644
index 46a68b6a23..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.txn;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.store.StoreContext;
-
-/** Holds a list of TxnOp instance representing transactional operations. */
-public class TxnBuffer
-{
- private final List<TxnOp> _ops = new ArrayList<TxnOp>();
- private static final Logger _log = Logger.getLogger(TxnBuffer.class);
-
- public TxnBuffer()
- {
- }
-
- public void commit(StoreContext context) throws AMQException
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Committing " + _ops.size() + " ops to commit.:" + _ops);
- }
-
- if (prepare(context))
- {
- for (TxnOp op : _ops)
- {
- op.commit(context);
- }
- }
- _ops.clear();
- }
-
- private boolean prepare(StoreContext context) throws AMQException
- {
- for (int i = 0; i < _ops.size(); i++)
- {
- TxnOp op = _ops.get(i);
- try
- {
- op.prepare(context);
- }
- catch (AMQException e)
- {
- undoPrepare(i);
- throw e;
- }
- catch (RuntimeException e)
- {
- undoPrepare(i);
- throw e;
- }
- }
- return true;
- }
-
- private void undoPrepare(int lastPrepared)
- {
- //compensate previously prepared ops
- for (int j = 0; j < lastPrepared; j++)
- {
- _ops.get(j).undoPrepare();
- }
- }
-
-
-
- public void rollback(StoreContext context) throws AMQException
- {
- for (TxnOp op : _ops)
- {
- op.rollback(context);
- }
- _ops.clear();
- }
-
- public void enlist(TxnOp op)
- {
- _ops.add(op);
- }
-
- public void cancel(TxnOp op)
- {
- _ops.remove(op);
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnOp.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnOp.java
deleted file mode 100644
index 919c078cf0..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnOp.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.txn;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.store.StoreContext;
-
-/**
- * This provides the abstraction of an individual operation within a
- * transaction. It is used by the TxnBuffer class.
- */
-public interface TxnOp
-{
- /**
- * Do the part of the operation that updates persistent state
- */
- public void prepare(StoreContext context) throws AMQException;
- /**
- * Complete the operation started by prepare. Can now update in
- * memory state or make netork transfers.
- */
- public void commit(StoreContext context) throws AMQException;
- /**
- * This is not the same as rollback. Unfortunately the use of an
- * in memory reference count as a locking mechanism and a test for
- * whether a message should be deleted means that as things are,
- * handling an acknowledgement unavoidably alters both memory and
- * persistent state on prepare. This is needed to 'compensate' or
- * undo the in-memory change if the peristent update of later ops
- * fails.
- */
- public void undoPrepare();
- /**
- * Rolls back the operation.
- */
- public void rollback(StoreContext context) throws AMQException;
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
index 3b776a62b4..e4a382d275 100644..100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
@@ -1,624 +1,62 @@
/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
package org.apache.qpid.server.virtualhost;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.PropertiesConfiguration;
-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.abstraction.ContentChunk;
-import org.apache.qpid.server.AMQBrokerManagerMBean;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.messages.VirtualHostMessages;
-import org.apache.qpid.server.configuration.ExchangeConfiguration;
-import org.apache.qpid.server.configuration.QueueConfiguration;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
-import org.apache.qpid.server.connection.ConnectionRegistry;
import org.apache.qpid.server.connection.IConnectionRegistry;
-import org.apache.qpid.server.exchange.DefaultExchangeFactory;
-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.management.AMQManagedObject;
-import org.apache.qpid.server.management.ManagedObject;
-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.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.queue.MessageMetaData;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.access.ACLManager;
-import org.apache.qpid.server.security.access.Accessable;
-import org.apache.qpid.server.security.access.plugins.SimpleXML;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
-import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
+import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
-
-import javax.management.NotCompliantMBeanException;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Timer;
-import java.util.TimerTask;
+import org.apache.qpid.server.store.TransactionLog;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.access.ACLManager;
+import org.apache.qpid.server.management.ManagedObject;
-public class VirtualHost implements Accessable
+public interface VirtualHost
{
- private static final Logger _logger = Logger.getLogger(VirtualHost.class);
-
- private final String _name;
-
- private ConnectionRegistry _connectionRegistry;
-
- private QueueRegistry _queueRegistry;
-
- private ExchangeRegistry _exchangeRegistry;
-
- private ExchangeFactory _exchangeFactory;
-
- private MessageStore _messageStore;
-
- protected VirtualHostMBean _virtualHostMBean;
-
- private AMQBrokerManagerMBean _brokerMBean;
-
- private AuthenticationManager _authenticationManager;
-
- private ACLManager _accessManager;
-
- private final Timer _houseKeepingTimer;
- private VirtualHostConfiguration _configuration;
-
- public void setAccessableName(String name)
- {
- _logger.warn("Setting Accessable Name for VirualHost is not allowed. ("
- + name + ") ignored remains :" + getAccessableName());
- }
-
- public String getAccessableName()
- {
- return _name;
- }
-
- public IConnectionRegistry getConnectionRegistry()
- {
- return _connectionRegistry;
- }
-
- public VirtualHostConfiguration getConfiguration()
- {
- return _configuration;
- }
-
- /**
- * Abstract 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, ManagedVirtualHost.VERSION);
- }
-
- public String getObjectInstanceName()
- {
- return _name.toString();
- }
-
- public String getName()
- {
- return _name.toString();
- }
-
- public VirtualHost getVirtualHost()
- {
- return VirtualHost.this;
- }
-
- } // End of MBean class
-
- /**
- * Normal Constructor
- *
- * @param hostConfig
- *
- * @throws Exception
- */
- public VirtualHost(VirtualHostConfiguration hostConfig) throws Exception
- {
- this(hostConfig, null);
- }
-
- public VirtualHost(VirtualHostConfiguration hostConfig, MessageStore store) throws Exception
- {
- _configuration = hostConfig;
- _name = hostConfig.getName();
-
- CurrentActor.get().message(VirtualHostMessages.VHT_1001(_name));
-
- if (_name == null || _name.length() == 0)
- {
- throw new IllegalArgumentException("Illegal name (" + _name + ") for virtualhost.");
- }
-
- _virtualHostMBean = new VirtualHostMBean();
-
- _connectionRegistry = new ConnectionRegistry(this);
-
- _houseKeepingTimer = new Timer("Queue-housekeeping-" + _name, true);
-
- _queueRegistry = new DefaultQueueRegistry(this);
-
- _exchangeFactory = new DefaultExchangeFactory(this);
- _exchangeFactory.initialise(hostConfig);
-
- _exchangeRegistry = new DefaultExchangeRegistry(this);
-
- //Create a temporary RT to store the durable entries from the config file
- // so we can replay them 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
-
- StartupRoutingTable configFileRT = new StartupRoutingTable();
-
- _messageStore = configFileRT;
-
- // This needs to be after the RT has been defined as it creates the default durable exchanges.
- _exchangeRegistry.initialise();
-
- // We don't need to store the Default queues in the store as we always
- // create them first on start up so don't clear them from the startup
- // configuration here. This also ensures that we don't attempt to
- // perform a createExchange twice with the same details in the
- // MessageStore(RoutingTable) as some instances may not like that.
- // Derby being one.
- // todo this can be removed with the resolution fo QPID-2096
- configFileRT.exchange.clear();
-
- initialiseModel(hostConfig);
-
- //todo REMOVE Work Around for QPID-2096
- // This means that all durable exchanges declared in the configuration
- // will not be stored in the MessageStore.
- // They will still be created/registered/available on startup for as
- // long as they are contained in the configuration. However, when they
- // are removed from the configuration they will no longer exist.
- // This differs from durable queues as they will be writen to to the
- // store. After QPID-2096 has been resolved exchanges will mirror that
- // functionality.
- configFileRT.exchange.clear();
-
- if (store != null)
- {
- _messageStore = store;
- }
- else
- {
- if (hostConfig == null)
- {
- throw new IllegalAccessException("HostConfig and MessageStore cannot be null");
- }
- initialiseMessageStore(hostConfig);
- }
-
- //Now that the RT has been initialised loop through the persistent queues/exchanges created from the config
- // file and write them in to the new routing Table.
- for (StartupRoutingTable.CreateQueueTuple cqt : configFileRT.queue)
- {
- _messageStore.createQueue(cqt.queue, cqt.arguments);
- }
-
- for (Exchange exchange : configFileRT.exchange)
- {
- _messageStore.createExchange(exchange);
- }
-
- for (StartupRoutingTable.CreateBindingTuple cbt : configFileRT.bindings)
- {
- _messageStore.bindQueue(cbt.exchange, cbt.routingKey, cbt.queue, cbt.arguments);
- }
-
- _authenticationManager = new PrincipalDatabaseAuthenticationManager(_name, hostConfig);
-
- _accessManager = ApplicationRegistry.getInstance().getAccessManager();
- _accessManager.configureHostPlugins(hostConfig.getSecurityConfiguration());
-
- _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
- _brokerMBean.register();
- initialiseHouseKeeping(hostConfig.getHousekeepingExpiredMessageCheckPeriod());
- }
-
- private void initialiseHouseKeeping(long period)
- {
- /* add a timer task to iterate over queues, cleaning expired messages from queues with no consumers */
- if (period != 0L)
- {
- class RemoveExpiredMessagesTask extends TimerTask
- {
- public void run()
- {
- for (AMQQueue q : _queueRegistry.getQueues())
- {
-
- try
- {
- q.checkMessageStatus();
- }
- catch (AMQException e)
- {
- _logger.error("Exception in housekeeping for queue: " + q.getName().toString(), e);
- throw new RuntimeException(e);
- }
- }
- }
- }
-
- _houseKeepingTimer.scheduleAtFixedRate(new RemoveExpiredMessagesTask(),
- period / 2,
- period);
-
- class ForceChannelClosuresTask extends TimerTask
- {
- public void run()
- {
- _connectionRegistry.expireClosedChannels();
- }
- }
- }
- }
-
- private void initialiseMessageStore(VirtualHostConfiguration hostConfig) throws Exception
- {
- String messageStoreClass = hostConfig.getMessageStoreClass();
-
- Class clazz = Class.forName(messageStoreClass);
- Object o = clazz.newInstance();
-
- if (!(o instanceof MessageStore))
- {
- throw new ClassCastException("Message store class must implement " + MessageStore.class + ". Class " + clazz +
- " does not.");
- }
- MessageStore messageStore = (MessageStore) o;
- messageStore.configure(this, "store", hostConfig);
- _messageStore = messageStore;
- }
-
- private void initialiseModel(VirtualHostConfiguration config) throws ConfigurationException, AMQException
- {
- _logger.debug("Loading configuration for virtualhost: " + config.getName());
-
- List exchangeNames = config.getExchanges();
-
- for (Object exchangeNameObj : exchangeNames)
- {
- String exchangeName = String.valueOf(exchangeNameObj);
- configureExchange(config.getExchangeConfiguration(exchangeName));
- }
-
- String[] queueNames = config.getQueueNames();
-
- for (Object queueNameObj : queueNames)
- {
- String queueName = String.valueOf(queueNameObj);
- configureQueue(config.getQueueConfiguration(queueName));
- }
- }
-
- private void configureExchange(ExchangeConfiguration exchangeConfiguration) throws AMQException
- {
- 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();
-
- Exchange newExchange = _exchangeFactory.createExchange(exchangeName, type, durable, autodelete, 0);
- _exchangeRegistry.registerExchange(newExchange);
- }
- }
-
- private void configureQueue(QueueConfiguration queueConfiguration) throws AMQException, ConfigurationException
- {
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueConfiguration, this);
-
- if (queue.isDurable())
- {
- _messageStore.createQueue(queue);
- }
-
- String exchangeName = queueConfiguration.getExchange();
-
- Exchange exchange = _exchangeRegistry.getExchange(exchangeName == null ? null : new AMQShortString(exchangeName));
-
- if (exchange == null)
- {
- exchange = _exchangeRegistry.getDefaultExchange();
- }
-
- if (exchange == null)
- {
- throw new ConfigurationException("Attempt to bind queue to unknown exchange:" + exchangeName);
- }
-
- List routingKeys = queueConfiguration.getRoutingKeys();
- if (routingKeys == null || routingKeys.isEmpty())
- {
- routingKeys = Collections.singletonList(queue.getName());
- }
-
- for (Object routingKeyNameObj : routingKeys)
- {
- AMQShortString routingKey = new AMQShortString(String.valueOf(routingKeyNameObj));
- if (_logger.isInfoEnabled())
- {
- _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + this);
- }
- queue.bind(exchange, routingKey, null);
- }
-
- if (exchange != _exchangeRegistry.getDefaultExchange())
- {
- queue.bind(_exchangeRegistry.getDefaultExchange(), queue.getName(), null);
- }
- }
-
- public String getName()
- {
- return _name;
- }
-
- public QueueRegistry getQueueRegistry()
- {
- return _queueRegistry;
- }
-
- public ExchangeRegistry getExchangeRegistry()
- {
- return _exchangeRegistry;
- }
-
- public ExchangeFactory getExchangeFactory()
- {
- return _exchangeFactory;
- }
-
- public MessageStore getMessageStore()
- {
- return _messageStore;
- }
-
- public AuthenticationManager getAuthenticationManager()
- {
- return _authenticationManager;
- }
-
- public ACLManager getAccessManager()
- {
- return _accessManager;
- }
-
- public void close() throws Exception
- {
-
- //Stop Connections
- _connectionRegistry.close();
-
- //Stop the Queues processing
- if (_queueRegistry != null)
- {
- for (AMQQueue queue : _queueRegistry.getQueues())
- {
- queue.stop();
- }
- }
-
- //Stop Housekeeping
- if (_houseKeepingTimer != null)
- {
- _houseKeepingTimer.cancel();
- }
-
- //Close MessageStore
- if (_messageStore != null)
- {
- _messageStore.close();
- }
-
- CurrentActor.get().message(VirtualHostMessages.VHT_1002());
- }
-
- public ManagedObject getBrokerMBean()
- {
- return _brokerMBean;
- }
-
- public ManagedObject getManagedObject()
- {
- return _virtualHostMBean;
- }
-
- /**
- * Temporary Startup RT class to record the creation of persistent queues / exchanges.
- *
- *
- * 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
- */
- private class StartupRoutingTable implements MessageStore
- {
- public List<Exchange> exchange = new LinkedList<Exchange>();
- public List<CreateQueueTuple> queue = new LinkedList<CreateQueueTuple>();
- public List<CreateBindingTuple> bindings = new LinkedList<CreateBindingTuple>();
-
- public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception
- {
- }
-
- public void close() throws Exception
- {
- }
-
- public void removeMessage(StoreContext storeContext, Long messageId) throws AMQException
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public void createExchange(Exchange exchange) throws AMQException
- {
- if (exchange.isDurable())
- {
- this.exchange.add(exchange);
- }
- }
-
- public void removeExchange(Exchange exchange) throws AMQException
- {
- }
-
- public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
- {
- if (exchange.isDurable() && queue.isDurable())
- {
- bindings.add(new CreateBindingTuple(exchange, routingKey, queue, args));
- }
- }
-
- public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
- {
- }
-
- public void createQueue(AMQQueue queue) throws AMQException
- {
- createQueue(queue, null);
- }
-
- public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException
- {
- if (queue.isDurable())
- {
- this.queue.add(new CreateQueueTuple(queue, arguments));
- }
- }
-
- public void removeQueue(AMQQueue queue) throws AMQException
- {
- }
-
- public void enqueueMessage(StoreContext context, AMQQueue queue, Long messageId) throws AMQException
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public void dequeueMessage(StoreContext context, AMQQueue queue, Long messageId) throws AMQException
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public void beginTran(StoreContext context) throws AMQException
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public void commitTran(StoreContext context) throws AMQException
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
+ IConnectionRegistry getConnectionRegistry();
- public void abortTran(StoreContext context) throws AMQException
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
+ VirtualHostConfiguration getConfiguration();
- public boolean inTran(StoreContext context)
- {
- return false; //To change body of implemented methods use File | Settings | File Templates.
- }
+ String getName();
- public Long getNewMessageId()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
+ QueueRegistry getQueueRegistry();
- public void storeContentBodyChunk(StoreContext context, Long messageId, int index, ContentChunk contentBody, boolean lastContentBody) throws AMQException
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
+ ExchangeRegistry getExchangeRegistry();
- public void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData messageMetaData) throws AMQException
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
+ ExchangeFactory getExchangeFactory();
- public MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
+ MessageStore getMessageStore();
- public ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
+ TransactionLog getTransactionLog();
- public boolean isPersistent()
- {
- return false; //To change body of implemented methods use File | Settings | File Templates.
- }
+ DurableConfigurationStore getDurableConfigurationStore();
- private class CreateQueueTuple
- {
- public AMQQueue queue;
- public FieldTable arguments;
+ AuthenticationManager getAuthenticationManager();
- public CreateQueueTuple(AMQQueue queue, FieldTable arguments)
- {
- this.queue = queue;
- this.arguments = arguments;
- }
- }
+ ACLManager getAccessManager();
- private class CreateBindingTuple
- {
- public AMQQueue queue;
- public FieldTable arguments;
- public Exchange exchange;
- public AMQShortString routingKey;
+ void close() throws Exception;
- public CreateBindingTuple(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args)
- {
- this.exchange = exchange;
- this.routingKey = routingKey;
- this.queue = queue;
- arguments = args;
- }
- }
- }
+ ManagedObject getManagedObject();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
new file mode 100755
index 0000000000..7fa5a26436
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
@@ -0,0 +1,340 @@
+/*
+*
+* 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;
+
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreRecoveryHandler;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
+import org.apache.qpid.server.store.TransactionLog;
+import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.TransactionLogMessages;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.MessageTransferMessage;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.AMQException;
+
+import org.apache.log4j.Logger;
+
+import java.nio.ByteBuffer;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.TreeMap;
+
+public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHandler,
+ ConfigurationRecoveryHandler.QueueRecoveryHandler,
+ ConfigurationRecoveryHandler.ExchangeRecoveryHandler,
+ ConfigurationRecoveryHandler.BindingRecoveryHandler,
+ MessageStoreRecoveryHandler,
+ MessageStoreRecoveryHandler.StoredMessageRecoveryHandler,
+ TransactionLogRecoveryHandler,
+ TransactionLogRecoveryHandler.QueueEntryRecoveryHandler
+{
+ private static final Logger _logger = Logger.getLogger(VirtualHostConfigRecoveryHandler.class);
+
+
+ private final VirtualHost _virtualHost;
+
+ private MessageStoreLogSubject _logSubject;
+ private List<ProcessAction> _actions;
+
+ private MessageStore _store;
+ private TransactionLog _transactionLog;
+
+ private final Map<String, Integer> _queueRecoveries = new TreeMap<String, Integer>();
+ private Map<Long, ServerMessage> _recoveredMessages = new HashMap<Long, ServerMessage>();
+ private Map<Long, StoredMessage> _unusedMessages = new HashMap<Long, StoredMessage>();
+
+
+
+ public VirtualHostConfigRecoveryHandler(VirtualHost virtualHost)
+ {
+ _virtualHost = virtualHost;
+ }
+
+ public QueueRecoveryHandler begin(MessageStore store)
+ {
+ _logSubject = new MessageStoreLogSubject(_virtualHost,store);
+ _store = store;
+ CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1004(null, false));
+
+ return this;
+ }
+
+ public void queue(String queueName, String owner, FieldTable arguments)
+ {
+ AMQShortString queueNameShortString = new AMQShortString(queueName);
+
+ AMQQueue q = _virtualHost.getQueueRegistry().getQueue(queueNameShortString);
+
+ if (q == null)
+ {
+ q = AMQQueueFactory.createAMQQueueImpl(queueNameShortString, true, owner == null ? null : new AMQShortString(owner), false, _virtualHost,
+ arguments);
+ _virtualHost.getQueueRegistry().registerQueue(q);
+ }
+
+ CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1004(queueName, true));
+
+ //Record that we have a queue for recovery
+ _queueRecoveries.put(queueName, 0);
+ }
+
+ public ExchangeRecoveryHandler completeQueueRecovery()
+ {
+ return this;
+ }
+
+ public void exchange(String exchangeName, String type, boolean autoDelete)
+ {
+ try
+ {
+ Exchange exchange;
+ AMQShortString exchangeNameSS = new AMQShortString(exchangeName);
+ exchange = _virtualHost.getExchangeRegistry().getExchange(exchangeNameSS);
+ if (exchange == null)
+ {
+ exchange = _virtualHost.getExchangeFactory().createExchange(exchangeNameSS, new AMQShortString(type), true, autoDelete, 0);
+ _virtualHost.getExchangeRegistry().registerExchange(exchange);
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public BindingRecoveryHandler completeExchangeRecovery()
+ {
+ return this;
+ }
+
+ public StoredMessageRecoveryHandler begin()
+ {
+ // TODO - log begin
+ return this;
+ }
+
+ public void message(StoredMessage message)
+ {
+ ServerMessage serverMessage;
+ switch(message.getMetaData().getType())
+ {
+ case META_DATA_0_8:
+ serverMessage = new AMQMessage(message);
+ break;
+ case META_DATA_0_10:
+ serverMessage = new MessageTransferMessage(message, null);
+ break;
+ default:
+ throw new RuntimeException("Unknown message type retreived from store " + message.getMetaData().getClass());
+ }
+
+
+ _recoveredMessages.put(message.getMessageNumber(), serverMessage);
+ _unusedMessages.put(message.getMessageNumber(), message);
+ }
+
+ public void completeMessageRecovery()
+ {
+ //TODO - log end
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public TransactionLogRecoveryHandler.QueueEntryRecoveryHandler begin(TransactionLog log)
+ {
+ _transactionLog = log;
+ return this;
+ }
+
+ private static final class ProcessAction
+ {
+ private final AMQQueue _queue;
+ private final AMQMessage _message;
+
+ public ProcessAction(AMQQueue queue, AMQMessage message)
+ {
+ _queue = queue;
+ _message = message;
+ }
+
+ public void process()
+ {
+ try
+ {
+ _queue.enqueue(_message);
+ }
+ catch(AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+ public void binding(String exchangeName, String queueName, String bindingKey, ByteBuffer buf)
+ {
+ _actions = new ArrayList<ProcessAction>();
+ try
+ {
+ QueueRegistry queueRegistry = _virtualHost.getQueueRegistry();
+ Exchange exchange = _virtualHost.getExchangeRegistry().getExchange(exchangeName);
+ AMQQueue queue = queueRegistry.getQueue(new AMQShortString(queueName));
+ if (queue == null)
+ {
+ _logger.error("Unkown queue: " + queueName + " cannot be bound to exchange: "
+ + exchange.getName());
+ }
+ else
+ {
+
+
+ FieldTable argumentsFT = null;
+ if(buf != null)
+ {
+ argumentsFT = new FieldTable(org.apache.mina.common.ByteBuffer.wrap(buf),buf.limit());
+ }
+
+ _logger.info("Restoring binding: (Exchange: " + exchange.getName() + ", Queue: " + queueName
+ + ", Routing Key: " + bindingKey + ", Arguments: " + argumentsFT + ")");
+
+ queue.bind(exchange, bindingKey == null ? null : new AMQShortString(bindingKey), argumentsFT);
+
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public void completeBindingRecovery()
+ {
+ //return this;
+ }
+
+ public void complete()
+ {
+
+
+ }
+
+ public void queueEntry(final String queueName, long messageId)
+ {
+ AMQShortString queueNameShortString = new AMQShortString(queueName);
+
+ AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(queueNameShortString);
+
+ try
+ {
+ if(queue != null)
+ {
+ ServerMessage message = _recoveredMessages.get(messageId);
+ _unusedMessages.remove(messageId);
+
+ if(message != null)
+ {
+
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("On recovery, delivering " + message.getMessageNumber() + " to " + queue.getName());
+ }
+
+ Integer count = _queueRecoveries.get(queueName);
+ if (count == null)
+ {
+ count = 0;
+ }
+
+ queue.enqueue(message);
+
+ _queueRecoveries.put(queueName, ++count);
+ }
+ else
+ {
+ _logger.warn("Message id " + messageId + " referenced in log as enqueue in queue " + queue.getName() + " is unknwon, entry will be discarded");
+ TransactionLog.Transaction txn = _transactionLog.newTransaction();
+ txn.dequeueMessage(queue, messageId);
+ txn.commitTranAsync();
+ }
+ }
+ else
+ {
+ _logger.warn("Message id " + messageId + " in log references queue " + queueName + " which is not in the configuration, entry will be discarded");
+ TransactionLog.Transaction txn = _transactionLog.newTransaction();
+ TransactionLogResource mockQueue =
+ new TransactionLogResource()
+ {
+
+ public String getResourceName()
+ {
+ return queueName;
+ }
+ };
+ txn.dequeueMessage(mockQueue, messageId);
+ txn.commitTranAsync();
+ }
+
+ }
+ catch(AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+
+
+ }
+
+ public void 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.TXN_1005(entry.getValue(), entry.getKey()));
+
+ CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1006(entry.getKey(), true));
+ }
+
+ CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1006(null, false));
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
new file mode 100644
index 0000000000..c321fdf3e0
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
@@ -0,0 +1,608 @@
+/*
+ *
+ * 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;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.Configuration;
+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.server.AMQBrokerManagerMBean;
+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.logging.LogSubject;
+import org.apache.qpid.server.configuration.ExchangeConfiguration;
+import org.apache.qpid.server.configuration.QueueConfiguration;
+import org.apache.qpid.server.configuration.VirtualHostConfiguration;
+import org.apache.qpid.server.connection.ConnectionRegistry;
+import org.apache.qpid.server.connection.IConnectionRegistry;
+import org.apache.qpid.server.exchange.DefaultExchangeFactory;
+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.management.AMQManagedObject;
+import org.apache.qpid.server.management.ManagedObject;
+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.security.access.ACLManager;
+import org.apache.qpid.server.security.access.Accessable;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.store.TransactionLog;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
+
+import javax.management.NotCompliantMBeanException;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class VirtualHostImpl implements Accessable, VirtualHost
+{
+ private static final Logger _logger = Logger.getLogger(VirtualHostImpl.class);
+
+ private final String _name;
+
+ private ConnectionRegistry _connectionRegistry;
+
+ private QueueRegistry _queueRegistry;
+
+ private ExchangeRegistry _exchangeRegistry;
+
+ private ExchangeFactory _exchangeFactory;
+
+ private MessageStore _messageStore;
+
+ protected VirtualHostMBean _virtualHostMBean;
+
+ private AMQBrokerManagerMBean _brokerMBean;
+
+ private AuthenticationManager _authenticationManager;
+
+ private ACLManager _accessManager;
+
+ private final Timer _houseKeepingTimer;
+ private VirtualHostConfiguration _configuration;
+ private DurableConfigurationStore _durableConfigurationStore;
+
+ public void setAccessableName(String name)
+ {
+ _logger.warn("Setting Accessable Name for VirualHost is not allowed. ("
+ + name + ") ignored remains :" + getAccessableName());
+ }
+
+ public String getAccessableName()
+ {
+ return _name;
+ }
+
+ public IConnectionRegistry getConnectionRegistry()
+ {
+ return _connectionRegistry;
+ }
+
+ public VirtualHostConfiguration getConfiguration()
+ {
+ return _configuration;
+ }
+
+ /**
+ * Abstract 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, ManagedVirtualHost.VERSION);
+ }
+
+ public String getObjectInstanceName()
+ {
+ return _name.toString();
+ }
+
+ public String getName()
+ {
+ return _name.toString();
+ }
+
+ public VirtualHostImpl getVirtualHost()
+ {
+ return VirtualHostImpl.this;
+ }
+
+ } // End of MBean class
+
+ /**
+ * Normal Constructor
+ *
+ * @param hostConfig
+ *
+ * @throws Exception
+ */
+ public VirtualHostImpl(VirtualHostConfiguration hostConfig) throws Exception
+ {
+ this(hostConfig, null);
+ }
+
+ public VirtualHostImpl(VirtualHostConfiguration hostConfig, MessageStore store) throws Exception
+ {
+ _configuration = hostConfig;
+ _name = hostConfig.getName();
+
+ CurrentActor.get().message(VirtualHostMessages.VHT_1001(_name));
+
+ if (_name == null || _name.length() == 0)
+ {
+ throw new IllegalArgumentException("Illegal name (" + _name + ") for virtualhost.");
+ }
+
+ _virtualHostMBean = new VirtualHostMBean();
+
+ _connectionRegistry = new ConnectionRegistry(this);
+
+ _houseKeepingTimer = new Timer("Queue-housekeeping-" + _name, true);
+
+ _queueRegistry = new DefaultQueueRegistry(this);
+
+ _exchangeFactory = new DefaultExchangeFactory(this);
+ _exchangeFactory.initialise(hostConfig);
+
+ _exchangeRegistry = new DefaultExchangeRegistry(this);
+
+ //Create a temporary RT to store the durable entries from the config file
+ // so we can replay them 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
+
+ StartupRoutingTable configFileRT = new StartupRoutingTable();
+
+ _durableConfigurationStore = configFileRT;
+
+ // This needs to be after the RT has been defined as it creates the default durable exchanges.
+ _exchangeRegistry.initialise();
+
+ // We don't need to store the Default queues in the store as we always
+ // create them first on start up so don't clear them from the startup
+ // configuration here. This also ensures that we don't attempt to
+ // perform a createExchange twice with the same details in the
+ // MessageStore(RoutingTable) as some instances may not like that.
+ // Derby being one.
+ // todo this can be removed with the resolution fo QPID-2096
+ configFileRT.exchange.clear();
+
+ initialiseModel(hostConfig);
+
+ //todo REMOVE Work Around for QPID-2096
+ // This means that all durable exchanges declared in the configuration
+ // will not be stored in the MessageStore.
+ // They will still be created/registered/available on startup for as
+ // long as they are contained in the configuration. However, when they
+ // are removed from the configuration they will no longer exist.
+ // This differs from durable queues as they will be writen to to the
+ // store. After QPID-2096 has been resolved exchanges will mirror that
+ // functionality.
+ configFileRT.exchange.clear();
+
+ if (store != null)
+ {
+ _messageStore = store;
+ _durableConfigurationStore = store;
+ }
+ else
+ {
+ if (hostConfig == null)
+ {
+ throw new IllegalAccessException("HostConfig and MessageStore cannot be null");
+ }
+ initialiseMessageStore(hostConfig);
+ }
+
+ //Now that the RT has been initialised loop through the persistent queues/exchanges created from the config
+ // file and write them in to the new routing Table.
+ for (StartupRoutingTable.CreateQueueTuple cqt : configFileRT.queue)
+ {
+ getDurableConfigurationStore().createQueue(cqt.queue, cqt.arguments);
+ }
+
+ for (Exchange exchange : configFileRT.exchange)
+ {
+ getDurableConfigurationStore().createExchange(exchange);
+ }
+
+ for (StartupRoutingTable.CreateBindingTuple cbt : configFileRT.bindings)
+ {
+ getDurableConfigurationStore().bindQueue(cbt.exchange, cbt.routingKey, cbt.queue, cbt.arguments);
+ }
+
+ _authenticationManager = new PrincipalDatabaseAuthenticationManager(_name, hostConfig);
+
+ _accessManager = ApplicationRegistry.getInstance().getAccessManager();
+ _accessManager.configureHostPlugins(hostConfig.getSecurityConfiguration());
+
+ _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
+ _brokerMBean.register();
+ initialiseHouseKeeping(hostConfig.getHousekeepingExpiredMessageCheckPeriod());
+ }
+
+ private void initialiseHouseKeeping(long period)
+ {
+ /* add a timer task to iterate over queues, cleaning expired messages from queues with no consumers */
+ if (period != 0L)
+ {
+ class RemoveExpiredMessagesTask extends TimerTask
+ {
+ public void run()
+ {
+ for (AMQQueue q : _queueRegistry.getQueues())
+ {
+
+ try
+ {
+ q.checkMessageStatus();
+ }
+ catch (AMQException e)
+ {
+ _logger.error("Exception in housekeeping for queue: " + q.getName().toString(), e);
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+
+ _houseKeepingTimer.scheduleAtFixedRate(new RemoveExpiredMessagesTask(),
+ period / 2,
+ period);
+
+ class ForceChannelClosuresTask extends TimerTask
+ {
+ public void run()
+ {
+ _connectionRegistry.expireClosedChannels();
+ }
+ }
+ }
+ }
+
+ private void initialiseMessageStore(VirtualHostConfiguration hostConfig) throws Exception
+ {
+ String messageStoreClass = hostConfig.getMessageStoreClass();
+
+ Class clazz = Class.forName(messageStoreClass);
+ Object o = clazz.newInstance();
+
+ if (!(o instanceof MessageStore))
+ {
+ throw new ClassCastException("Message store class must implement " + MessageStore.class + ". Class " + clazz +
+ " does not.");
+ }
+ MessageStore messageStore = (MessageStore) o;
+ VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(this);
+
+ MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, messageStore);
+
+ messageStore.configureConfigStore(this.getName(),
+ recoveryHandler,
+ hostConfig.getStoreConfiguration(),
+ storeLogSubject);
+
+ messageStore.configureMessageStore(this.getName(),
+ recoveryHandler,
+ hostConfig.getStoreConfiguration(),
+ storeLogSubject);
+ messageStore.configureTransactionLog(this.getName(),
+ recoveryHandler,
+ hostConfig.getStoreConfiguration(),
+ storeLogSubject);
+
+ _messageStore = messageStore;
+ _durableConfigurationStore = messageStore;
+ }
+
+ private void initialiseModel(VirtualHostConfiguration config) throws ConfigurationException, AMQException
+ {
+ _logger.debug("Loading configuration for virtualhost: " + config.getName());
+
+ List exchangeNames = config.getExchanges();
+
+ for (Object exchangeNameObj : exchangeNames)
+ {
+ String exchangeName = String.valueOf(exchangeNameObj);
+ configureExchange(config.getExchangeConfiguration(exchangeName));
+ }
+
+ String[] queueNames = config.getQueueNames();
+
+ for (Object queueNameObj : queueNames)
+ {
+ String queueName = String.valueOf(queueNameObj);
+ configureQueue(config.getQueueConfiguration(queueName));
+ }
+ }
+
+ private void configureExchange(ExchangeConfiguration exchangeConfiguration) throws AMQException
+ {
+ 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();
+
+ Exchange newExchange = _exchangeFactory.createExchange(exchangeName, type, durable, autodelete, 0);
+ _exchangeRegistry.registerExchange(newExchange);
+ }
+ }
+
+ private void configureQueue(QueueConfiguration queueConfiguration) throws AMQException, ConfigurationException
+ {
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueConfiguration, this);
+
+ if (queue.isDurable())
+ {
+ getDurableConfigurationStore().createQueue(queue);
+ }
+
+ String exchangeName = queueConfiguration.getExchange();
+
+ Exchange exchange = _exchangeRegistry.getExchange(exchangeName == null ? null : new AMQShortString(exchangeName));
+
+ if (exchange == null)
+ {
+ exchange = _exchangeRegistry.getDefaultExchange();
+ }
+
+ if (exchange == null)
+ {
+ throw new ConfigurationException("Attempt to bind queue to unknown exchange:" + exchangeName);
+ }
+
+ List routingKeys = queueConfiguration.getRoutingKeys();
+ if (routingKeys == null || routingKeys.isEmpty())
+ {
+ routingKeys = Collections.singletonList(queue.getName());
+ }
+
+ for (Object routingKeyNameObj : routingKeys)
+ {
+ AMQShortString routingKey = new AMQShortString(String.valueOf(routingKeyNameObj));
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + this);
+ }
+ queue.bind(exchange, routingKey, null);
+ }
+
+ if (exchange != _exchangeRegistry.getDefaultExchange())
+ {
+ queue.bind(_exchangeRegistry.getDefaultExchange(), queue.getName(), null);
+ }
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public QueueRegistry getQueueRegistry()
+ {
+ return _queueRegistry;
+ }
+
+ public ExchangeRegistry getExchangeRegistry()
+ {
+ return _exchangeRegistry;
+ }
+
+ public ExchangeFactory getExchangeFactory()
+ {
+ return _exchangeFactory;
+ }
+
+ public MessageStore getMessageStore()
+ {
+ return _messageStore;
+ }
+
+ public TransactionLog getTransactionLog()
+ {
+ return _messageStore;
+ }
+
+ public DurableConfigurationStore getDurableConfigurationStore()
+ {
+ return _durableConfigurationStore;
+ }
+
+ public AuthenticationManager getAuthenticationManager()
+ {
+ return _authenticationManager;
+ }
+
+ public ACLManager getAccessManager()
+ {
+ return _accessManager;
+ }
+
+ public void close() throws Exception
+ {
+
+ //Stop Connections
+ _connectionRegistry.close();
+
+ //Stop the Queues processing
+ if (_queueRegistry != null)
+ {
+ for (AMQQueue queue : _queueRegistry.getQueues())
+ {
+ queue.stop();
+ }
+ }
+
+ //Stop Housekeeping
+ if (_houseKeepingTimer != null)
+ {
+ _houseKeepingTimer.cancel();
+ }
+
+ //Close MessageStore
+ if (_messageStore != null)
+ {
+ _messageStore.close();
+ }
+
+ CurrentActor.get().message(VirtualHostMessages.VHT_1002());
+ }
+
+ public ManagedObject getBrokerMBean()
+ {
+ return _brokerMBean;
+ }
+
+ public ManagedObject getManagedObject()
+ {
+ return _virtualHostMBean;
+ }
+
+ /**
+ * Temporary Startup RT class to record the creation of persistent queues / exchanges.
+ *
+ *
+ * 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
+ */
+ private class StartupRoutingTable implements DurableConfigurationStore
+ {
+ public List<Exchange> exchange = new LinkedList<Exchange>();
+ public List<CreateQueueTuple> queue = new LinkedList<CreateQueueTuple>();
+ public List<CreateBindingTuple> bindings = new LinkedList<CreateBindingTuple>();
+
+ public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception
+ {
+ }
+
+ public void close() throws Exception
+ {
+ }
+
+ public void removeMessage(Long messageId) throws AMQException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void configureConfigStore(String name,
+ ConfigurationRecoveryHandler recoveryHandler,
+ Configuration config,
+ LogSubject logSubject) throws Exception
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void createExchange(Exchange exchange) throws AMQException
+ {
+ if (exchange.isDurable())
+ {
+ this.exchange.add(exchange);
+ }
+ }
+
+ public void removeExchange(Exchange exchange) throws AMQException
+ {
+ }
+
+ public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
+ {
+ if (exchange.isDurable() && queue.isDurable())
+ {
+ bindings.add(new CreateBindingTuple(exchange, routingKey, queue, args));
+ }
+ }
+
+ public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
+ {
+ }
+
+ public void createQueue(AMQQueue queue) throws AMQException
+ {
+ createQueue(queue, null);
+ }
+
+ public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException
+ {
+ if (queue.isDurable())
+ {
+ this.queue.add(new CreateQueueTuple(queue, arguments));
+ }
+ }
+
+ public void removeQueue(AMQQueue queue) throws AMQException
+ {
+ }
+
+
+ private class CreateQueueTuple
+ {
+ public AMQQueue queue;
+ public FieldTable arguments;
+
+ public CreateQueueTuple(AMQQueue queue, FieldTable arguments)
+ {
+ this.queue = queue;
+ this.arguments = arguments;
+ }
+ }
+
+ private class CreateBindingTuple
+ {
+ public AMQQueue queue;
+ public FieldTable arguments;
+ public Exchange exchange;
+ public AMQShortString routingKey;
+
+ public CreateBindingTuple(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args)
+ {
+ this.exchange = exchange;
+ this.routingKey = routingKey;
+ this.queue = queue;
+ arguments = args;
+ }
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return _name;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
index 5543adbeb5..b86e0d0baf 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
@@ -21,7 +21,6 @@
package org.apache.qpid.server.virtualhost;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
import java.util.ArrayList;
import java.util.Collection;
@@ -31,7 +30,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class VirtualHostRegistry
{
- private final Map<String, VirtualHost> _registry = new ConcurrentHashMap<String,VirtualHost>();
+ private final Map<String, VirtualHost> _registry = new ConcurrentHashMap<String, VirtualHost>();
private String _defaultVirtualHostName;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java
index 0869d9a497..ef3599bdc8 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java
@@ -14,14 +14,16 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.tools.messagestore.commands;
import org.apache.qpid.tools.messagestore.MessageStoreTool;
import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.LocalTransaction;
public class Copy extends Move
{
@@ -49,7 +51,9 @@ public class Copy extends Move
protected void doCommand(AMQQueue fromQueue, long start, long end, AMQQueue toQueue)
{
- fromQueue.copyMessagesToAnotherQueue(start, end, toQueue.getName().toString(), _storeContext);
+ ServerTransaction txn = new LocalTransaction(fromQueue.getVirtualHost().getTransactionLog());
+ fromQueue.copyMessagesToAnotherQueue(start, end, toQueue.getName().toString(), txn);
+ txn.commit();
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java
index 731f6140f9..a7d58dc6dd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java
@@ -21,16 +21,13 @@
package org.apache.qpid.tools.messagestore.commands;
import org.apache.commons.codec.binary.Hex;
-import org.apache.mina.common.ByteBuffer;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.QueueEntryImpl;
import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.tools.messagestore.MessageStoreTool;
import org.apache.qpid.tools.utils.Console;
import java.io.UnsupportedEncodingException;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -100,7 +97,7 @@ public class Dump extends Show
for (QueueEntry entry : messages)
{
- AMQMessage msg = entry.getMessage();
+ ServerMessage msg = entry.getMessage();
if (!includeMsg(msg, msgids))
{
continue;
@@ -112,7 +109,7 @@ public class Dump extends Show
// Show general message information
hex.add(Show.Columns.ID.name());
- ascii.add(msg.getMessageId().toString());
+ ascii.add(msg.getMessageNumber().toString());
hex.add(Console.ROW_DIVIDER);
ascii.add(Console.ROW_DIVIDER);
@@ -136,10 +133,10 @@ public class Dump extends Show
hex.add(Console.ROW_DIVIDER);
ascii.add(Console.ROW_DIVIDER);
- Iterator bodies = msg.getContentBodyIterator();
- if (bodies.hasNext())
- {
+ final int messageSize = (int) msg.getSize();
+ if (messageSize != 0)
+ {
hex.add("Hex");
hex.add(Console.ROW_DIVIDER);
@@ -147,14 +144,19 @@ public class Dump extends Show
ascii.add("ASCII");
ascii.add(Console.ROW_DIVIDER);
- while (bodies.hasNext())
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(64 * 1024);
+
+ int position = 0;
+
+ while(position < messageSize)
{
- ContentChunk chunk = (ContentChunk) bodies.next();
+ position += msg.getContent(buf, position);
+ buf.flip();
//Duplicate so we don't destroy original data :)
- ByteBuffer hexBuffer = chunk.getData().duplicate();
+ java.nio.ByteBuffer hexBuffer = buf;
- ByteBuffer charBuffer = hexBuffer.duplicate();
+ java.nio.ByteBuffer charBuffer = hexBuffer.duplicate();
Hex hexencoder = new Hex();
@@ -232,6 +234,7 @@ public class Dump extends Show
ascii.add(asciiLine);
}
+ buf.clear();
}
}
else
@@ -252,7 +255,7 @@ public class Dump extends Show
return display;
}
- private void addShowInformation(List<String> column1, List<String> column2, AMQMessage msg,
+ private void addShowInformation(List<String> column1, List<String> column2, ServerMessage msg,
String title, boolean routing, boolean headers, boolean messageHeaders)
{
List<QueueEntry> single = new LinkedList<QueueEntry>();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java
index df8b59ec19..ab8e781df5 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java
@@ -14,9 +14,9 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.tools.messagestore.commands;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java
index a8dd58ca83..6a5e2a6025 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java
@@ -14,17 +14,17 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.tools.messagestore.commands;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.queue.QueueEntryImpl;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.tools.messagestore.MessageStoreTool;
import java.util.LinkedList;
@@ -33,12 +33,6 @@ import java.util.List;
public class Move extends AbstractCommand
{
- /**
- * Since the Coopy command is not associated with a real channel we can safely create our own store context
- * for use in the few methods that require one.
- */
- protected StoreContext _storeContext = new StoreContext();
-
public Move(MessageStoreTool tool)
{
super(tool);
@@ -172,7 +166,7 @@ public class Move extends AbstractCommand
{
for (QueueEntry msg : messages)
{
- ids.add(msg.getMessage().getMessageId());
+ ids.add(msg.getMessage().getMessageNumber());
}
}
}
@@ -201,6 +195,8 @@ public class Move extends AbstractCommand
protected void doCommand(AMQQueue fromQueue, long start, long id, AMQQueue toQueue)
{
- fromQueue.moveMessagesToAnotherQueue(start, id, toQueue.getName().toString(), _storeContext);
+ ServerTransaction txn = new LocalTransaction(fromQueue.getVirtualHost().getTransactionLog());
+ fromQueue.moveMessagesToAnotherQueue(start, id, toQueue.getName().toString(), txn);
+ txn.commit();
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java
index 5e99997863..8df4afa2db 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java
@@ -62,6 +62,6 @@ public class Purge extends Move
protected void doCommand(AMQQueue fromQueue, long start, long end, AMQQueue toQueue)
{
- fromQueue.removeMessagesFromQueue(start, end, _storeContext);
+ fromQueue.removeMessagesFromQueue(start, end);
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
index 2fa017fc64..4fd4999b19 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
@@ -25,10 +25,10 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.QueueEntryImpl;
+import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.tools.messagestore.MessageStoreTool;
import org.apache.qpid.tools.utils.Console;
@@ -171,7 +171,7 @@ public class Show extends AbstractCommand
// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getEncoding();
// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getExpiration();
// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getHeaders();
-// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getMessageId();
+// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getMessageNumber();
// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getPriority();
// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getPropertyFlags();
// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getReplyTo();
@@ -182,14 +182,14 @@ public class Show extends AbstractCommand
// //Print out all the property names
// ((BasicContentHeaderProperties)msg.getContentHeaderBody().properties).getHeaders().getPropertyNames();
//
-// msg.getMessageId();
+// msg.getMessageNumber();
// msg.getSize();
// msg.getArrivalTime();
// msg.getDeliveredSubscription();
// msg.getDeliveredToConsumer();
// msg.getMessageHandle();
-// msg.getMessageId();
+// msg.getMessageNumber();
// msg.getMessagePublishInfo();
// msg.getPublisher();
@@ -337,30 +337,24 @@ public class Show extends AbstractCommand
//Add create the table of data
for (QueueEntry entry : messages)
{
- AMQMessage msg = entry.getMessage();
+ ServerMessage msg = entry.getMessage();
if (!includeMsg(msg, msgids))
{
continue;
}
- id.add(msg.getMessageId().toString());
+ id.add(msg.getMessageNumber().toString());
size.add("" + msg.getSize());
arrival.add("" + msg.getArrivalTime());
- try
- {
- ispersitent.add(msg.isPersistent() ? "true" : "false");
- }
- catch (AMQException e)
- {
- ispersitent.add("n/a");
- }
+ ispersitent.add(msg.isPersistent() ? "true" : "false");
+
- isredelivered.add(msg.isRedelivered() ? "true" : "false");
+ isredelivered.add(entry.isRedelivered() ? "true" : "false");
- isdelivered.add(msg.getDeliveredToConsumer() ? "true" : "false");
+ isdelivered.add(entry.getDeliveredToConsumer() ? "true" : "false");
// msg.getMessageHandle();
@@ -368,7 +362,10 @@ public class Show extends AbstractCommand
try
{
- headers = ((BasicContentHeaderProperties) msg.getContentHeaderBody().properties);
+ if(msg instanceof AMQMessage)
+ {
+ headers = ((BasicContentHeaderProperties) ((AMQMessage)msg).getContentHeaderBody().properties);
+ }
}
catch (AMQException e)
{
@@ -417,7 +414,11 @@ public class Show extends AbstractCommand
MessagePublishInfo info = null;
try
{
- info = msg.getMessagePublishInfo();
+ if(msg instanceof AMQMessage)
+ {
+ info = ((AMQMessage)msg).getMessagePublishInfo();
+ }
+
}
catch (AMQException e)
{
@@ -457,14 +458,14 @@ public class Show extends AbstractCommand
return data;
}
- protected boolean includeMsg(AMQMessage msg, List<Long> msgids)
+ protected boolean includeMsg(ServerMessage msg, List<Long> msgids)
{
if (msgids == null)
{
return true;
}
- Long msgid = msg.getMessageId();
+ Long msgid = msg.getMessageNumber();
boolean found = false;
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
index e3889162ad..3cdb9c0c2d 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
@@ -27,6 +27,7 @@ import org.apache.qpid.server.exchange.ExchangeRegistry;
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.virtualhost.VirtualHostImpl;
import org.apache.qpid.server.virtualhost.VirtualHost;
public class AMQBrokerManagerMBeanTest extends TestCase
@@ -46,7 +47,7 @@ public class AMQBrokerManagerMBeanTest extends TestCase
assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) == null);
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHost.VirtualHostMBean) _vHost.getManagedObject());
+ ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
mbean.createNewExchange(exchange1, "direct", false);
mbean.createNewExchange(exchange2, "topic", false);
mbean.createNewExchange(exchange3, "headers", false);
@@ -68,7 +69,7 @@ public class AMQBrokerManagerMBeanTest extends TestCase
{
String queueName = "testQueue_" + System.currentTimeMillis();
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHost.VirtualHostMBean) _vHost.getManagedObject());
+ ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) == null);
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java
index 105056fe3d..d2408ba21f 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java
@@ -22,23 +22,22 @@ package org.apache.qpid.server;
import junit.framework.TestCase;
import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl;
-import org.apache.qpid.server.queue.MockQueueEntry;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.queue.SimpleQueueEntryList;
import org.apache.qpid.server.queue.MockAMQMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.MockAMQQueue;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.queue.QueueEntryIterator;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.subscription.MockSubscription;
+import org.apache.qpid.server.store.MemoryMessageStore;
+import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.AMQException;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.LinkedList;
-import java.util.Iterator;
/**
* QPID-1385 : Race condition between added to unacked map and resending due to a rollback.
@@ -63,6 +62,7 @@ public class ExtractResendAndRequeueTest extends TestCase
UnacknowledgedMessageMapImpl _unacknowledgedMessageMap;
private static final int INITIAL_MSG_COUNT = 10;
private AMQQueue _queue = new MockAMQQueue(getName());
+ private MessageStore _messageStore = new MemoryMessageStore();
private LinkedList<QueueEntry> _referenceList = new LinkedList<QueueEntry>();
@Override
@@ -89,7 +89,7 @@ public class ExtractResendAndRequeueTest extends TestCase
while(queueEntries.advance())
{
QueueEntry entry = queueEntries.getNode();
- _unacknowledgedMessageMap.add(entry.getMessage().getMessageId(), entry);
+ _unacknowledgedMessageMap.add(entry.getMessage().getMessageNumber(), entry);
// Store the entry for future inspection
_referenceList.add(entry);
@@ -137,7 +137,7 @@ public class ExtractResendAndRequeueTest extends TestCase
// requeueIfUnabletoResend doesn't matter here.
_unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, true, new StoreContext()));
+ msgToResend, true, _messageStore));
assertEquals("Message count for resend not correct.", INITIAL_MSG_COUNT, msgToResend.size());
assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size());
@@ -166,7 +166,7 @@ public class ExtractResendAndRequeueTest extends TestCase
// requeueIfUnabletoResend doesn't matter here.
_unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, true, new StoreContext()));
+ msgToResend, true, _messageStore));
assertEquals("Message count for resend not correct.", 0, msgToResend.size());
assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size());
@@ -187,7 +187,7 @@ public class ExtractResendAndRequeueTest extends TestCase
// requeueIfUnabletoResend = true so all messages should go to msgToRequeue
_unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, true, new StoreContext()));
+ msgToResend, true, _messageStore));
assertEquals("Message count for resend not correct.", 0, msgToResend.size());
assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size());
@@ -208,7 +208,7 @@ public class ExtractResendAndRequeueTest extends TestCase
// requeueIfUnabletoResend = false so all messages should be dropped all maps should be empty
_unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, false, new StoreContext()));
+ msgToResend, false, _messageStore));
assertEquals("Message count for resend not correct.", 0, msgToResend.size());
assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size());
@@ -240,7 +240,7 @@ public class ExtractResendAndRequeueTest extends TestCase
// requeueIfUnabletoResend : value doesn't matter here as queue has been deleted
_unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue,
- msgToResend, false, new StoreContext()));
+ msgToResend, false, _messageStore));
assertEquals("Message count for resend not correct.", 0, msgToResend.size());
assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size());
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/TxAckTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/TxAckTest.java
deleted file mode 100644
index 06d6b6de8b..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/TxAckTest.java
+++ /dev/null
@@ -1,290 +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.ack;
-
-import junit.framework.TestCase;
-
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.MessageHandleFactory;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.queue.AMQMessageHandle;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.store.TestMemoryMessageStore;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.store.MemoryMessageStore;
-import org.apache.qpid.server.txn.NonTransactionalContext;
-import org.apache.qpid.server.txn.TransactionalContext;
-
-import java.util.*;
-
-public class TxAckTest extends TestCase
-{
- private Scenario individual;
- private Scenario multiple;
- private Scenario combined;
-
- protected void setUp() throws Exception
- {
- super.setUp();
-
-
- // Highlight that this test will cause the creation of an AR
- ApplicationRegistry.getInstance();
-
- //ack only 5th msg
- individual = new Scenario(10, Arrays.asList(5l), Arrays.asList(1l, 2l, 3l, 4l, 6l, 7l, 8l, 9l, 10l));
- individual.update(5, false);
-
- //ack all up to and including 5th msg
- multiple = new Scenario(10, Arrays.asList(1l, 2l, 3l, 4l, 5l), Arrays.asList(6l, 7l, 8l, 9l, 10l));
- multiple.update(5, true);
-
- //leave only 8th and 9th unacked
- combined = new Scenario(10, Arrays.asList(1l, 2l, 3l, 4l, 5l, 6l, 7l, 10l), Arrays.asList(8l, 9l));
- combined.update(3, false);
- combined.update(5, true);
- combined.update(7, true);
- combined.update(2, true);//should be ignored
- combined.update(1, false);//should be ignored
- combined.update(10, false);
- }
-
- @Override
- protected void tearDown() throws Exception
- {
- individual.stop();
- multiple.stop();
- combined.stop();
-
- // Ensure we close the AR we created
- ApplicationRegistry.remove();
- super.tearDown();
- }
-
- public void testPrepare() throws AMQException
- {
- individual.prepare();
- multiple.prepare();
- combined.prepare();
- }
-
- public void testUndoPrepare() throws AMQException
- {
- individual.undoPrepare();
- multiple.undoPrepare();
- combined.undoPrepare();
- }
-
- public void testCommit() throws AMQException
- {
- individual.commit();
- multiple.commit();
- combined.commit();
- }
-
- public static junit.framework.Test suite()
- {
- return new junit.framework.TestSuite(TxAckTest.class);
- }
-
- private class Scenario
- {
- private final UnacknowledgedMessageMap _map = new UnacknowledgedMessageMapImpl(5000);
- private final TxAck _op = new TxAck(_map);
- private final List<Long> _acked;
- private final List<Long> _unacked;
- private StoreContext _storeContext = new StoreContext();
- private AMQQueue _queue;
-
- Scenario(int messageCount, List<Long> acked, List<Long> unacked) throws Exception
- {
- TransactionalContext txnContext = new NonTransactionalContext(new TestMemoryMessageStore(),
- _storeContext, null,
- new LinkedList<RequiredDeliveryException>()
- );
-
- VirtualHost virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next();
-
- _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("test"), false, null, false,
- virtualHost, null);
-
- for (int i = 0; i < messageCount; i++)
- {
- long deliveryTag = i + 1;
-
- MessagePublishInfo info = new MessagePublishInfo()
- {
-
- public AMQShortString getExchange()
- {
- return null;
- }
-
- public void setExchange(AMQShortString exchange)
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public boolean isImmediate()
- {
- return false;
- }
-
- public boolean isMandatory()
- {
- return false;
- }
-
- public AMQShortString getRoutingKey()
- {
- return null;
- }
- };
-
- TestMessage message = new TestMessage(deliveryTag, i, info, txnContext.getStoreContext());
- _map.add(deliveryTag, _queue.enqueue(new StoreContext(), message));
- }
- _acked = acked;
- _unacked = unacked;
- }
-
- void update(long deliverytag, boolean multiple)
- {
- _op.update(deliverytag, multiple);
- }
-
- private void assertCount(List<Long> tags, int expected)
- {
- for (long tag : tags)
- {
- QueueEntry u = _map.get(tag);
- assertTrue("Message not found for tag " + tag, u != null);
- ((TestMessage) u.getMessage()).assertCountEquals(expected);
- }
- }
-
- void prepare() throws AMQException
- {
- _op.consolidate();
- _op.prepare(_storeContext);
-
- assertCount(_acked, -1);
- assertCount(_unacked, 0);
-
- }
-
- void undoPrepare()
- {
- _op.consolidate();
- _op.undoPrepare();
-
- assertCount(_acked, 1);
- assertCount(_unacked, 0);
- }
-
- void commit()
- {
- _op.consolidate();
- _op.commit(_storeContext);
-
- //check acked messages are removed from map
- Set<Long> keys = new HashSet<Long>(_map.getDeliveryTags());
- keys.retainAll(_acked);
- assertTrue("Expected messages with following tags to have been removed from map: " + keys, keys.isEmpty());
- //check unacked messages are still in map
- keys = new HashSet<Long>(_unacked);
- keys.removeAll(_map.getDeliveryTags());
- assertTrue("Expected messages with following tags to still be in map: " + keys, keys.isEmpty());
- }
-
- public void stop()
- {
- _queue.stop();
- }
- }
-
- private static AMQMessageHandle createMessageHandle(final long messageId, final MessagePublishInfo publishBody)
- {
- final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId,
- null,
- false);
- try
- {
- amqMessageHandle.setPublishAndContentHeaderBody(new StoreContext(),
- publishBody,
- new ContentHeaderBody()
- {
- public int getSize()
- {
- return 1;
- }
- });
- }
- catch (AMQException e)
- {
- // won't happen
- }
-
-
- return amqMessageHandle;
- }
-
-
- private class TestMessage extends AMQMessage
- {
- private final long _tag;
- private int _count;
-
- TestMessage(long tag, long messageId, MessagePublishInfo publishBody, StoreContext storeContext)
- throws AMQException
- {
- super(createMessageHandle(messageId, publishBody), storeContext, publishBody);
- _tag = tag;
- }
-
-
- public boolean incrementReference()
- {
- _count++;
- return true;
- }
-
- public void decrementReference(StoreContext context)
- {
- _count--;
- }
-
- void assertCountEquals(int expected)
- {
- assertEquals("Wrong count for message with tag " + _tag, expected, _count);
- }
- }
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
index c5f291a0cb..5bd739c0af 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -27,6 +27,7 @@ import java.io.RandomAccessFile;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Collections;
import junit.framework.TestCase;
@@ -482,12 +483,17 @@ public class ServerConfigurationTest extends TestCase
{
// Check default
ServerConfiguration serverConfig = new ServerConfiguration(_config);
- assertEquals(5672, serverConfig.getPort());
+ assertNotNull(serverConfig.getPorts());
+ assertEquals(1, serverConfig.getPorts().size());
+ assertEquals(5672, serverConfig.getPorts().get(0));
+
// Check value we set
- _config.setProperty("connector.port", 10);
+ _config.setProperty("connector.port", "10");
serverConfig = new ServerConfiguration(_config);
- assertEquals(10, serverConfig.getPort());
+ assertNotNull(serverConfig.getPorts());
+ assertEquals(1, serverConfig.getPorts().size());
+ assertEquals("10", serverConfig.getPorts().get(0));
}
public void testGetBind() throws ConfigurationException
@@ -723,7 +729,9 @@ public class ServerConfigurationTest extends TestCase
ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile());
assertEquals(4235, config.getSSLPort()); // From first file, not
// overriden by second
- assertEquals(2342, config.getPort()); // From the first file, not
+ assertNotNull(config.getPorts());
+ assertEquals(1, config.getPorts().size());
+ assertEquals("2342", config.getPorts().get(0)); // From the first file, not
// present in the second
assertEquals(true, config.getQpidNIO()); // From the second file, not
// present in the first
@@ -967,7 +975,7 @@ public class ServerConfigurationTest extends TestCase
out.write("\t<rule access=\"deny\" network=\"127.0.0.1\"/>");
out.write("</firewall>\n");
out.close();
-
+
reg.getConfiguration().reparseConfigFile();
assertFalse(reg.getAccessManager().authoriseConnect(session, virtualHost));
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
index 5d3b4e681a..b65020395c 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
@@ -14,21 +14,20 @@
* "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.
- *
+ * under the License.
+ *
*/
package org.apache.qpid.server.configuration;
import junit.framework.TestCase;
-import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
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.virtualhost.VirtualHost;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
public class VirtualHostConfigurationTest extends TestCase
{
@@ -55,50 +54,50 @@ public class VirtualHostConfigurationTest extends TestCase
super.tearDown();
}
-
+
public void testQueuePriority() throws Exception
{
// Set up queue with 5 priorities
- configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)",
+ configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)",
"atest");
- configXml.addProperty("virtualhost.test.queues.queue.atest(-1).exchange",
+ configXml.addProperty("virtualhost.test.queues.queue.atest(-1).exchange",
"amq.direct");
- configXml.addProperty("virtualhost.test.queues.queue.atest.priorities",
+ configXml.addProperty("virtualhost.test.queues.queue.atest.priorities",
"5");
// Set up queue with JMS style priorities
- configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)",
+ configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)",
"ptest");
- configXml.addProperty("virtualhost.test.queues.queue.ptest(-1).exchange",
+ configXml.addProperty("virtualhost.test.queues.queue.ptest(-1).exchange",
"amq.direct");
- configXml.addProperty("virtualhost.test.queues.queue.ptest.priority",
+ configXml.addProperty("virtualhost.test.queues.queue.ptest.priority",
"true");
-
+
// Set up queue with no priorities
- configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)",
+ configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)",
"ntest");
- configXml.addProperty("virtualhost.test.queues.queue.ntest(-1).exchange",
+ configXml.addProperty("virtualhost.test.queues.queue.ntest(-1).exchange",
"amq.direct");
- configXml.addProperty("virtualhost.test.queues.queue.ntest.priority",
+ configXml.addProperty("virtualhost.test.queues.queue.ntest.priority",
"false");
-
- VirtualHost vhost = new VirtualHost(new VirtualHostConfiguration("test", configXml.subset("virtualhost.test")));
-
+
+ VirtualHost vhost = new VirtualHostImpl(new VirtualHostConfiguration("test", configXml.subset("virtualhost.test")));
+
// Check that atest was a priority queue with 5 priorities
AMQQueue atest = vhost.getQueueRegistry().getQueue(new AMQShortString("atest"));
assertTrue(atest instanceof AMQPriorityQueue);
assertEquals(5, ((AMQPriorityQueue) atest).getPriorities());
-
+
// Check that ptest was a priority queue with 10 priorities
AMQQueue ptest = vhost.getQueueRegistry().getQueue(new AMQShortString("ptest"));
assertTrue(ptest instanceof AMQPriorityQueue);
assertEquals(10, ((AMQPriorityQueue) ptest).getPriorities());
-
+
// Check that ntest wasn't a priority queue
AMQQueue ntest = vhost.getQueueRegistry().getQueue(new AMQShortString("ntest"));
assertFalse(ntest instanceof AMQPriorityQueue);
}
-
+
public void testQueueAlerts() throws Exception
{
// Set up queue with 5 priorities
@@ -106,7 +105,7 @@ public class VirtualHostConfigurationTest extends TestCase
configXml.addProperty("virtualhost.test.queues.maximumQueueDepth", "1");
configXml.addProperty("virtualhost.test.queues.maximumMessageSize", "2");
configXml.addProperty("virtualhost.test.queues.maximumMessageAge", "3");
-
+
configXml.addProperty("virtualhost.test.queues(-1).queue(1).name(1)", "atest");
configXml.addProperty("virtualhost.test.queues.queue.atest(-1).exchange", "amq.direct");
configXml.addProperty("virtualhost.test.queues.queue.atest(-1).maximumQueueDepth", "4");
@@ -114,21 +113,21 @@ public class VirtualHostConfigurationTest extends TestCase
configXml.addProperty("virtualhost.test.queues.queue.atest(-1).maximumMessageAge", "6");
configXml.addProperty("virtualhost.test.queues(-1).queue(-1).name(-1)", "btest");
-
- VirtualHost vhost = new VirtualHost(new VirtualHostConfiguration("test", configXml.subset("virtualhost.test")));
-
+
+ VirtualHost vhost = new VirtualHostImpl(new VirtualHostConfiguration("test", configXml.subset("virtualhost.test")));
+
// Check specifically configured values
AMQQueue aTest = vhost.getQueueRegistry().getQueue(new AMQShortString("atest"));
assertEquals(4, aTest.getMaximumQueueDepth());
assertEquals(5, aTest.getMaximumMessageSize());
assertEquals(6, aTest.getMaximumMessageAge());
-
- // Check default values
+
+ // Check default values
AMQQueue bTest = vhost.getQueueRegistry().getQueue(new AMQShortString("btest"));
assertEquals(1, bTest.getMaximumQueueDepth());
assertEquals(2, bTest.getMaximumMessageSize());
assertEquals(3, bTest.getMaximumMessageAge());
-
+
}
-
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
index f8dd266bd2..e26b5b048c 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
@@ -27,18 +27,18 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.queue.*;
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.MemoryMessageStore;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.txn.NonTransactionalContext;
-import org.apache.qpid.server.txn.TransactionalContext;
-import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.log4j.Logger;
import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
public class AbstractHeadersExchangeTestBase extends TestCase
{
@@ -52,10 +52,6 @@ public class AbstractHeadersExchangeTestBase extends TestCase
*/
private MessageStore _store = new MemoryMessageStore();
- private StoreContext _storeContext = new StoreContext();
-
- private MessageHandleFactory _handleFactory = new MessageHandleFactory();
-
private int count;
public void testDoNothing()
@@ -91,14 +87,18 @@ public class AbstractHeadersExchangeTestBase extends TestCase
}
- protected void route(Message m) throws AMQException
+ protected int route(Message m) throws AMQException
{
+ m.getIncomingMessage().headersReceived();
m.route(exchange);
- m.getIncomingMessage().routingComplete(_store, _handleFactory);
if(m.getIncomingMessage().allContentReceived())
{
- m.getIncomingMessage().deliverToQueues();
+ for(AMQQueue q : m.getIncomingMessage().getDestinationQueues())
+ {
+ q.enqueue(m);
+ }
}
+ return m.getIncomingMessage().getDestinationQueues().size();
}
protected void routeAndTest(Message m, TestQueue... expected) throws AMQException
@@ -118,10 +118,8 @@ public class AbstractHeadersExchangeTestBase extends TestCase
protected void routeAndTest(Message m, boolean expectReturn, List<TestQueue> expected) throws AMQException
{
- try
- {
- route(m);
- assertFalse("Expected "+m+" to be returned due to manadatory flag, and lack of routing",expectReturn);
+ int queueCount = route(m);
+
for (TestQueue q : queues)
{
if (expected.contains(q))
@@ -135,12 +133,11 @@ public class AbstractHeadersExchangeTestBase extends TestCase
//assert !m.isInQueue(q) : "Did not expect " + m + " to be delivered to " + q;
}
}
- }
- catch (NoRouteException ex)
- {
- assertTrue("Expected "+m+" not to be returned",expectReturn);
- }
+ if(expectReturn)
+ {
+ assertEquals("Expected "+m+" to be returned due to manadatory flag, and lack of routing",0, queueCount);
+ }
}
@@ -242,6 +239,11 @@ public class AbstractHeadersExchangeTestBase extends TestCase
{
final List<HeadersExchangeTest.Message> messages = new ArrayList<HeadersExchangeTest.Message>();
+ public String toString()
+ {
+ return getName().toString();
+ }
+
public TestQueue(AMQShortString name) throws AMQException
{
super(name, false, new AMQShortString("test"), true, ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"));
@@ -256,9 +258,9 @@ public class AbstractHeadersExchangeTestBase extends TestCase
* @throws AMQException
*/
@Override
- public QueueEntry enqueue(StoreContext context, AMQMessage msg) throws AMQException
+ public QueueEntry enqueue(ServerMessage msg) throws AMQException
{
- messages.add( new HeadersExchangeTest.Message(msg));
+ messages.add( new HeadersExchangeTest.Message((AMQMessage) msg));
return new QueueEntry()
{
@@ -317,6 +319,11 @@ public class AbstractHeadersExchangeTestBase extends TestCase
return false; //To change body of implemented methods use File | Settings | File Templates.
}
+ public boolean isAcquiredBy(Subscription subscription)
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public void setDeliveredToSubscription()
{
//To change body of implemented methods use File | Settings | File Templates.
@@ -327,9 +334,9 @@ public class AbstractHeadersExchangeTestBase extends TestCase
//To change body of implemented methods use File | Settings | File Templates.
}
- public String debugIdentity()
+ public boolean releaseButRetain()
{
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ return false;
}
public boolean immediateAndNotDelivered()
@@ -337,11 +344,26 @@ public class AbstractHeadersExchangeTestBase extends TestCase
return false; //To change body of implemented methods use File | Settings | File Templates.
}
- public void setRedelivered(boolean b)
+ public void setRedelivered()
{
//To change body of implemented methods use File | Settings | File Templates.
}
+ public AMQMessageHeader getMessageHeader()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isPersistent()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isRedelivered()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public Subscription getDeliveredSubscription()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
@@ -362,17 +384,22 @@ public class AbstractHeadersExchangeTestBase extends TestCase
return false; //To change body of implemented methods use File | Settings | File Templates.
}
- public void requeue(StoreContext storeContext) throws AMQException
+ public void requeue()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void requeue(Subscription subscription)
{
//To change body of implemented methods use File | Settings | File Templates.
}
- public void dequeue(final StoreContext storeContext) throws FailedDequeueException
+ public void dequeue()
{
//To change body of implemented methods use File | Settings | File Templates.
}
- public void dispose(final StoreContext storeContext) throws MessageCleanupException
+ public void dispose()
{
//To change body of implemented methods use File | Settings | File Templates.
}
@@ -382,7 +409,12 @@ public class AbstractHeadersExchangeTestBase extends TestCase
//To change body of implemented methods use File | Settings | File Templates.
}
- public void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException
+ public void discard()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void routeToAlternate()
{
//To change body of implemented methods use File | Settings | File Templates.
}
@@ -421,15 +453,16 @@ public class AbstractHeadersExchangeTestBase extends TestCase
*/
static class Message extends AMQMessage
{
+ private static AtomicLong _messageId = new AtomicLong();
+
private class TestIncomingMessage extends IncomingMessage
{
public TestIncomingMessage(final long messageId,
final MessagePublishInfo info,
- final TransactionalContext txnContext,
final AMQProtocolSession publisher)
{
- super(messageId, info, txnContext, publisher);
+ super(info);
}
@@ -439,7 +472,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase
}
- public ContentHeaderBody getContentHeaderBody()
+ public ContentHeaderBody getContentHeader()
{
try
{
@@ -454,15 +487,6 @@ public class AbstractHeadersExchangeTestBase extends TestCase
private IncomingMessage _incoming;
- private static MessageStore _messageStore = new SkeletonMessageStore();
-
- private static StoreContext _storeContext = new StoreContext();
-
-
- private static TransactionalContext _txnContext = new NonTransactionalContext(_messageStore, _storeContext,
- null,
- new LinkedList<RequiredDeliveryException>()
- );
Message(AMQProtocolSession protocolSession, String id, String... headers) throws AMQException
{
@@ -471,7 +495,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase
Message(AMQProtocolSession protocolSession, String id, FieldTable headers) throws AMQException
{
- this(protocolSession, _messageStore.getNewMessageId(),getPublishRequest(id), getContentHeader(headers), null);
+ this(protocolSession, _messageId.incrementAndGet(),getPublishRequest(id), getContentHeader(headers), Collections.EMPTY_LIST);
}
public IncomingMessage getIncomingMessage()
@@ -484,46 +508,34 @@ public class AbstractHeadersExchangeTestBase extends TestCase
ContentHeaderBody header,
List<ContentBody> bodies) throws AMQException
{
- super(createMessageHandle(messageId, publish, header), _txnContext.getStoreContext(), publish);
+ super(new MockStoredMessage(messageId, publish, header));
+
+ StoredMessage<MessageMetaData> storedMessage = getStoredMessage();
+ int pos = 0;
+ for(ContentBody body : bodies)
+ {
+ storedMessage.addContent(pos, body.payload.duplicate().buf());
+ pos += body.payload.limit();
+ }
-
- _incoming = new TestIncomingMessage(getMessageId(),publish, _txnContext, protocolsession);
+ _incoming = new TestIncomingMessage(getMessageId(),publish, protocolsession);
_incoming.setContentHeaderBody(header);
}
- private static AMQMessageHandle createMessageHandle(final long messageId,
- final MessagePublishInfo publish,
- final ContentHeaderBody header)
- {
-
- final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId,
- _messageStore,
- true);
-
- try
- {
- amqMessageHandle.setPublishAndContentHeaderBody(new StoreContext(),publish,header);
- }
- catch (AMQException e)
- {
-
- }
- return amqMessageHandle;
- }
private Message(AMQMessage msg) throws AMQException
{
- super(msg);
+ super(msg.getStoredMessage());
}
void route(Exchange exchange) throws AMQException
{
- exchange.route(_incoming);
+ _incoming.enqueue(exchange.route(_incoming));
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
index ac12e050b4..016f7eacbe 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
@@ -29,6 +29,7 @@ import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.management.ManagedObject;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
index 86ba96bf5d..dc47951548 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
@@ -22,16 +22,95 @@ package org.apache.qpid.server.exchange;
import java.util.Map;
import java.util.HashMap;
+import java.util.Set;
import junit.framework.TestCase;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.message.AMQMessageHeader;
/**
*/
public class HeadersBindingTest extends TestCase
{
+
+ private class MockHeader implements AMQMessageHeader
+ {
+
+ private final Map<String, Object> _headers = new HashMap<String, Object>();
+
+ public String getCorrelationId()
+ {
+ return null;
+ }
+
+ public long getExpiration()
+ {
+ return 0;
+ }
+
+ public String getMessageId()
+ {
+ return null;
+ }
+
+ public String getMimeType()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public String getEncoding()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public byte getPriority()
+ {
+ return 0;
+ }
+
+ public long getTimestamp()
+ {
+ return 0;
+ }
+
+ public String getType()
+ {
+ return null;
+ }
+
+ public String getReplyTo()
+ {
+ return null;
+ }
+
+ public Object getHeader(String name)
+ {
+ return _headers.get(name);
+ }
+
+ public boolean containsHeaders(Set<String> names)
+ {
+ return _headers.keySet().containsAll(names);
+ }
+
+ public boolean containsHeader(String name)
+ {
+ return _headers.containsKey(name);
+ }
+
+ public void setString(String key, String value)
+ {
+ setObject(key,value);
+ }
+
+ public void setObject(String key, Object value)
+ {
+ _headers.put(key,value);
+ }
+ }
+
private FieldTable bindHeaders = new FieldTable();
- private FieldTable matchHeaders = new FieldTable();
+ private MockHeader matchHeaders = new MockHeader();
public void testDefault_1()
{
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java
index 750a1cd081..580bc78b8d 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -35,7 +35,8 @@ public class HeadersExchangeTest extends AbstractHeadersExchangeTestBase
super.setUp();
// AR will use the NullAR by default
// Just use the first vhost.
- VirtualHost virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next();
+ VirtualHost
+ virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next();
_protocolSession = new InternalTestProtocolSession(virtualHost);
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
index 82b8f76efc..9d7a323b6d 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
@@ -14,9 +14,9 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.server.exchange;
@@ -25,28 +25,24 @@ import junit.framework.Assert;
import org.apache.qpid.server.queue.*;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.txn.NonTransactionalContext;
-import org.apache.qpid.server.txn.TransactionalContext;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.MemoryMessageStore;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.RequiredDeliveryException;
import org.apache.qpid.server.protocol.InternalTestProtocolSession;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import java.util.LinkedList;
-
-public class DestWildExchangeTest extends TestCase
+public class TopicExchangeTest extends TestCase
{
TopicExchange _exchange;
VirtualHost _vhost;
MessageStore _store;
- StoreContext _context;
InternalTestProtocolSession _protocolSession;
@@ -56,27 +52,26 @@ public class DestWildExchangeTest extends TestCase
_exchange = new TopicExchange();
_vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next();
_store = new MemoryMessageStore();
- _context = new StoreContext();
_protocolSession = new InternalTestProtocolSession(_vhost);
}
public void tearDown()
{
- ApplicationRegistry.remove();
+ ApplicationRegistry.remove();
}
public void testNoRoute() throws AMQException
{
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*#b"), false, null, false, _vhost, null);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*#b"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.*.#.b"), queue, null);
MessagePublishInfo info = new PublishInfo(new AMQShortString("a.b"));
- IncomingMessage message = new IncomingMessage(0L, info, null, _protocolSession);
+ IncomingMessage message = new IncomingMessage(info);
- _exchange.route(message);
+ message.enqueue(_exchange.route(message));
Assert.assertEquals(0, queue.getMessageCount());
}
@@ -89,33 +84,20 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a.b");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has route and should be routed");
- }
+ routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.c");
- try
- {
- routeMessage(message);
- fail("Message has no route and should fail to be routed");
- }
- catch (AMQException nre)
- {
- }
+ int queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
}
@@ -129,52 +111,33 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a.b");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has route and should be routed");
- }
+ routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.c");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has route and should be routed");
- }
+ int queueCount = routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a");
- try
- {
- routeMessage(message);
- fail("Message has no route and should fail to be routed");
- }
- catch (AMQException nre)
- {
- }
+
+ queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
}
@@ -187,89 +150,56 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a.b.c");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has route and should be routed");
- }
+ int queueCount = routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.b");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has route and should be routed");
- }
+ queueCount = routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.c");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has route and should be routed");
- }
+ queueCount = routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has route and should be routed");
- }
+ queueCount = routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("b");
- try
- {
- routeMessage(message);
- fail("Message has no route and should fail to be routed");
- }
- catch (AMQException nre)
- {
- }
+
+ queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
}
@@ -283,38 +213,24 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a.c.d.b");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has no route and should be routed");
- }
+ routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.c.b");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has no route and should be routed");
- }
+ routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
}
@@ -327,66 +243,39 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a.c.b.b");
- try
- {
- routeMessage(message);
- fail("Message has route and should not be routed");
- }
- catch (AMQException nre)
- {
- }
+ int queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.a.b.c");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has no route and should be routed");
- }
+ routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.b.c.b");
- try
- {
- routeMessage(message);
- fail("Message has route and should not be routed");
- }
- catch (AMQException nre)
- {
- }
+ queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.b.c.b.c");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has no route and should be routed");
-
- }
+ routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
}
@@ -400,34 +289,21 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a.c.b.b.c");
- try
- {
- routeMessage(message);
- fail("Message has route and should not be routed");
- }
- catch (AMQException nre)
- {
- }
+ int queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.a.b.c.d");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has no route and should be routed");
- }
+ routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
}
@@ -440,33 +316,20 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a.c.b.b.c");
- try
- {
- routeMessage(message);
- fail("Message has route and should not be routed");
- }
- catch (AMQException nre)
- {
- }
+ int queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
message = createMessage("a.a.b.c.d");
- try
- {
- routeMessage(message);
- }
- catch (AMQException nre)
- {
- fail("Message has no route and should be routed");
- }
+ routeMessage(message);
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber());
- queue.deleteMessageFromTop(_context);
+ queue.deleteMessageFromTop();
Assert.assertEquals(0, queue.getMessageCount());
}
@@ -479,25 +342,26 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a.b.c");
- try
- {
- routeMessage(message);
- fail("Message has route and should not be routed");
- }
- catch (AMQException nre)
- {
- }
+ int queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
}
- private void routeMessage(final IncomingMessage message)
+ private int routeMessage(final IncomingMessage message)
throws AMQException
{
- _exchange.route(message);
- message.routingComplete(_store, new MessageHandleFactory());
- message.deliverToQueues();
+ MessageMetaData mmd = message.headersReceived();
+ message.setStoredMessage(_store.addMessage(mmd));
+
+ message.enqueue(_exchange.route(message));
+ AMQMessage msg = new AMQMessage(message.getStoredMessage());
+ for(AMQQueue q : message.getDestinationQueues())
+ {
+ q.enqueue(msg);
+ }
+ return message.getDestinationQueues().size();
}
public void testMoreRouting() throws AMQException
@@ -508,14 +372,8 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a.b.c");
- try
- {
- routeMessage(message);
- fail("Message has route and should not be routed");
- }
- catch (AMQException nre)
- {
- }
+ int queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
@@ -529,14 +387,8 @@ public class DestWildExchangeTest extends TestCase
IncomingMessage message = createMessage("a");
- try
- {
- routeMessage(message);
- fail("Message has route and should not be routed");
- }
- catch (AMQException nre)
- {
- }
+ int queueCount = routeMessage(message);
+ Assert.assertEquals("Message should not route to any queues", 0, queueCount);
Assert.assertEquals(0, queue.getMessageCount());
@@ -546,12 +398,11 @@ public class DestWildExchangeTest extends TestCase
{
MessagePublishInfo info = new PublishInfo(new AMQShortString(s));
- TransactionalContext trancontext = new NonTransactionalContext(_store, _context, null,
- new LinkedList<RequiredDeliveryException>()
- );
-
- IncomingMessage message = new IncomingMessage(0L, info, trancontext,_protocolSession);
- message.setContentHeaderBody( new ContentHeaderBody());
+ IncomingMessage message = new IncomingMessage(info);
+ final ContentHeaderBody chb = new ContentHeaderBody();
+ BasicContentHeaderProperties props = new BasicContentHeaderProperties();
+ chb.properties = props;
+ message.setContentHeaderBody(chb);
return message;
@@ -574,7 +425,7 @@ public class DestWildExchangeTest extends TestCase
public void setExchange(AMQShortString exchange)
{
-
+
}
public boolean isImmediate()
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java
index 0fa126dedb..46dc677921 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java
@@ -121,7 +121,7 @@ public class AMQPChannelActorTest extends TestCase
// Verify that the message has the correct type
assertTrue("Message contains the [con: prefix",
logs.get(0).toString().contains("[con:"));
-
+
// Verify that all the values were presented to the MessageFormatter
// so we will not end up with '{n}' entries in the log.
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java
index 1b25844a14..98c14efe4d 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java
@@ -75,7 +75,7 @@ public class AMQPConnectionActorTest extends TestCase
// Correctly Close the AR we created
ApplicationRegistry.remove();
- super.tearDown();
+ super.tearDown();
}
private void setUpWithConfig(ServerConfiguration serverConfig) throws AMQException
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java
index e02993b840..e3280a4076 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java
@@ -41,12 +41,12 @@ public class MessageStoreMessagesTest extends AbstractTestMessages
{
String location = "/path/to/the/message/store.files";
- _logMessage = MessageStoreMessages.MST_1002(location);
+ _logMessage = ConfigStoreMessages.CFG_1002(location);
List<Object> log = performLog();
String[] expected = {"Store location :", location};
- validateLogMessage(log, "MST-1002", expected);
+ validateLogMessage(log, "CFG-1002", expected);
}
public void testMessage1003()
@@ -59,7 +59,7 @@ public class MessageStoreMessagesTest extends AbstractTestMessages
validateLogMessage(log, "MST-1003", expected);
}
- public void testMessage1004()
+ /* public void testMessage1004()
{
_logMessage = MessageStoreMessages.MST_1004(null,false);
List<Object> log = performLog();
@@ -91,7 +91,7 @@ public class MessageStoreMessagesTest extends AbstractTestMessages
// Here we use MessageFormat to ensure the messasgeCount of 2000 is
// reformated for display as '2,000'
- String[] expected = {"Recovered ",
+ String[] expected = {"Recovered ",
MessageFormat.format("{0,number}", messasgeCount),
"messages for queue", queueName};
@@ -119,5 +119,5 @@ public class MessageStoreMessagesTest extends AbstractTestMessages
validateLogMessage(log, "MST-1006", expected);
}
-
+ */
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
index bc36c61382..e6561a06b9 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
@@ -23,19 +23,16 @@ package org.apache.qpid.server.protocol;
import junit.framework.TestCase;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
-import org.apache.qpid.codec.AMQCodecFactory;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.virtualhost.VirtualHost;
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.registry.IApplicationRegistry;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.SkeletonMessageStore;
import javax.management.JMException;
-import java.security.Principal;
/** Test class to test MBean operations for AMQMinaProtocolSession. */
public class AMQProtocolSessionMBeanTest extends TestCase
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
index ec7bf1cb72..681e513ecb 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
@@ -21,19 +21,19 @@
package org.apache.qpid.server.protocol;
import java.security.Principal;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.output.ProtocolOutputConverter;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.message.MessageContentSource;
import org.apache.qpid.transport.TestNetworkDriver;
public class InternalTestProtocolSession extends AMQProtocolEngine implements ProtocolOutputConverter
@@ -70,6 +70,16 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
return (byte) 8;
}
+ public void writeReturn(MessagePublishInfo messagePublishInfo,
+ ContentHeaderBody header,
+ MessageContentSource msgContent,
+ int channelId,
+ int replyCode,
+ AMQShortString replyText) throws AMQException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public byte getProtocolMinorVersion()
{
return (byte) 0;
@@ -82,12 +92,12 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
synchronized (_channelDelivers)
{
List<DeliveryPair> all =_channelDelivers.get(channelId).get(consumerTag);
-
+
if (all == null)
{
return new ArrayList<DeliveryPair>(0);
}
-
+
List<DeliveryPair> msgs = all.subList(0, count);
List<DeliveryPair> response = new ArrayList<DeliveryPair>(msgs);
@@ -108,7 +118,7 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
{
}
- public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag) throws AMQException
+ public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) throws AMQException
{
_deliveryCount.incrementAndGet();
@@ -130,11 +140,11 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
consumers.put(consumerTag, consumerDelivers);
}
- consumerDelivers.add(new DeliveryPair(deliveryTag, message));
+ consumerDelivers.add(new DeliveryPair(deliveryTag, (AMQMessage)entry.getMessage()));
}
}
- public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ public void writeGetOk(QueueEntry message, int channelId, long deliveryTag, int queueSize) throws AMQException
{
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java
index e37492bcb0..13e712dbac 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java
@@ -22,17 +22,10 @@ package org.apache.qpid.server.protocol;
import junit.framework.TestCase;
import org.apache.qpid.AMQException;
-import org.apache.qpid.codec.AMQCodecFactory;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQConstant;
-
-import java.security.Principal;
/** Test class to test MBean operations for AMQMinaProtocolSession. */
public class MaxChannelsTest extends TestCase
@@ -66,14 +59,14 @@ public class MaxChannelsTest extends TestCase
}
assertEquals("Maximum number of channels not set.", new Long(maxChannels), new Long(_session.getChannels().size()));
}
-
+
@Override
public void setUp()
{
//Highlight that this test will cause a new AR to be created
ApplicationRegistry.getInstance();
}
-
+
@Override
public void tearDown() throws Exception
{
@@ -87,7 +80,7 @@ public class MaxChannelsTest extends TestCase
{
// Correctly Close the AR we created
ApplicationRegistry.remove();
- }
+ }
}
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java
index aff7af6952..dd013e6ad5 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java
@@ -1,6 +1,6 @@
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
@@ -8,21 +8,22 @@ package org.apache.qpid.server.queue;
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
+ *
*/
import java.util.ArrayList;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.FieldTable;
import junit.framework.AssertionFailedError;
@@ -42,38 +43,38 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest
{
// Enqueue messages in order
- _queue.enqueue(null, createMessage(1L, (byte) 10));
- _queue.enqueue(null, createMessage(2L, (byte) 4));
- _queue.enqueue(null, createMessage(3L, (byte) 0));
-
+ _queue.enqueue(createMessage(1L, (byte) 10));
+ _queue.enqueue(createMessage(2L, (byte) 4));
+ _queue.enqueue(createMessage(3L, (byte) 0));
+
// Enqueue messages in reverse order
- _queue.enqueue(null, createMessage(4L, (byte) 0));
- _queue.enqueue(null, createMessage(5L, (byte) 4));
- _queue.enqueue(null, createMessage(6L, (byte) 10));
-
+ _queue.enqueue(createMessage(4L, (byte) 0));
+ _queue.enqueue(createMessage(5L, (byte) 4));
+ _queue.enqueue(createMessage(6L, (byte) 10));
+
// Enqueue messages out of order
- _queue.enqueue(null, createMessage(7L, (byte) 4));
- _queue.enqueue(null, createMessage(8L, (byte) 10));
- _queue.enqueue(null, createMessage(9L, (byte) 0));
-
+ _queue.enqueue(createMessage(7L, (byte) 4));
+ _queue.enqueue(createMessage(8L, (byte) 10));
+ _queue.enqueue(createMessage(9L, (byte) 0));
+
// Register subscriber
_queue.registerSubscription(_subscription, false);
Thread.sleep(150);
-
+
ArrayList<QueueEntry> msgs = _subscription.getMessages();
try
{
- assertEquals(new Long(1L), msgs.get(0).getMessage().getMessageId());
- assertEquals(new Long(6L), msgs.get(1).getMessage().getMessageId());
- assertEquals(new Long(8L), msgs.get(2).getMessage().getMessageId());
+ assertEquals(new Long(1L), msgs.get(0).getMessage().getMessageNumber());
+ assertEquals(new Long(6L), msgs.get(1).getMessage().getMessageNumber());
+ assertEquals(new Long(8L), msgs.get(2).getMessage().getMessageNumber());
- assertEquals(new Long(2L), msgs.get(3).getMessage().getMessageId());
- assertEquals(new Long(5L), msgs.get(4).getMessage().getMessageId());
- assertEquals(new Long(7L), msgs.get(5).getMessage().getMessageId());
+ assertEquals(new Long(2L), msgs.get(3).getMessage().getMessageNumber());
+ assertEquals(new Long(5L), msgs.get(4).getMessage().getMessageNumber());
+ assertEquals(new Long(7L), msgs.get(5).getMessage().getMessageNumber());
- assertEquals(new Long(3L), msgs.get(6).getMessage().getMessageId());
- assertEquals(new Long(4L), msgs.get(7).getMessage().getMessageId());
- assertEquals(new Long(9L), msgs.get(8).getMessage().getMessageId());
+ assertEquals(new Long(3L), msgs.get(6).getMessage().getMessageNumber());
+ assertEquals(new Long(4L), msgs.get(7).getMessage().getMessageNumber());
+ assertEquals(new Long(9L), msgs.get(8).getMessage().getMessageNumber());
}
catch (AssertionFailedError afe)
{
@@ -81,7 +82,7 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest
int index = 1;
for (QueueEntry qe : msgs)
{
- System.err.println(index + ":" + qe.getMessage().getMessageId());
+ System.err.println(index + ":" + qe.getMessage().getMessageNumber());
index++;
}
@@ -98,10 +99,10 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest
msg.getContentHeaderBody().properties = props;
return msg;
}
-
+
protected AMQMessage createMessage(Long id) throws AMQException
{
return createMessage(id, (byte) 0);
}
-
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
index 19470e6226..5f0d77afea 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
@@ -20,21 +20,17 @@
*/
package org.apache.qpid.server.queue;
-import java.util.ArrayList;
-import java.util.LinkedList;
-
-import javax.management.Notification;
-
import junit.framework.TestCase;
-
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.RequiredDeliveryException;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.protocol.AMQProtocolEngine;
import org.apache.qpid.server.protocol.InternalTestProtocolSession;
@@ -42,16 +38,16 @@ import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.store.MemoryMessageStore;
import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
-import org.apache.qpid.server.txn.NonTransactionalContext;
-import org.apache.qpid.server.txn.TransactionalContext;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import javax.management.Notification;
+import java.util.ArrayList;
+
/** This class tests all the alerts an AMQQueue can throw based on threshold values of different parameters */
public class AMQQueueAlertTest extends TestCase
-{
+{
private final static long MAX_MESSAGE_COUNT = 50;
private final static long MAX_MESSAGE_AGE = 250; // 0.25 sec
private final static long MAX_MESSAGE_SIZE = 2000; // 2 KB
@@ -61,11 +57,6 @@ public class AMQQueueAlertTest extends TestCase
private VirtualHost _virtualHost;
private AMQProtocolEngine _protocolSession;
private MessageStore _messageStore = new MemoryMessageStore();
- private StoreContext _storeContext = new StoreContext();
- private TransactionalContext _transactionalContext = new NonTransactionalContext(_messageStore, _storeContext,
- null,
- new LinkedList<RequiredDeliveryException>()
- );
private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE;
/**
@@ -75,6 +66,10 @@ public class AMQQueueAlertTest extends TestCase
*/
public void testMessageCountAlert() throws Exception
{
+ _protocolSession = new InternalTestProtocolSession(_virtualHost);
+ AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore);
+ _protocolSession.addChannel(channel);
+
_queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue1"), false, new AMQShortString("AMQueueAlertTest"),
false, _virtualHost,
null);
@@ -82,7 +77,7 @@ public class AMQQueueAlertTest extends TestCase
_queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
- sendMessages(MAX_MESSAGE_COUNT, 256l);
+ sendMessages(channel, MAX_MESSAGE_COUNT, 256l);
assertTrue(_queueMBean.getMessageCount() == MAX_MESSAGE_COUNT);
Notification lastNotification = _queueMBean.getLastNotification();
@@ -99,6 +94,10 @@ public class AMQQueueAlertTest extends TestCase
*/
public void testMessageSizeAlert() throws Exception
{
+ _protocolSession = new InternalTestProtocolSession(_virtualHost);
+ AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore);
+ _protocolSession.addChannel(channel);
+
_queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue2"), false, new AMQShortString("AMQueueAlertTest"),
false, _virtualHost,
null);
@@ -106,7 +105,7 @@ public class AMQQueueAlertTest extends TestCase
_queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
_queueMBean.setMaximumMessageSize(MAX_MESSAGE_SIZE);
- sendMessages(1, MAX_MESSAGE_SIZE * 2);
+ sendMessages(channel, 1, MAX_MESSAGE_SIZE * 2);
assertTrue(_queueMBean.getMessageCount() == 1);
Notification lastNotification = _queueMBean.getLastNotification();
@@ -125,6 +124,10 @@ public class AMQQueueAlertTest extends TestCase
*/
public void testQueueDepthAlertNoSubscriber() throws Exception
{
+ _protocolSession = new InternalTestProtocolSession(_virtualHost);
+ AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore);
+ _protocolSession.addChannel(channel);
+
_queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue3"), false, new AMQShortString("AMQueueAlertTest"),
false, _virtualHost,
null);
@@ -134,7 +137,7 @@ public class AMQQueueAlertTest extends TestCase
while (_queue.getQueueDepth() < MAX_QUEUE_DEPTH)
{
- sendMessages(1, MAX_MESSAGE_SIZE);
+ sendMessages(channel, 1, MAX_MESSAGE_SIZE);
}
Notification lastNotification = _queueMBean.getLastNotification();
@@ -154,6 +157,10 @@ public class AMQQueueAlertTest extends TestCase
*/
public void testMessageAgeAlert() throws Exception
{
+ _protocolSession = new InternalTestProtocolSession(_virtualHost);
+ AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore);
+ _protocolSession.addChannel(channel);
+
_queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue4"), false, new AMQShortString("AMQueueAlertTest"),
false, _virtualHost,
null);
@@ -161,7 +168,7 @@ public class AMQQueueAlertTest extends TestCase
_queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
_queueMBean.setMaximumMessageAge(MAX_MESSAGE_AGE);
- sendMessages(1, MAX_MESSAGE_SIZE);
+ sendMessages(channel, 1, MAX_MESSAGE_SIZE);
// Ensure message sits on queue long enough to age.
Thread.sleep(MAX_MESSAGE_AGE * 2);
@@ -201,7 +208,7 @@ public class AMQQueueAlertTest extends TestCase
// Send messages(no of message to be little more than what can cause a Queue_Depth alert)
int messageCount = Math.round(MAX_QUEUE_DEPTH / MAX_MESSAGE_SIZE) + 10;
long totalSize = (messageCount * MAX_MESSAGE_SIZE);
- sendMessages(messageCount, MAX_MESSAGE_SIZE);
+ sendMessages(channel, messageCount, MAX_MESSAGE_SIZE);
// Check queueDepth. There should be no messages on the queue and as the subscriber is listening
// so there should be no Queue_Deoth alert raised
@@ -228,7 +235,7 @@ public class AMQQueueAlertTest extends TestCase
_queue.registerSubscription(
subscription2, false);
-
+
while (_queue.getUndeliveredMessageCount()!= 0)
{
Thread.sleep(100);
@@ -247,7 +254,7 @@ public class AMQQueueAlertTest extends TestCase
_queueMBean.clearQueue();
assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth()));
}
-
+
protected IncomingMessage message(final boolean immediate, long size) throws AMQException
{
MessagePublishInfo publish = new MessagePublishInfo()
@@ -280,8 +287,10 @@ public class AMQQueueAlertTest extends TestCase
};
ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
+ BasicContentHeaderProperties props = new BasicContentHeaderProperties();
+ contentHeaderBody.properties = props;
contentHeaderBody.bodySize = size; // in bytes
- IncomingMessage message = new IncomingMessage(_messageStore.getNewMessageId(), publish, _transactionalContext, _protocolSession);
+ IncomingMessage message = new IncomingMessage(publish);
message.setContentHeaderBody(contentHeaderBody);
return message;
@@ -305,16 +314,19 @@ public class AMQQueueAlertTest extends TestCase
}
- private void sendMessages(long messageCount, final long size) throws AMQException
+ private void sendMessages(AMQChannel channel, long messageCount, final long size) throws AMQException
{
IncomingMessage[] messages = new IncomingMessage[(int) messageCount];
+ MessageMetaData[] metaData = new MessageMetaData[(int) messageCount];
for (int i = 0; i < messages.length; i++)
{
messages[i] = message(false, size);
ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
qs.add(_queue);
+ metaData[i] = messages[i].headersReceived();
+ messages[i].setStoredMessage(_messageStore.addMessage(metaData[i]));
+
messages[i].enqueue(qs);
- messages[i].routingComplete(_messageStore, new MessageHandleFactory());
}
@@ -324,6 +336,10 @@ public class AMQQueueAlertTest extends TestCase
ByteBuffer _data = ByteBuffer.allocate((int)size);
+ {
+ _data.limit((int)size);
+ }
+
public int getSize()
{
return (int) size;
@@ -336,10 +352,12 @@ public class AMQQueueAlertTest extends TestCase
public void reduceToFit()
{
-
+
}
});
- messages[i].deliverToQueues();
+
+ _queue.enqueue(new AMQMessage(messages[i].getStoredMessage()));
+
}
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
index e692069663..97f061fdd1 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java
@@ -25,7 +25,6 @@ import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.AMQException;
public class AMQQueueFactoryTest extends TestCase
{
@@ -55,31 +54,18 @@ public class AMQQueueFactoryTest extends TestCase
FieldTable fieldTable = new FieldTable();
fieldTable.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), 5);
- try
- {
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testPriorityQueue"), false, new AMQShortString("owner"), false,
- _virtualHost, fieldTable);
- assertEquals("Queue not a priorty queue", AMQPriorityQueue.class, queue.getClass());
- }
- catch (AMQException e)
- {
- fail(e.getMessage());
- }
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testPriorityQueue"), false, new AMQShortString("owner"), false,
+ _virtualHost, fieldTable);
+
+ assertEquals("Queue not a priorty queue", AMQPriorityQueue.class, queue.getClass());
}
public void testSimpleQueueRegistration()
{
- try
- {
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("owner"), false,
- _virtualHost, null);
- assertEquals("Queue not a simple queue", SimpleAMQQueue.class, queue.getClass());
- }
- catch (AMQException e)
- {
- fail(e.getMessage());
- }
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("owner"), false,
+ _virtualHost, null);
+ assertEquals("Queue not a simple queue", SimpleAMQQueue.class, queue.getClass());
}
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
index 03eb7021ad..3bb8d397be 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
@@ -29,7 +29,10 @@ import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.RequiredDeliveryException;
+import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.util.TestApplicationRegistry;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.subscription.SubscriptionFactory;
import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
@@ -38,19 +41,15 @@ import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.txn.TransactionalContext;
-import org.apache.qpid.server.txn.NonTransactionalContext;
import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.store.MemoryMessageStore;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.mina.common.ByteBuffer;
+import org.apache.commons.configuration.PropertiesConfiguration;
import javax.management.JMException;
import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Collections;
/**
* Test class to test AMQQueueMBean attribtues and operations
@@ -61,8 +60,6 @@ public class AMQQueueMBeanTest extends TestCase
private AMQQueue _queue;
private AMQQueueMBean _queueMBean;
private MessageStore _messageStore;
- private StoreContext _storeContext = new StoreContext();
- private TransactionalContext _transactionalContext;
private VirtualHost _virtualHost;
private AMQProtocolSession _protocolSession;
private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE;
@@ -108,7 +105,7 @@ public class AMQQueueMBeanTest extends TestCase
//Ensure that the data has been removed from the Store
verifyBrokerState();
}
-
+
public void testDeleteMessages() throws Exception
{
int messageCount = 10;
@@ -129,9 +126,9 @@ public class AMQQueueMBeanTest extends TestCase
}
catch(Exception e)
{
-
+
}
-
+
//delete last message, leaving 2nd to 9th
_queueMBean.deleteMessages(10L,10L);
assertTrue(_queueMBean.getMessageCount() == (messageCount - 2));
@@ -143,7 +140,7 @@ public class AMQQueueMBeanTest extends TestCase
}
catch(Exception e)
{
-
+
}
//delete remaining messages, leaving none
@@ -159,18 +156,16 @@ public class AMQQueueMBeanTest extends TestCase
private void verifyBrokerState()
{
- TestableMemoryMessageStore store = new TestableMemoryMessageStore((MemoryMessageStore) _virtualHost.getMessageStore());
+ TestableMemoryMessageStore store = (TestableMemoryMessageStore)_virtualHost.getMessageStore();
// Unlike MessageReturnTest there is no need for a delay as there this thread does the clean up.
- assertNotNull("ContentBodyMap should not be null", store.getContentBodyMap());
- assertEquals("Expected the store to have no content:" + store.getContentBodyMap(), 0, store.getContentBodyMap().size());
- assertNotNull("MessageMetaDataMap should not be null", store.getMessageMetaDataMap());
- assertEquals("Expected the store to have no metadata:" + store.getMessageMetaDataMap(), 0, store.getMessageMetaDataMap().size());
+
+ assertEquals("Store should have no messages:" + store.getMessageCount(), 0, store.getMessageCount());
}
public void testConsumerCount() throws AMQException
{
-
+
assertTrue(_queue.getActiveConsumerCount() == 0);
assertTrue(_queueMBean.getActiveConsumerCount() == 0);
@@ -182,7 +177,7 @@ public class AMQQueueMBeanTest extends TestCase
Subscription subscription =
SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), protocolSession, new AMQShortString("test"), false, null, false, channel.getCreditManager());
-
+
_queue.registerSubscription(subscription, false);
assertEquals(1,(int)_queueMBean.getActiveConsumerCount());
@@ -225,7 +220,6 @@ public class AMQQueueMBeanTest extends TestCase
assertTrue(_queueMBean.getMaximumQueueDepth() == (maxQueueDepth));
assertTrue(_queueMBean.getName().equals("testQueue"));
- assertTrue(_queueMBean.getOwner().equals("AMQueueMBeanTest"));
assertFalse(_queueMBean.isAutoDelete());
assertFalse(_queueMBean.isDurable());
}
@@ -261,7 +255,7 @@ public class AMQQueueMBeanTest extends TestCase
{
}
-
+
try
{
long end = Integer.MAX_VALUE;
@@ -275,17 +269,22 @@ public class AMQQueueMBeanTest extends TestCase
}
IncomingMessage msg = message(false, false);
- long id = msg.getMessageId();
- _queue.clearQueue(_storeContext);
+ _queue.clearQueue();
ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
qs.add(_queue);
msg.enqueue(qs);
- msg.routingComplete(_messageStore, new MessageHandleFactory());
+ MessageMetaData mmd = msg.headersReceived();
+ msg.setStoredMessage(_messageStore.addMessage(mmd));
+ long id = msg.getMessageNumber();
msg.addContentBodyFrame(new ContentChunk()
{
ByteBuffer _data = ByteBuffer.allocate((int)MESSAGE_SIZE);
+ {
+ _data.limit((int)MESSAGE_SIZE);
+ }
+
public int getSize()
{
return (int) MESSAGE_SIZE;
@@ -301,7 +300,12 @@ public class AMQQueueMBeanTest extends TestCase
}
});
- msg.deliverToQueues();
+
+ AMQMessage m = new AMQMessage(msg.getStoredMessage());
+ for(AMQQueue q : msg.getDestinationQueues())
+ {
+ q.enqueue(m);
+ }
// _queue.process(_storeContext, new QueueEntry(_queue, msg), false);
_queueMBean.viewMessageContent(id);
try
@@ -350,7 +354,7 @@ public class AMQQueueMBeanTest extends TestCase
contentHeaderBody.bodySize = MESSAGE_SIZE; // in bytes
contentHeaderBody.properties = new BasicContentHeaderProperties();
((BasicContentHeaderProperties) contentHeaderBody.properties).setDeliveryMode((byte) (persistent ? 2 : 1));
- IncomingMessage msg = new IncomingMessage(_messageStore.getNewMessageId(), publish, _transactionalContext, _protocolSession);
+ IncomingMessage msg = new IncomingMessage(publish);
msg.setContentHeaderBody(contentHeaderBody);
return msg;
@@ -360,15 +364,17 @@ public class AMQQueueMBeanTest extends TestCase
protected void setUp() throws Exception
{
super.setUp();
- IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance();
+
+ PropertiesConfiguration configuration = new PropertiesConfiguration();
+ configuration.setProperty("virtualhosts.virtualhost.test.store.class", TestableMemoryMessageStore.class.getName());
+ IApplicationRegistry applicationRegistry = new TestApplicationRegistry(new ServerConfiguration(configuration));
+ ApplicationRegistry.initialise(applicationRegistry );
+
+ configuration.setProperty("virtualhosts.virtualhost.test.store.class", TestableMemoryMessageStore.class.getName());
+
_virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test");
_messageStore = _virtualHost.getMessageStore();
- _transactionalContext = new NonTransactionalContext(_messageStore, _storeContext,
- null,
- new LinkedList<RequiredDeliveryException>()
- );
-
_queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("AMQueueMBeanTest"), false, _virtualHost,
null);
_queueMBean = new AMQQueueMBean(_queue);
@@ -391,7 +397,8 @@ public class AMQQueueMBeanTest extends TestCase
currentMessage.enqueue(qs);
// route header
- currentMessage.routingComplete(_messageStore, new MessageHandleFactory());
+ MessageMetaData mmd = currentMessage.headersReceived();
+ currentMessage.setStoredMessage(_messageStore.addMessage(mmd));
// Add the body so we have somthing to test later
currentMessage.addContentBodyFrame(
@@ -400,7 +407,12 @@ public class AMQQueueMBeanTest extends TestCase
.convertToContentChunk(
new ContentBody(ByteBuffer.allocate((int) MESSAGE_SIZE),
MESSAGE_SIZE)));
- currentMessage.deliverToQueues();
+
+ AMQMessage m = new AMQMessage(currentMessage.getStoredMessage());
+ for(AMQQueue q : currentMessage.getDestinationQueues())
+ {
+ q.enqueue(m);
+ }
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java
index 79f7d75aa9..d64e533f72 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java
@@ -28,7 +28,10 @@ import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.RequiredDeliveryException;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.MessageMetaData;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.server.protocol.AMQProtocolSession;
@@ -39,15 +42,9 @@ import org.apache.qpid.server.flow.Pre0_10CreditManager;
import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.TestMemoryMessageStore;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.txn.NonTransactionalContext;
-import org.apache.qpid.server.txn.TransactionalContext;
-import org.apache.qpid.server.util.NullApplicationRegistry;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.Set;
-import java.util.Collections;
/**
* Tests that acknowledgements are handled correctly.
@@ -62,8 +59,6 @@ public class AckTest extends TestCase
private TestMemoryMessageStore _messageStore;
- private StoreContext _storeContext = new StoreContext();
-
private AMQChannel _channel;
private AMQQueue _queue;
@@ -99,11 +94,7 @@ public class AckTest extends TestCase
private void publishMessages(int count, boolean persistent) throws AMQException
{
- TransactionalContext txnContext = new NonTransactionalContext(_messageStore, _storeContext, null,
- new LinkedList<RequiredDeliveryException>()
- );
_queue.registerSubscription(_subscription,false);
- MessageHandleFactory factory = new MessageHandleFactory();
for (int i = 1; i <= count; i++)
{
// AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
@@ -136,31 +127,50 @@ public class AckTest extends TestCase
return new AMQShortString("rk");
}
};
- IncomingMessage msg = new IncomingMessage(_messageStore.getNewMessageId(), publishBody, txnContext,_protocolSession);
+ final IncomingMessage msg = new IncomingMessage(publishBody);
//IncomingMessage msg2 = null;
+ BasicContentHeaderProperties b = new BasicContentHeaderProperties();
+ ContentHeaderBody cb = new ContentHeaderBody();
+ cb.properties = b;
+
if (persistent)
{
- BasicContentHeaderProperties b = new BasicContentHeaderProperties();
//This is DeliveryMode.PERSISTENT
b.setDeliveryMode((byte) 2);
- ContentHeaderBody cb = new ContentHeaderBody();
- cb.properties = b;
- msg.setContentHeaderBody(cb);
- }
- else
- {
- msg.setContentHeaderBody(new ContentHeaderBody());
}
+
+ msg.setContentHeaderBody(cb);
+
// we increment the reference here since we are not delivering the messaging to any queues, which is where
// the reference is normally incremented. The test is easier to construct if we have direct access to the
// subscription
ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
qs.add(_queue);
msg.enqueue(qs);
- msg.routingComplete(_messageStore, factory);
+ MessageMetaData mmd = msg.headersReceived();
+ msg.setStoredMessage(_messageStore.addMessage(mmd));
if(msg.allContentReceived())
{
- msg.deliverToQueues();
+ ServerTransaction txn = new AutoCommitTransaction(_messageStore);
+ txn.enqueue(_queue, msg, new ServerTransaction.Action() {
+ public void postCommit()
+ {
+ try
+ {
+ _queue.enqueue(new AMQMessage(msg.getStoredMessage()));
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void onRollback()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ });
+
}
// we manually send the message to the subscription
//_subscription.send(new QueueEntry(_queue,msg), _queue);
@@ -178,8 +188,7 @@ public class AckTest extends TestCase
publishMessages(msgCount, true);
UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap();
- assertTrue(map.size() == msgCount);
- assertTrue(_messageStore.getMessageMetaDataMap().size() == msgCount);
+ assertEquals("",msgCount,map.size());
Set<Long> deliveryTagSet = map.getDeliveryTags();
int i = 1;
@@ -191,8 +200,6 @@ public class AckTest extends TestCase
assertTrue(unackedMsg.getQueue() == _queue);
}
- assertTrue(map.size() == msgCount);
- assertTrue(_messageStore.getMessageMetaDataMap().size() == msgCount);
}
/**
@@ -207,8 +214,8 @@ public class AckTest extends TestCase
UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap();
assertTrue(map.size() == 0);
- assertTrue(_messageStore.getMessageMetaDataMap().size() == 0);
- assertTrue(_messageStore.getContentBodyMap().size() == 0);
+ assertTrue(_messageStore.getMessageCount() == 0);
+
}
@@ -224,8 +231,8 @@ public class AckTest extends TestCase
UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap();
assertTrue(map.size() == 0);
- assertTrue(_messageStore.getMessageMetaDataMap().size() == 0);
- assertTrue(_messageStore.getContentBodyMap().size() == 0);
+ assertTrue(_messageStore.getMessageCount() == 0);
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java
index 355ba6a362..7000df157e 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java
@@ -20,25 +20,18 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.server.message.AMQMessage;
public class MockAMQMessage extends AMQMessage
{
public MockAMQMessage(long messageId)
throws AMQException
{
- super(new MockAMQMessageHandle(messageId) ,
- (StoreContext)null,
- (MessagePublishInfo)new MockMessagePublishInfo());
+ super(new MockStoredMessage(messageId));
}
- protected MockAMQMessage(AMQMessage msg)
- throws AMQException
- {
- super(msg);
- }
+
@Override
@@ -46,4 +39,5 @@ public class MockAMQMessage extends AMQMessage
{
return 0l;
}
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
index a131c2a465..7c1f728664 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
@@ -23,23 +23,19 @@ package org.apache.qpid.server.queue;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.configuration.QueueConfiguration;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.AMQException;
-import org.apache.commons.configuration.Configuration;
import java.util.List;
import java.util.Set;
import java.util.Map;
-import java.util.HashMap;
-import java.util.LinkedList;
public class MockAMQQueue implements AMQQueue
{
@@ -47,6 +43,10 @@ public class MockAMQQueue implements AMQQueue
private AMQShortString _name;
private VirtualHost _virtualhost;
+ private PrincipalHolder _principalHolder;
+
+ private Object _exclusiveOwner;
+
public MockAMQQueue(String name)
{
_name = new AMQShortString(name);
@@ -57,6 +57,11 @@ public class MockAMQQueue implements AMQQueue
return _name;
}
+ public void setNoLocal(boolean b)
+ {
+
+ }
+
public boolean isDurable()
{
return false; //To change body of implemented methods use File | Settings | File Templates.
@@ -162,17 +167,22 @@ public class MockAMQQueue implements AMQQueue
return 0; //To change body of implemented methods use File | Settings | File Templates.
}
- public QueueEntry enqueue(StoreContext storeContext, AMQMessage message) throws AMQException
+ public QueueEntry enqueue(ServerMessage message) throws AMQException
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
- public void requeue(StoreContext storeContext, QueueEntry entry) throws AMQException
+ public void requeue(QueueEntry entry)
{
//To change body of implemented methods use File | Settings | File Templates.
}
- public void dequeue(StoreContext storeContext, QueueEntry entry) throws FailedDequeueException
+ public void requeue(QueueEntryImpl storeContext, Subscription subscription)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void dequeue(QueueEntry entry)
{
//To change body of implemented methods use File | Settings | File Templates.
}
@@ -211,23 +221,23 @@ public class MockAMQQueue implements AMQQueue
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
-
+
public List<QueueEntry> getMessagesRangeOnTheQueue(long fromPosition, long toPosition)
{
return null;
}
- public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, StoreContext storeContext)
+ public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction storeContext)
{
//To change body of implemented methods use File | Settings | File Templates.
}
- public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, StoreContext storeContext)
+ public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, ServerTransaction storeContext)
{
//To change body of implemented methods use File | Settings | File Templates.
}
- public void removeMessagesFromQueue(long fromMessageId, long toMessageId, StoreContext storeContext)
+ public void removeMessagesFromQueue(long fromMessageId, long toMessageId)
{
//To change body of implemented methods use File | Settings | File Templates.
}
@@ -286,16 +296,16 @@ public class MockAMQQueue implements AMQQueue
return 0; //To change body of implemented methods use File | Settings | File Templates.
}
- public void deleteMessageFromTop(StoreContext storeContext) throws AMQException
+ public void deleteMessageFromTop()
{
//To change body of implemented methods use File | Settings | File Templates.
}
- public long clearQueue(StoreContext storeContext) throws AMQException
+ public long clearQueue()
{
return 0; //To change body of implemented methods use File | Settings | File Templates.
}
-
+
public void checkMessageStatus() throws AMQException
{
@@ -327,8 +337,28 @@ public class MockAMQQueue implements AMQQueue
//To change body of implemented methods use File | Settings | File Templates.
}
+ public boolean isExclusive()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Exchange getAlternateExchange()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void setAlternateExchange(Exchange exchange)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Map<String, Object> getArguments()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public void checkCapacity(AMQChannel channel)
- {
+ {
}
public ManagedObject getManagedObject()
@@ -343,7 +373,7 @@ public class MockAMQQueue implements AMQQueue
public void setMinimumAlertRepeatGap(long value)
{
-
+
}
public long getCapacity()
@@ -368,7 +398,32 @@ public class MockAMQQueue implements AMQQueue
public void configure(QueueConfiguration config)
{
-
+
+ }
+
+ public PrincipalHolder getPrincipalHolder()
+ {
+ return _principalHolder;
}
+ public void setPrincipalHolder(PrincipalHolder principalHolder)
+ {
+ _principalHolder = principalHolder;
+ }
+
+ public Object getExclusiveOwner()
+ {
+ return _exclusiveOwner;
+ }
+
+ public void setExclusiveOwner(Object exclusiveOwner)
+ {
+ _exclusiveOwner = exclusiveOwner;
+ }
+
+
+ public String getResourceName()
+ {
+ return _name.toString();
+ }
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java
index 37f91e7464..3f74cb973b 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java
@@ -21,8 +21,9 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.AMQMessage;
public class MockQueueEntry implements QueueEntry
{
@@ -44,14 +45,14 @@ public class MockQueueEntry implements QueueEntry
return false;
}
- public void addStateChangeListener(StateChangeListener listener)
+ public boolean isAcquiredBy(Subscription subscription)
{
-
+ return false;
}
- public String debugIdentity()
+ public void addStateChangeListener(StateChangeListener listener)
{
- return null;
+
}
public boolean delete()
@@ -59,17 +60,22 @@ public class MockQueueEntry implements QueueEntry
return false;
}
- public void dequeue(StoreContext storeContext) throws FailedDequeueException
+ public void dequeue()
+ {
+
+ }
+
+ public void discard()
{
}
- public void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException
+ public void routeToAlternate()
{
}
- public void dispose(StoreContext storeContext) throws MessageCleanupException
+ public void dispose()
{
}
@@ -119,70 +125,95 @@ public class MockQueueEntry implements QueueEntry
return false;
}
-
+
public boolean isQueueDeleted()
{
return false;
}
-
+
public boolean isRejectedBy(Subscription subscription)
{
return false;
}
-
+
public void reject()
{
}
-
+
public void reject(Subscription subscription)
{
}
-
+
public void release()
{
}
-
+ public boolean releaseButRetain()
+ {
+ return false;
+ }
+
+
public boolean removeStateChangeListener(StateChangeListener listener)
{
return false;
}
-
- public void requeue(StoreContext storeContext) throws AMQException
+
+ public void requeue()
{
}
-
+ public void requeue(Subscription subscription)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+
public void setDeliveredToSubscription()
{
}
-
- public void setRedelivered(boolean b)
+
+ public void setRedelivered()
+ {
+
+
+ }
+
+ public AMQMessageHeader getMessageHeader()
{
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+ public boolean isPersistent()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+ public boolean isRedelivered()
+ {
+ return false;
}
-
+
public int compareTo(QueueEntry o)
{
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java
new file mode 100755
index 0000000000..7dc491de4d
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java
@@ -0,0 +1,92 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* 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.store.MessageStore;
+import org.apache.qpid.server.store.TransactionLog;
+import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.message.MessageMetaData;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+
+import java.nio.ByteBuffer;
+
+public class MockStoredMessage implements StoredMessage<MessageMetaData>
+{
+ private long _messageId;
+ private MessageMetaData _metaData;
+ private final ByteBuffer _content;
+
+
+ public MockStoredMessage(long messageId)
+ {
+ this(messageId, new MockMessagePublishInfo(), new ContentHeaderBody(new BasicContentHeaderProperties(), 60));
+ }
+
+ public MockStoredMessage(long messageId, MessagePublishInfo info, ContentHeaderBody chb)
+ {
+ _messageId = messageId;
+ _metaData = new MessageMetaData(info, chb, 0);
+ _content = ByteBuffer.allocate(_metaData.getContentSize());
+
+ }
+
+ public MessageMetaData getMetaData()
+ {
+ return _metaData;
+ }
+
+ public long getMessageNumber()
+ {
+ return _messageId;
+ }
+
+ public void addContent(int offsetInMessage, ByteBuffer src)
+ {
+ src = src.duplicate();
+ ByteBuffer dst = _content.duplicate();
+ dst.position(offsetInMessage);
+ dst.put(src);
+ }
+
+ public int getContent(int offset, ByteBuffer dst)
+ {
+ ByteBuffer src = _content.duplicate();
+ src.position(offset);
+ src = src.slice();
+ if(dst.remaining() < src.limit())
+ {
+ src.limit(dst.remaining());
+ }
+ dst.put(src);
+ return src.limit();
+ }
+
+ public TransactionLog.StoreFuture flushToStore()
+ {
+ return MessageStore.IMMEDIATE_FUTURE;
+ }
+
+ public void remove()
+ {
+ }
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
index 111e94f9bf..8c6574095b 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
@@ -1,6 +1,6 @@
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
@@ -8,16 +8,16 @@ package org.apache.qpid.server.queue;
* 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.
- *
+ *
*/
@@ -31,21 +31,21 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.ContentHeaderProperties;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.DirectExchange;
-import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.subscription.MockSubscription;
import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.subscription.SubscriptionImpl;
-import org.apache.qpid.server.txn.NonTransactionalContext;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.MessageMetaData;
public class SimpleAMQQueueTest extends TestCase
{
@@ -59,7 +59,7 @@ public class SimpleAMQQueueTest extends TestCase
protected DirectExchange _exchange = new DirectExchange();
protected MockSubscription _subscription = new MockSubscription();
protected FieldTable _arguments = null;
-
+
MessagePublishInfo info = new MessagePublishInfo()
{
@@ -88,7 +88,7 @@ public class SimpleAMQQueueTest extends TestCase
return null;
}
};
-
+
@Override
protected void setUp() throws Exception
{
@@ -97,7 +97,7 @@ public class SimpleAMQQueueTest extends TestCase
ApplicationRegistry applicationRegistry = (ApplicationRegistry)ApplicationRegistry.getInstance();
PropertiesConfiguration env = new PropertiesConfiguration();
- _virtualHost = new VirtualHost(new VirtualHostConfiguration(getClass().getName(), env), _store);
+ _virtualHost = new VirtualHostImpl(new VirtualHostConfiguration(getClass().getName(), env), _store);
applicationRegistry.getVirtualHostRegistry().registerVirtualHost(_virtualHost);
_queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false, _virtualHost, _arguments);
@@ -119,51 +119,51 @@ public class SimpleAMQQueueTest extends TestCase
}
catch (IllegalArgumentException e)
{
- assertTrue("Exception was not about missing name",
+ assertTrue("Exception was not about missing name",
e.getMessage().contains("name"));
}
-
+
try {
_queue = new SimpleAMQQueue(_qname, false, _owner, false, null);
assertNull("Queue was created", _queue);
}
catch (IllegalArgumentException e)
{
- assertTrue("Exception was not about missing vhost",
+ assertTrue("Exception was not about missing vhost",
e.getMessage().contains("Host"));
}
- _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false,
+ _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false,
_virtualHost, _arguments);
assertNotNull("Queue was not created", _queue);
}
-
+
public void testGetVirtualHost()
{
assertEquals("Virtual host was wrong", _virtualHost, _queue.getVirtualHost());
}
-
+
public void testBinding()
{
try
{
_queue.bind(_exchange, _routingKey, null);
- assertTrue("Routing key was not bound",
+ assertTrue("Routing key was not bound",
_exchange.getBindings().containsKey(_routingKey));
- assertEquals("Queue was not bound to key",
+ assertEquals("Queue was not bound to key",
_exchange.getBindings().get(_routingKey).get(0),
_queue);
- assertEquals("Exchange binding count", 1,
+ assertEquals("Exchange binding count", 1,
_queue.getExchangeBindings().size());
- assertEquals("Wrong exchange bound", _routingKey,
+ assertEquals("Wrong exchange bound", _routingKey,
_queue.getExchangeBindings().get(0).getRoutingKey());
- assertEquals("Wrong exchange bound", _exchange,
+ assertEquals("Wrong exchange bound", _exchange,
_queue.getExchangeBindings().get(0).getExchange());
-
+
_queue.unBind(_exchange, _routingKey, null);
- assertFalse("Routing key was still bound",
+ assertFalse("Routing key was still bound",
_exchange.getBindings().containsKey(_routingKey));
- assertNull("Routing key was not empty",
+ assertNull("Routing key was not empty",
_exchange.getBindings().get(_routingKey));
}
catch (AMQException e)
@@ -171,61 +171,61 @@ public class SimpleAMQQueueTest extends TestCase
assertNull("Unexpected exception", e);
}
}
-
+
public void testSubscription() throws AMQException
{
// Check adding a subscription adds it to the queue
_queue.registerSubscription(_subscription, false);
- assertEquals("Subscription did not get queue", _queue,
+ assertEquals("Subscription did not get queue", _queue,
_subscription.getQueue());
- assertEquals("Queue does not have consumer", 1,
+ assertEquals("Queue does not have consumer", 1,
_queue.getConsumerCount());
- assertEquals("Queue does not have active consumer", 1,
+ assertEquals("Queue does not have active consumer", 1,
_queue.getActiveConsumerCount());
-
+
// Check sending a message ends up with the subscriber
AMQMessage messageA = createMessage(new Long(24));
- _queue.enqueue(null, messageA);
- assertEquals(messageA, _subscription.getLastSeenEntry().getMessage());
-
+ _queue.enqueue(messageA);
+ assertEquals(messageA, _subscription.getQueueContext().getLastSeenEntry().getMessage());
+
// Check removing the subscription removes it's information from the queue
_queue.unregisterSubscription(_subscription);
assertTrue("Subscription still had queue", _subscription.isClosed());
assertFalse("Queue still has consumer", 1 == _queue.getConsumerCount());
- assertFalse("Queue still has active consumer",
+ assertFalse("Queue still has active consumer",
1 == _queue.getActiveConsumerCount());
-
+
AMQMessage messageB = createMessage(new Long (25));
- _queue.enqueue(null, messageB);
- QueueEntry entry = _subscription.getLastSeenEntry();
- assertNull(entry);
+ _queue.enqueue(messageB);
+ assertNull(_subscription.getQueueContext());
+
}
-
+
public void testQueueNoSubscriber() throws AMQException, InterruptedException
{
AMQMessage messageA = createMessage(new Long(24));
- _queue.enqueue(null, messageA);
+ _queue.enqueue(messageA);
_queue.registerSubscription(_subscription, false);
Thread.sleep(150);
- assertEquals(messageA, _subscription.getLastSeenEntry().getMessage());
+ assertEquals(messageA, _subscription.getQueueContext().getLastSeenEntry().getMessage());
}
public void testExclusiveConsumer() throws AMQException
{
// Check adding an exclusive subscription adds it to the queue
_queue.registerSubscription(_subscription, true);
- assertEquals("Subscription did not get queue", _queue,
+ assertEquals("Subscription did not get queue", _queue,
_subscription.getQueue());
- assertEquals("Queue does not have consumer", 1,
+ assertEquals("Queue does not have consumer", 1,
_queue.getConsumerCount());
- assertEquals("Queue does not have active consumer", 1,
+ assertEquals("Queue does not have active consumer", 1,
_queue.getActiveConsumerCount());
// Check sending a message ends up with the subscriber
AMQMessage messageA = createMessage(new Long(24));
- _queue.enqueue(null, messageA);
- assertEquals(messageA, _subscription.getLastSeenEntry().getMessage());
-
+ _queue.enqueue(messageA);
+ assertEquals(messageA, _subscription.getQueueContext().getLastSeenEntry().getMessage());
+
// Check we cannot add a second subscriber to the queue
Subscription subB = new MockSubscription();
Exception ex = null;
@@ -235,12 +235,12 @@ public class SimpleAMQQueueTest extends TestCase
}
catch (AMQException e)
{
- ex = e;
+ ex = e;
}
assertNotNull(ex);
assertTrue(ex instanceof AMQException);
- // Check we cannot add an exclusive subscriber to a queue with an
+ // Check we cannot add an exclusive subscriber to a queue with an
// existing subscription
_queue.unregisterSubscription(_subscription);
_queue.registerSubscription(_subscription, false);
@@ -250,35 +250,35 @@ public class SimpleAMQQueueTest extends TestCase
}
catch (AMQException e)
{
- ex = e;
+ ex = e;
}
assertNotNull(ex);
}
-
- public void testAutoDeleteQueue() throws Exception
+
+ public void testAutoDeleteQueue() throws Exception
{
_queue.stop();
- _queue = new SimpleAMQQueue(_qname, false, _owner, true, _virtualHost);
+ _queue = new SimpleAMQQueue(_qname, false, null, true, _virtualHost);
_queue.registerSubscription(_subscription, false);
AMQMessage message = createMessage(new Long(25));
- _queue.enqueue(null, message);
+ _queue.enqueue(message);
_queue.unregisterSubscription(_subscription);
assertTrue("Queue was not deleted when subscription was removed",
_queue.isDeleted());
}
-
+
public void testResend() throws Exception
{
_queue.registerSubscription(_subscription, false);
Long id = new Long(26);
AMQMessage message = createMessage(id);
- _queue.enqueue(null, message);
- QueueEntry entry = _subscription.getLastSeenEntry();
- entry.setRedelivered(true);
+ _queue.enqueue(message);
+ QueueEntry entry = _subscription.getQueueContext().getLastSeenEntry();
+ entry.setRedelivered();
_queue.resend(entry, _subscription);
-
+
}
-
+
public void testGetFirstMessageId() throws Exception
{
// Create message
@@ -286,7 +286,7 @@ public class SimpleAMQQueueTest extends TestCase
AMQMessage message = createMessage(messageId);
// Put message on queue
- _queue.enqueue(null, message);
+ _queue.enqueue(message);
// Get message id
Long testmsgid = _queue.getMessagesOnTheQueue(1).get(0);
@@ -302,7 +302,7 @@ public class SimpleAMQQueueTest extends TestCase
Long messageId = new Long(i);
AMQMessage message = createMessage(messageId);
// Put message on queue
- _queue.enqueue(null, message);
+ _queue.enqueue(message);
}
// Get message ids
List<Long> msgids = _queue.getMessagesOnTheQueue(5);
@@ -323,7 +323,7 @@ public class SimpleAMQQueueTest extends TestCase
Long messageId = new Long(i);
AMQMessage message = createMessage(messageId);
// Put message on queue
- _queue.enqueue(null, message);
+ _queue.enqueue(message);
}
// Get message ids
List<Long> msgids = _queue.getMessagesOnTheQueue(5, 5);
@@ -335,7 +335,7 @@ public class SimpleAMQQueueTest extends TestCase
assertEquals("Message ID was wrong", messageId, msgids.get(i));
}
}
-
+
public void testGetMessagesRangeOnTheQueue() throws Exception
{
for (int i = 1 ; i <= 10; i++)
@@ -344,142 +344,138 @@ public class SimpleAMQQueueTest extends TestCase
Long messageId = new Long(i);
AMQMessage message = createMessage(messageId);
// Put message on queue
- _queue.enqueue(null, message);
+ _queue.enqueue(message);
}
-
+
// Get non-existent 0th QueueEntry & check returned list was empty
// (the position parameters in this method are indexed from 1)
List<QueueEntry> entries = _queue.getMessagesRangeOnTheQueue(0, 0);
assertTrue(entries.size() == 0);
-
+
// Check that when 'from' is 0 it is ignored and the range continues from 1
entries = _queue.getMessagesRangeOnTheQueue(0, 2);
assertTrue(entries.size() == 2);
- long msgID = entries.get(0).getMessage().getMessageId();
+ long msgID = entries.get(0).getMessage().getMessageNumber();
assertEquals("Message ID was wrong", msgID, 1L);
- msgID = entries.get(1).getMessage().getMessageId();
+ msgID = entries.get(1).getMessage().getMessageNumber();
assertEquals("Message ID was wrong", msgID, 2L);
// Check that when 'from' is greater than 'to' the returned list is empty
entries = _queue.getMessagesRangeOnTheQueue(5, 4);
assertTrue(entries.size() == 0);
-
- // Get first QueueEntry & check id
+
+ // Get first QueueEntry & check id
entries = _queue.getMessagesRangeOnTheQueue(1, 1);
assertTrue(entries.size() == 1);
- msgID = entries.get(0).getMessage().getMessageId();
+ msgID = entries.get(0).getMessage().getMessageNumber();
assertEquals("Message ID was wrong", msgID, 1L);
-
+
// Get 5th,6th,7th entries and check id's
entries = _queue.getMessagesRangeOnTheQueue(5, 7);
assertTrue(entries.size() == 3);
- msgID = entries.get(0).getMessage().getMessageId();
+ msgID = entries.get(0).getMessage().getMessageNumber();
assertEquals("Message ID was wrong", msgID, 5L);
- msgID = entries.get(1).getMessage().getMessageId();
+ msgID = entries.get(1).getMessage().getMessageNumber();
assertEquals("Message ID was wrong", msgID, 6L);
- msgID = entries.get(2).getMessage().getMessageId();
+ msgID = entries.get(2).getMessage().getMessageNumber();
assertEquals("Message ID was wrong", msgID, 7L);
-
+
// Get 10th QueueEntry & check id
entries = _queue.getMessagesRangeOnTheQueue(10, 10);
assertTrue(entries.size() == 1);
- msgID = entries.get(0).getMessage().getMessageId();
+ msgID = entries.get(0).getMessage().getMessageNumber();
assertEquals("Message ID was wrong", msgID, 10L);
-
+
// Get non-existent 11th QueueEntry & check returned set was empty
entries = _queue.getMessagesRangeOnTheQueue(11, 11);
assertTrue(entries.size() == 0);
-
+
// Get 9th,10th, and non-existent 11th entries & check result is of size 2 with correct IDs
entries = _queue.getMessagesRangeOnTheQueue(9, 11);
assertTrue(entries.size() == 2);
- msgID = entries.get(0).getMessage().getMessageId();
+ msgID = entries.get(0).getMessage().getMessageNumber();
assertEquals("Message ID was wrong", msgID, 9L);
- msgID = entries.get(1).getMessage().getMessageId();
+ msgID = entries.get(1).getMessage().getMessageNumber();
assertEquals("Message ID was wrong", msgID, 10L);
}
-
+
public void testEnqueueDequeueOfPersistentMessageToNonDurableQueue() throws AMQException
{
// Create IncomingMessage and nondurable queue
- NonTransactionalContext txnContext = new NonTransactionalContext(_store, null, null, null);
- IncomingMessage msg = new IncomingMessage(1L, info, txnContext, null);
+ final IncomingMessage msg = new IncomingMessage(info);
ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
contentHeaderBody.properties = new BasicContentHeaderProperties();
((BasicContentHeaderProperties) contentHeaderBody.properties).setDeliveryMode((byte) 2);
msg.setContentHeaderBody(contentHeaderBody);
- ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
-
+
+ final ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
+
// Send persistent message
+
qs.add(_queue);
- msg.enqueue(qs);
- msg.routingComplete(_store, new MessageHandleFactory());
- _store.storeMessageMetaData(null, new Long(1L), new MessageMetaData(info, contentHeaderBody, 1));
-
+ MessageMetaData metaData = msg.headersReceived();
+ StoredMessage handle = _store.addMessage(metaData);
+ msg.setStoredMessage(handle);
+
+
+ ServerTransaction txn = new AutoCommitTransaction(_store);
+
+ txn.enqueue(qs, msg, new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ msg.enqueue(qs);
+ }
+
+ public void onRollback()
+ {
+ }
+ });
+
+
+
// Check that it is enqueued
AMQQueue data = _store.getMessages().get(1L);
- assertNotNull(data);
-
+ assertNull(data);
+
// Dequeue message
MockQueueEntry entry = new MockQueueEntry();
- AMQMessage amqmsg = new AMQMessage(1L, _store, new MessageHandleFactory(), txnContext);
-
+ AMQMessage amqmsg = new AMQMessage(handle);
+
entry.setMessage(amqmsg);
- _queue.dequeue(null, entry);
-
+ _queue.dequeue(entry);
+
// Check that it is dequeued
data = _store.getMessages().get(1L);
assertNull(data);
}
- // FIXME: move this to somewhere useful
- private static AMQMessageHandle createMessageHandle(final long messageId, final MessagePublishInfo publishBody)
- {
- final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId,
- null,
- false);
- try
- {
- amqMessageHandle.setPublishAndContentHeaderBody(new StoreContext(),
- publishBody,
- new ContentHeaderBody()
- {
- public int getSize()
- {
- return 1;
- }
- });
- }
- catch (AMQException e)
- {
- // won't happen
- }
-
-
- return amqMessageHandle;
- }
-
public class TestMessage extends AMQMessage
{
private final long _tag;
private int _count;
- TestMessage(long tag, long messageId, MessagePublishInfo publishBody, StoreContext storeContext)
+ TestMessage(long tag, long messageId, MessagePublishInfo publishBody)
throws AMQException
{
- super(createMessageHandle(messageId, publishBody), storeContext, publishBody);
+ this(tag, messageId, publishBody, new ContentHeaderBody(1, 1, new BasicContentHeaderProperties(), 0));
+
+ }
+ TestMessage(long tag, long messageId, MessagePublishInfo publishBody, ContentHeaderBody chb)
+ throws AMQException
+ {
+ super(new MockStoredMessage(messageId, publishBody, chb));
_tag = tag;
}
-
public boolean incrementReference()
{
_count++;
return true;
}
- public void decrementReference(StoreContext context)
+ public void decrementReference()
{
_count--;
}
@@ -489,10 +485,10 @@ public class SimpleAMQQueueTest extends TestCase
assertEquals("Wrong count for message with tag " + _tag, expected, _count);
}
}
-
+
protected AMQMessage createMessage(Long id) throws AMQException
{
- AMQMessage messageA = new TestMessage(id, id, info, new StoreContext());
+ AMQMessage messageA = new TestMessage(id, id, info);
return messageA;
}
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java
index 02de09c91f..ba94af5936 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java
@@ -27,8 +27,6 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.AMQException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
public class SimpleAMQQueueThreadPoolTest extends TestCase
{
@@ -47,7 +45,7 @@ public class SimpleAMQQueueThreadPoolTest extends TestCase
assertFalse("Creation did not start Pool.", ReferenceCountingExecutorService.getInstance().getPool().isShutdown());
assertEquals("References not increased", initialCount + 1, ReferenceCountingExecutorService.getInstance().getReferenceCount());
-
+
queue.stop();
assertEquals("References not decreased", initialCount , ReferenceCountingExecutorService.getInstance().getReferenceCount());
@@ -55,6 +53,6 @@ public class SimpleAMQQueueThreadPoolTest extends TestCase
finally
{
ApplicationRegistry.remove();
- }
+ }
}
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ACLManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ACLManagerTest.java
index 8102360ce0..44f9861e8d 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ACLManagerTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ACLManagerTest.java
@@ -57,11 +57,11 @@ public class ACLManagerTest extends TestCase
BufferedWriter out = new BufferedWriter(new FileWriter(tmpFile));
out.write("<security><queueDenier>notyet</queueDenier><exchangeDenier>yes</exchangeDenier></security>");
out.close();
-
+
_conf = new SecurityConfiguration(new XMLConfiguration(tmpFile));
-
+
// Create ACLManager
-
+
_pluginManager = new MockPluginManager("");
_authzManager = new ACLManager(_conf, _pluginManager);
@@ -79,15 +79,15 @@ public class ACLManagerTest extends TestCase
// Correctly Close the AR we created
ApplicationRegistry.remove();
super.tearDown();
- }
-
+ }
+
public void testACLManagerConfigurationPluginManager() throws Exception
{
AMQQueue queue = new MockAMQQueue("notyet");
AMQQueue otherQueue = new MockAMQQueue("other");
-
+
assertFalse(_authzManager.authoriseDelete(_session, queue));
-
+
// This should only be denied if the config hasn't been correctly passed in
assertTrue(_authzManager.authoriseDelete(_session, otherQueue));
assertTrue(_authzManager.authorisePurge(_session, queue));
@@ -96,11 +96,11 @@ public class ACLManagerTest extends TestCase
public void testACLManagerConfigurationPluginManagerACLPlugin() throws ConfigurationException
{
_authzManager = new ACLManager(_conf, _pluginManager, ExchangeDenier.FACTORY);
-
+
Exchange exchange = null;
assertFalse(_authzManager.authoriseDelete(_session, exchange));
}
-
+
public void testConfigurePlugins() throws ConfigurationException
{
Configuration hostConfig = new PropertiesConfiguration();
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java
index 317dee2b47..37a0fd7fc3 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java
@@ -14,16 +14,16 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.server.security.access;
import org.apache.commons.configuration.Configuration;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.security.access.plugins.AllowAll;
+import org.apache.qpid.server.security.PrincipalHolder;
public class ExchangeDenier extends AllowAll
{
@@ -40,9 +40,9 @@ public class ExchangeDenier extends AllowAll
return new ExchangeDenier();
}
};
-
+
@Override
- public AuthzResult authoriseDelete(AMQProtocolSession session, Exchange exchange)
+ public AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange)
{
return AuthzResult.DENIED;
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java
index 88100dc25f..73e9dac775 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java
@@ -27,14 +27,13 @@ import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.amqp_0_9.ExchangeDeclareBodyImpl;
-import org.apache.qpid.framing.amqp_0_9.QueueDeclareBodyImpl;
import org.apache.qpid.framing.amqp_8_0.QueueBindBodyImpl;
import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.DirectExchange;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult;
-import org.apache.qpid.server.store.SkeletonMessageStore;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.registry.ApplicationRegistry;
@@ -43,7 +42,7 @@ public class PrincipalPermissionsTest extends TestCase
private String _user = "user";
private PrincipalPermissions _perms;
-
+
// Common things that are passed to frame constructors
private AMQShortString _queueName = new AMQShortString(this.getClass().getName()+"queue");
private AMQShortString _tempQueueName = new AMQShortString(this.getClass().getName()+"tempqueue");
@@ -65,18 +64,18 @@ public class PrincipalPermissionsTest extends TestCase
private AMQQueue _temporaryQueue;
private Boolean _temporary = false;
private Boolean _ownQueue = false;
-
+
@Override
public void setUp()
{
//Highlight that this test will cause a new AR to be created
- ApplicationRegistry.getInstance();
+ ApplicationRegistry.getInstance();
_perms = new PrincipalPermissions(_user);
- try
+ try
{
PropertiesConfiguration env = new PropertiesConfiguration();
- _virtualHost = new VirtualHost(new VirtualHostConfiguration("test", env));
+ _virtualHost = new VirtualHostImpl(new VirtualHostConfiguration("test", env));
_exchange = DirectExchange.TYPE.newInstance(_virtualHost, _exchangeName, _durable, _ticket, _autoDelete);
_queue = AMQQueueFactory.createAMQQueueImpl(_queueName, false, _owner , false, _virtualHost, _arguments);
_temporaryQueue = AMQQueueFactory.createAMQQueueImpl(_tempQueueName, false, _owner , true, _virtualHost, _arguments);
@@ -132,27 +131,29 @@ public class PrincipalPermissionsTest extends TestCase
_perms.grant(Permission.CREATEQUEUE, grantArgs);
assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.CREATEQUEUE, authArgs));
}
-
+
// FIXME disabled, this fails due to grant putting the grant into the wrong map QPID-1598
public void disableTestExchangeCreate()
{
- ExchangeDeclareBodyImpl exchangeDeclare =
+ ExchangeDeclareBodyImpl exchangeDeclare =
new ExchangeDeclareBodyImpl(_ticket, _exchangeName, _exchangeType, _passive, _durable,
_autoDelete, _internal, _nowait, _arguments);
Object[] authArgs = new Object[]{exchangeDeclare};
Object[] grantArgs = new Object[]{_exchangeName, _exchangeType};
-
+
assertEquals(AuthzResult.DENIED, _perms.authorise(Permission.CREATEEXCHANGE, authArgs));
_perms.grant(Permission.CREATEEXCHANGE, grantArgs);
assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.CREATEEXCHANGE, authArgs));
}
-
+
public void testConsume()
{
Object[] authArgs = new Object[]{_queue};
Object[] grantArgs = new Object[]{_queueName, _ownQueue};
- assertEquals(AuthzResult.DENIED,_perms.authorise(Permission.CONSUME, authArgs));
+ /* FIXME: This throws a null pointer exception QPID-1599
+ * assertFalse(_perms.authorise(Permission.CONSUME, authArgs));
+ */
_perms.grant(Permission.CONSUME, grantArgs);
assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.CONSUME, authArgs));
}
@@ -166,7 +167,7 @@ public class PrincipalPermissionsTest extends TestCase
_perms.grant(Permission.PUBLISH, grantArgs);
assertEquals(AuthzResult.ALLOWED, _perms.authorise(Permission.PUBLISH, authArgs));
}
-
+
public void testVhostAccess()
{
//Tests that granting a user Virtualhost level access allows all authorisation requests
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/QueueDenier.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/QueueDenier.java
index 5497f0ae44..5b76bf7532 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/QueueDenier.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/QueueDenier.java
@@ -14,21 +14,20 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.server.security.access;
import org.apache.commons.configuration.Configuration;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult;
import org.apache.qpid.server.security.access.plugins.AllowAll;
+import org.apache.qpid.server.security.PrincipalHolder;
public class QueueDenier extends AllowAll
{
-
+
public static final ACLPluginFactory FACTORY = new ACLPluginFactory()
{
public boolean supportsTag(String name)
@@ -43,18 +42,18 @@ public class QueueDenier extends AllowAll
return plugin;
}
};
-
+
private String _queueName = "";
-
+
@Override
- public AuthzResult authoriseDelete(AMQProtocolSession session, AMQQueue queue)
+ public AuthzResult authoriseDelete(PrincipalHolder session, AMQQueue queue)
{
if (!(queue.getName().toString().equals(_queueName)))
{
return AuthzResult.ALLOWED;
- }
- else
+ }
+ else
{
return AuthzResult.DENIED;
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
index 5802655cfc..5169676dae 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
@@ -29,17 +29,13 @@ import org.apache.qpid.server.exchange.ExchangeType;
import org.apache.qpid.server.exchange.TopicExchange;
import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-import org.apache.qpid.server.queue.IncomingMessage;
-import org.apache.qpid.server.queue.MessageHandleFactory;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.queue.AMQPriorityQueue;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
-import org.apache.qpid.server.queue.ExchangeBinding;
-import org.apache.qpid.server.txn.NonTransactionalContext;
-import org.apache.qpid.server.protocol.InternalTestProtocolSession;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
+import org.apache.qpid.server.queue.*;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.ContentHeaderBody;
@@ -103,7 +99,7 @@ public class MessageStoreTest extends TestCase
try
{
- _virtualHost = new VirtualHost(new VirtualHostConfiguration(getClass().getName(), configuration));
+ _virtualHost = new VirtualHostImpl(new VirtualHostConfiguration(getClass().getName(), configuration));
ApplicationRegistry.getInstance().getVirtualHostRegistry().registerVirtualHost(_virtualHost);
}
catch (Exception e)
@@ -169,7 +165,7 @@ public class MessageStoreTest extends TestCase
Exchange topicExchange = createExchange(TopicExchange.TYPE, topicExchangeName, true);
bindAllTopicQueuesToExchange(topicExchange, topicRouting);
- //Send Message To NonDurable direct Exchange = persistent
+ //Send Message To NonDurable direct Exchange = persistent
sendMessageOnExchange(nonDurableExchange, directRouting, true);
// and non-persistent
sendMessageOnExchange(nonDurableExchange, directRouting, false);
@@ -344,22 +340,11 @@ public class MessageStoreTest extends TestCase
MessagePublishInfo messageInfo = new TestMessagePublishInfo(directExchange, false, false, routingKey);
- IncomingMessage currentMessage = null;
+ final IncomingMessage currentMessage;
- try
- {
- currentMessage = new IncomingMessage(_virtualHost.getMessageStore().getNewMessageId(),
- messageInfo,
- new NonTransactionalContext(_virtualHost.getMessageStore(),
- new StoreContext(), null, null),
- new InternalTestProtocolSession(_virtualHost));
- }
- catch (AMQException e)
- {
- fail(e.getMessage());
- }
- currentMessage.setMessageStore(_virtualHost.getMessageStore());
+ currentMessage = new IncomingMessage(messageInfo);
+
currentMessage.setExchange(directExchange);
ContentHeaderBody headerBody = new ContentHeaderBody();
@@ -379,35 +364,42 @@ public class MessageStoreTest extends TestCase
currentMessage.setExpiration();
- try
- {
- currentMessage.route();
- }
- catch (AMQException e)
- {
- fail(e.getMessage());
- }
+ MessageMetaData mmd = currentMessage.headersReceived();
+ currentMessage.setStoredMessage(_virtualHost.getMessageStore().addMessage(mmd));
+
+ currentMessage.route();
+
- try
- {
- currentMessage.routingComplete(_virtualHost.getMessageStore(), new MessageHandleFactory());
- }
- catch (AMQException e)
- {
- fail(e.getMessage());
- }
// check and deliver if header says body length is zero
if (currentMessage.allContentReceived())
{
- try
- {
- currentMessage.deliverToQueues();
- }
- catch (AMQException e)
- {
- fail(e.getMessage());
- }
+ // TODO Deliver to queues
+ ServerTransaction trans = new AutoCommitTransaction(_virtualHost.getMessageStore());
+ final List<AMQQueue> destinationQueues = currentMessage.getDestinationQueues();
+ trans.enqueue(currentMessage.getDestinationQueues(), currentMessage, new ServerTransaction.Action() {
+ public void postCommit()
+ {
+ try
+ {
+ AMQMessage message = new AMQMessage(currentMessage.getStoredMessage());
+
+ for(AMQQueue queue : destinationQueues)
+ {
+ QueueEntry entry = queue.enqueue(message);
+ }
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public void onRollback()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ });
}
}
@@ -496,14 +488,7 @@ public class MessageStoreTest extends TestCase
fail(e.getMessage());
}
- try
- {
- _virtualHost.getQueueRegistry().registerQueue(queue);
- }
- catch (AMQException e)
- {
- fail(e.getMessage());
- }
+ _virtualHost.getQueueRegistry().registerQueue(queue);
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java
index fd6789f5ce..9c12242a07 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/SkeletonMessageStore.java
@@ -25,14 +25,15 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.server.queue.MessageMetaData;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.logging.LogSubject;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
+import java.nio.ByteBuffer;
/**
* A message store that does nothing. Designed to be used in tests that do not want to use any message store
@@ -45,8 +46,19 @@ public class SkeletonMessageStore implements MessageStore
public void configure(String base, Configuration config) throws Exception
{
}
-
- public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception
+
+ public void configureConfigStore(String name,
+ ConfigurationRecoveryHandler recoveryHandler,
+ Configuration config,
+ LogSubject logSubject) throws Exception
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void configureMessageStore(String name,
+ MessageStoreRecoveryHandler recoveryHandler,
+ Configuration config,
+ LogSubject logSubject) throws Exception
{
//To change body of implemented methods use File | Settings | File Templates.
}
@@ -55,7 +67,12 @@ public class SkeletonMessageStore implements MessageStore
{
}
- public void removeMessage(StoreContext s, Long messageId)
+ public <M extends StorableMessageMetaData> StoredMessage<M> addMessage(M metaData)
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void removeMessage(Long messageId)
{
}
@@ -85,24 +102,10 @@ public class SkeletonMessageStore implements MessageStore
public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException
{
- }
-
- public void beginTran(StoreContext s) throws AMQException
- {
}
- public boolean inTran(StoreContext sc)
- {
- return false;
- }
- public void commitTran(StoreContext storeContext) throws AMQException
- {
- }
- public void abortTran(StoreContext storeContext) throws AMQException
- {
- }
public List<AMQQueue> createQueues() throws AMQException
{
@@ -114,22 +117,26 @@ public class SkeletonMessageStore implements MessageStore
return _messageId.getAndIncrement();
}
- public void storeContentBodyChunk(StoreContext sc, Long messageId, int index, ContentChunk contentBody, boolean lastContentBody) throws AMQException
+ public void storeContentBodyChunk(
+ Long messageId,
+ int index,
+ ContentChunk contentBody,
+ boolean lastContentBody) throws AMQException
{
}
- public void storeMessageMetaData(StoreContext sc, Long messageId, MessageMetaData messageMetaData) throws AMQException
+ public void storeMessageMetaData(Long messageId, MessageMetaData messageMetaData) throws AMQException
{
}
- public MessageMetaData getMessageMetaData(StoreContext s,Long messageId) throws AMQException
+ public MessageMetaData getMessageMetaData(Long messageId) throws AMQException
{
return null;
}
- public ContentChunk getContentBodyChunk(StoreContext s,Long messageId, int index) throws AMQException
+ public ContentChunk getContentBodyChunk(Long messageId, int index) throws AMQException
{
return null;
}
@@ -139,18 +146,75 @@ public class SkeletonMessageStore implements MessageStore
return false;
}
- public void removeQueue(final AMQQueue queue) throws AMQException
+ public void storeMessageHeader(Long messageNumber, ServerMessage message)
{
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ public void storeContent(Long messageNumber, long offset, ByteBuffer body)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
}
- public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
+ public ServerMessage getMessage(Long messageNumber)
{
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void removeQueue(final AMQQueue queue) throws AMQException
+ {
+
+ }
+ public void configureTransactionLog(String name,
+ TransactionLogRecoveryHandler recoveryHandler,
+ Configuration storeConfiguration,
+ LogSubject logSubject) throws Exception
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
}
- public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
+ public Transaction newTransaction()
{
+ return new Transaction()
+ {
+
+ public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void commitTran() throws AMQException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ public StoreFuture commitTranAsync() throws AMQException
+ {
+ return new StoreFuture()
+ {
+ public boolean isComplete()
+ {
+ return true;
+ }
+
+ public void waitForCompletion()
+ {
+
+ }
+ };
+ }
+
+ public void abortTran() throws AMQException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ };
}
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java
index 4e48435962..4dea13d391 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java
@@ -20,32 +20,79 @@
*/
package org.apache.qpid.server.store;
-import org.apache.qpid.server.queue.MessageMetaData;
-import org.apache.qpid.framing.ContentBody;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.framing.abstraction.ContentChunk;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.List;
+import java.nio.ByteBuffer;
/**
* 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()
{
- _metaDataMap = new ConcurrentHashMap<Long, MessageMetaData>();
- _contentBodyMap = new ConcurrentHashMap<Long, List<ContentChunk>>();
}
- public ConcurrentMap<Long, MessageMetaData> getMessageMetaDataMap()
+ @Override
+ public StoredMessage addMessage(StorableMessageMetaData metaData)
{
- return _metaDataMap;
+ return new TestableStoredMessage(super.addMessage(metaData));
}
- public ConcurrentMap<Long, List<ContentChunk>> getContentBodyMap()
+ public int getMessageCount()
{
- return _contentBodyMap;
+ 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 StoreFuture flushToStore()
+ {
+ return _storedMessage.flushToStore();
+ }
+
+ public void remove()
+ {
+ _storedMessage.remove();
+ _messageCount.decrementAndGet();
+ }
+
}
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestReferenceCounting.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestReferenceCounting.java
index 2346660d25..c5b1ba7868 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestReferenceCounting.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestReferenceCounting.java
@@ -26,9 +26,8 @@ import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.MessageHandleFactory;
-import org.apache.qpid.server.queue.AMQMessageHandle;
+import org.apache.qpid.server.message.AMQMessage;
+import org.apache.qpid.server.message.MessageMetaData;
/**
* Tests that reference counting works correctly with AMQMessage and the message store
@@ -37,13 +36,12 @@ public class TestReferenceCounting extends TestCase
{
private TestMemoryMessageStore _store;
- private StoreContext _storeContext = new StoreContext();
-
protected void setUp() throws Exception
{
super.setUp();
_store = new TestMemoryMessageStore();
+
}
/**
@@ -83,11 +81,12 @@ public class TestReferenceCounting extends TestCase
};
- final long messageId = _store.getNewMessageId();
- AMQMessageHandle messageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, _store, true);
- messageHandle.setPublishAndContentHeaderBody(_storeContext,info, chb);
- AMQMessage message = new AMQMessage(messageHandle,
- _storeContext,info);
+
+ MessageMetaData mmd = new MessageMetaData(info, chb, 0);
+ StoredMessage storedMessage = _store.addMessage(mmd);
+
+
+ AMQMessage message = new AMQMessage(storedMessage);
message = message.takeReference();
@@ -95,9 +94,9 @@ public class TestReferenceCounting extends TestCase
// message.routingComplete(_store, _storeContext, new MessageHandleFactory());
- assertEquals(1, _store.getMessageMetaDataMap().size());
- message.decrementReference(_storeContext);
- assertEquals(1, _store.getMessageMetaDataMap().size());
+ assertEquals(1, _store.getMessageCount());
+ message.decrementReference();
+ assertEquals(1, _store.getMessageCount());
}
private ContentHeaderBody createPersistentContentHeader()
@@ -141,25 +140,24 @@ public class TestReferenceCounting extends TestCase
}
};
- final Long messageId = _store.getNewMessageId();
final ContentHeaderBody chb = createPersistentContentHeader();
- AMQMessageHandle messageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, _store, true);
- messageHandle.setPublishAndContentHeaderBody(_storeContext,info,chb);
- AMQMessage message = new AMQMessage(messageHandle,
- _storeContext,
- info);
-
-
+
+ MessageMetaData mmd = new MessageMetaData(info, chb, 0);
+ StoredMessage storedMessage = _store.addMessage(mmd);
+
+ AMQMessage message = new AMQMessage(storedMessage);
+
+
message = message.takeReference();
// we call routing complete to set up the handle
// message.routingComplete(_store, _storeContext, new MessageHandleFactory());
- assertEquals(1, _store.getMessageMetaDataMap().size());
+ assertEquals(1, _store.getMessageCount());
message = message.takeReference();
- message.decrementReference(_storeContext);
- assertEquals(1, _store.getMessageMetaDataMap().size());
+ message.decrementReference();
+ assertEquals(1, _store.getMessageCount());
}
public static junit.framework.Test suite()
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
index 9146fe88ae..ab8c1e7c9c 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
@@ -22,14 +22,15 @@ package org.apache.qpid.server.store;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.MessageMetaData;
-import org.apache.qpid.framing.ContentBody;
+import org.apache.qpid.server.message.MessageMetaData;
import org.apache.qpid.framing.abstraction.ContentChunk;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.HashMap;
import java.util.List;
+import java.nio.ByteBuffer;
/**
* Adds some extra methods to the memory message store for testing purposes.
@@ -39,6 +40,7 @@ public class TestableMemoryMessageStore extends MemoryMessageStore
MemoryMessageStore _mms = null;
private HashMap<Long, AMQQueue> _messages = new HashMap<Long, AMQQueue>();
+ private AtomicInteger _messageCount = new AtomicInteger(0);
public TestableMemoryMessageStore(MemoryMessageStore mms)
{
@@ -47,46 +49,111 @@ public class TestableMemoryMessageStore extends MemoryMessageStore
public TestableMemoryMessageStore()
{
- _metaDataMap = new ConcurrentHashMap<Long, MessageMetaData>();
- _contentBodyMap = new ConcurrentHashMap<Long, List<ContentChunk>>();
+
+ }
+
+
+
+
+ @Override
+ public StoredMessage addMessage(StorableMessageMetaData metaData)
+ {
+ return new TestableStoredMessage(super.addMessage(metaData));
+ }
+
+ public int getMessageCount()
+ {
+ return _messageCount.get();
}
- public ConcurrentMap<Long, MessageMetaData> getMessageMetaDataMap()
+ private class TestableTransaction implements Transaction
{
- if (_mms != null)
+ public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQException
{
- return _mms._metaDataMap;
+ getMessages().put(messageId, (AMQQueue)queue);
}
- else
+
+ public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQException
{
- return _metaDataMap;
+ getMessages().remove(messageId);
}
- }
- public ConcurrentMap<Long, List<ContentChunk>> getContentBodyMap()
- {
- if (_mms != null)
+ public void commitTran() throws AMQException
{
- return _mms._contentBodyMap;
}
- else
+
+ public StoreFuture commitTranAsync() throws AMQException
+ {
+ return new StoreFuture()
+ {
+ public boolean isComplete()
+ {
+ return true;
+ }
+
+ public void waitForCompletion()
+ {
+
+ }
+ };
+ }
+
+ public void abortTran() throws AMQException
{
- return _contentBodyMap;
}
- }
-
- public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
- {
- getMessages().put(messageId, queue);
}
- public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
+
+ @Override
+ public Transaction newTransaction()
{
- getMessages().remove(messageId);
+ return new TestableTransaction();
}
public HashMap<Long, AMQQueue> getMessages()
{
return _messages;
}
+
+ 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 StoreFuture flushToStore()
+ {
+ return _storedMessage.flushToStore();
+ }
+
+ public void remove()
+ {
+ _storedMessage.remove();
+ _messageCount.decrementAndGet();
+ }
+ }
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
index a3274a3a05..97ba143bdf 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
@@ -42,11 +42,15 @@ public class MockSubscription implements Subscription
private AMQShortString tag = new AMQShortString("mocktag");
private AMQQueue queue = null;
private StateListener _listener = null;
- private QueueEntry lastSeen = null;
+ private AMQQueue.Context _queueContext = null;
private State _state = State.ACTIVE;
private ArrayList<QueueEntry> messages = new ArrayList<QueueEntry>();
private final Lock _stateChangeLock = new ReentrantLock();
+ private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
+ private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this);
+
+
private static final AtomicLong idGenerator = new AtomicLong(0);
// Create a simple ID that increments for ever new Subscription
private final long _subscriptionID = idGenerator.getAndIncrement();
@@ -81,14 +85,19 @@ public class MockSubscription implements Subscription
return _subscriptionID;
}
- public QueueEntry getLastSeenEntry()
+ public AMQQueue.Context getQueueContext()
{
- return lastSeen;
+ return _queueContext;
}
public SubscriptionAcquiredState getOwningState()
{
- return new QueueEntry.SubscriptionAcquiredState(this);
+ return _owningState;
+ }
+
+ public QueueEntry.SubscriptionAssignedState getAssignedState()
+ {
+ return _assignedState;
}
public LogActor getLogActor()
@@ -116,6 +125,21 @@ public class MockSubscription implements Subscription
return true;
}
+ public void confirmAutoClose()
+ {
+
+ }
+
+ public void set(String key, Object value)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Object get(String key)
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public boolean isAutoClose()
{
return false;
@@ -131,6 +155,16 @@ public class MockSubscription implements Subscription
return _closed;
}
+ public boolean acquires()
+ {
+ return true;
+ }
+
+ public boolean seesRequeues()
+ {
+ return true;
+ }
+
public boolean isSuspended()
{
return false;
@@ -149,25 +183,23 @@ public class MockSubscription implements Subscription
{
}
+ public void onDequeue(QueueEntry queueEntry)
+ {
+ }
+
public void restoreCredit(QueueEntry queueEntry)
{
+ //To change body of implemented methods use File | Settings | File Templates.
}
public void send(QueueEntry msg) throws AMQException
{
- lastSeen = msg;
messages.add(msg);
}
- public boolean setLastSeenEntry(QueueEntry expected, QueueEntry newValue)
+ public void setQueueContext(AMQQueue.Context queueContext)
{
- boolean result = false;
- if (expected != null)
- {
- result = (expected.equals(lastSeen));
- }
- lastSeen = newValue;
- return result;
+ _queueContext = queueContext;
}
public void setQueue(AMQQueue queue, boolean exclusive)
@@ -175,6 +207,10 @@ public class MockSubscription implements Subscription
this.queue = queue;
}
+ public void setNoLocal(boolean noLocal)
+ {
+ }
+
public void setStateListener(StateListener listener)
{
this._listener = listener;
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/TxnBufferTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/TxnBufferTest.java
deleted file mode 100644
index 84d3d313d1..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/TxnBufferTest.java
+++ /dev/null
@@ -1,306 +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.txn;
-
-import junit.framework.TestCase;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.TestMemoryMessageStore;
-import org.apache.qpid.server.store.StoreContext;
-
-import java.util.LinkedList;
-import java.util.NoSuchElementException;
-
-public class TxnBufferTest extends TestCase
-{
- private final LinkedList<MockOp> ops = new LinkedList<MockOp>();
-
- public void testCommit() throws AMQException
- {
- MockStore store = new MockStore();
-
- TxnBuffer buffer = new TxnBuffer();
- buffer.enlist(new MockOp().expectPrepare().expectCommit());
- //check relative ordering
- MockOp op = new MockOp().expectPrepare().expectPrepare().expectCommit().expectCommit();
- buffer.enlist(op);
- buffer.enlist(op);
- buffer.enlist(new MockOp().expectPrepare().expectCommit());
-
- buffer.commit(null);
-
- validateOps();
- store.validate();
- }
-
- public void testRollback() throws AMQException
- {
- MockStore store = new MockStore();
-
- TxnBuffer buffer = new TxnBuffer();
- buffer.enlist(new MockOp().expectRollback());
- buffer.enlist(new MockOp().expectRollback());
- buffer.enlist(new MockOp().expectRollback());
-
- buffer.rollback(null);
-
- validateOps();
- store.validate();
- }
-
- public void testCommitWithFailureDuringPrepare() throws AMQException
- {
- MockStore store = new MockStore();
- store.beginTran(null);
-
- TxnBuffer buffer = new TxnBuffer();
- buffer.enlist(new StoreMessageOperation(store));
- buffer.enlist(new MockOp().expectPrepare().expectUndoPrepare());
- buffer.enlist(new TxnTester(store));
- buffer.enlist(new MockOp().expectPrepare().expectUndoPrepare());
- buffer.enlist(new FailedPrepare());
- buffer.enlist(new MockOp());
-
- try
- {
- buffer.commit(null);
- }
- catch (NoSuchElementException e)
- {
-
- }
-
- validateOps();
- store.validate();
- }
-
- public void testCommitWithPersistance() throws AMQException
- {
- MockStore store = new MockStore();
- store.beginTran(null);
- store.expectCommit();
-
- TxnBuffer buffer = new TxnBuffer();
- buffer.enlist(new MockOp().expectPrepare().expectCommit());
- buffer.enlist(new MockOp().expectPrepare().expectCommit());
- buffer.enlist(new MockOp().expectPrepare().expectCommit());
- buffer.enlist(new StoreMessageOperation(store));
- buffer.enlist(new TxnTester(store));
-
- buffer.commit(null);
- validateOps();
- store.validate();
- }
-
- private void validateOps()
- {
- for (MockOp op : ops)
- {
- op.validate();
- }
- }
-
- public static junit.framework.Test suite()
- {
- return new junit.framework.TestSuite(TxnBufferTest.class);
- }
-
- class MockOp implements TxnOp
- {
- final Object PREPARE = "PREPARE";
- final Object COMMIT = "COMMIT";
- final Object UNDO_PREPARE = "UNDO_PREPARE";
- final Object ROLLBACK = "ROLLBACK";
-
- private final LinkedList expected = new LinkedList();
-
- MockOp()
- {
- ops.add(this);
- }
-
- public void prepare(StoreContext context)
- {
- assertEquals(expected.removeLast(), PREPARE);
- }
-
- public void commit(StoreContext context)
- {
- assertEquals(expected.removeLast(), COMMIT);
- }
-
- public void undoPrepare()
- {
- assertEquals(expected.removeLast(), UNDO_PREPARE);
- }
-
- public void rollback(StoreContext context)
- {
- assertEquals(expected.removeLast(), ROLLBACK);
- }
-
- private MockOp expect(Object optype)
- {
- expected.addFirst(optype);
- return this;
- }
-
- MockOp expectPrepare()
- {
- return expect(PREPARE);
- }
-
- MockOp expectCommit()
- {
- return expect(COMMIT);
- }
-
- MockOp expectUndoPrepare()
- {
- return expect(UNDO_PREPARE);
- }
-
- MockOp expectRollback()
- {
- return expect(ROLLBACK);
- }
-
- void validate()
- {
- assertEquals("Expected ops were not all invoked", new LinkedList(), expected);
- }
-
- void clear()
- {
- expected.clear();
- }
- }
-
- class MockStore extends TestMemoryMessageStore
- {
- final Object BEGIN = "BEGIN";
- final Object ABORT = "ABORT";
- final Object COMMIT = "COMMIT";
-
- private final LinkedList expected = new LinkedList();
- private boolean inTran;
-
- public void beginTran(StoreContext context) throws AMQException
- {
- inTran = true;
- }
-
- public void commitTran(StoreContext context) throws AMQException
- {
- assertEquals(expected.removeLast(), COMMIT);
- inTran = false;
- }
-
- public void abortTran(StoreContext context) throws AMQException
- {
- assertEquals(expected.removeLast(), ABORT);
- inTran = false;
- }
-
- public boolean inTran(StoreContext context)
- {
- return inTran;
- }
-
- private MockStore expect(Object optype)
- {
- expected.addFirst(optype);
- return this;
- }
-
- MockStore expectBegin()
- {
- return expect(BEGIN);
- }
-
- MockStore expectCommit()
- {
- return expect(COMMIT);
- }
-
- MockStore expectAbort()
- {
- return expect(ABORT);
- }
-
- void clear()
- {
- expected.clear();
- }
-
- void validate()
- {
- assertEquals("Expected ops were not all invoked", new LinkedList(), expected);
- }
- }
-
- class NullOp implements TxnOp
- {
- public void prepare(StoreContext context) throws AMQException
- {
- }
- public void commit(StoreContext context)
- {
- }
- public void undoPrepare()
- {
- }
- public void rollback(StoreContext context)
- {
- }
- }
-
- class FailedPrepare extends NullOp
- {
- public void prepare() throws AMQException
- {
- throw new AMQException(null, "Fail!", null);
- }
- }
-
- class TxnTester extends NullOp
- {
- private final MessageStore store;
-
- private final StoreContext context = new StoreContext();
-
- TxnTester(MessageStore store)
- {
- this.store = store;
- }
-
- public void prepare() throws AMQException
- {
- assertTrue("Expected prepare to be performed under txn", store.inTran(context));
- }
-
- public void commit()
- {
- assertTrue("Expected commit not to be performed under txn", !store.inTran(context));
- }
- }
-
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
index f2096df9d1..906c769f9c 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
@@ -31,7 +31,6 @@ import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.ConsumerTagNotUniqueException;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.exchange.Exchange;
@@ -41,12 +40,10 @@ import org.apache.qpid.server.queue.AMQQueueFactory;
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.StoreContext;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.util.MockChannel;
-import java.security.Principal;
public class InternalBrokerBaseCase extends TestCase
{
@@ -55,7 +52,6 @@ public class InternalBrokerBaseCase extends TestCase
protected MockChannel _channel;
protected InternalTestProtocolSession _session;
protected VirtualHost _virtualHost;
- protected StoreContext _storeContext = new StoreContext();
protected AMQQueue _queue;
protected AMQShortString QUEUE_NAME;
@@ -97,7 +93,7 @@ public class InternalBrokerBaseCase extends TestCase
protected void checkStoreContents(int messageCount)
{
- assertEquals("Message header count incorrect in the MetaDataMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getMessageMetaDataMap().size());
+ assertEquals("Message header count incorrect in the MetaDataMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getMessageCount());
//The above publish message is sufficiently small not to fit in the header so no Body is required.
//assertEquals("Message body count incorrect in the ContentBodyMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getContentBodyMap().size());
@@ -114,11 +110,7 @@ public class InternalBrokerBaseCase extends TestCase
e.printStackTrace();
fail(e.getMessage());
}
- catch (ConsumerTagNotUniqueException e)
- {
- e.printStackTrace();
- fail(e.getMessage());
- }
+
//Keep the compiler happy
return null;
}
@@ -137,11 +129,7 @@ public class InternalBrokerBaseCase extends TestCase
e.printStackTrace();
fail(e.getMessage());
}
- catch (ConsumerTagNotUniqueException e)
- {
- e.printStackTrace();
- fail(e.getMessage());
- }
+
//Keep the compiler happy
return null;
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java
index 6b8201eefb..3d37412376 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/NullApplicationRegistry.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -36,8 +36,9 @@ import org.apache.qpid.server.security.access.ACLManager;
import org.apache.qpid.server.security.access.plugins.AllowAll;
import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabaseManager;
import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
-import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
+import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.Arrays;
import java.util.Collection;
@@ -76,7 +77,7 @@ public class NullApplicationRegistry extends ApplicationRegistry
_virtualHostRegistry = new VirtualHostRegistry(this);
PropertiesConfiguration vhostProps = new PropertiesConfiguration();
VirtualHostConfiguration hostConfig = new VirtualHostConfiguration("test", vhostProps);
- VirtualHost dummyHost = new VirtualHost(hostConfig);
+ VirtualHost dummyHost = new VirtualHostImpl(hostConfig);
_virtualHostRegistry.registerVirtualHost(dummyHost);
_virtualHostRegistry.setDefaultVirtualHostName("test");
_pluginManager = new PluginManager("");
@@ -97,7 +98,7 @@ public class NullApplicationRegistry extends ApplicationRegistry
try
{
- super.close();
+ super.close();
}
finally
{
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
index 7b7c86bb80..bb338458f1 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -35,8 +35,9 @@ import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabase
import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
+import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.logging.RootMessageLoggerImpl;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.TestLogActor;
@@ -60,7 +61,7 @@ public class TestApplicationRegistry extends ApplicationRegistry
private ServerConfiguration _config;
-
+
public TestApplicationRegistry() throws ConfigurationException
{
super(new ServerConfiguration(new PropertiesConfiguration()));
@@ -96,10 +97,10 @@ public class TestApplicationRegistry extends ApplicationRegistry
_messageStore = new TestableMemoryMessageStore();
_virtualHostRegistry = new VirtualHostRegistry(this);
-
+
PropertiesConfiguration vhostProps = new PropertiesConfiguration();
VirtualHostConfiguration hostConfig = new VirtualHostConfiguration("test", vhostProps);
- _vHost = new VirtualHost(hostConfig, _messageStore);
+ _vHost = new VirtualHostImpl(hostConfig, _messageStore);
_virtualHostRegistry.registerVirtualHost(_vHost);
@@ -152,7 +153,7 @@ public class TestApplicationRegistry extends ApplicationRegistry
CurrentActor.remove();
}
}
-
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java b/qpid/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java
index 447d09429d..9bd1e7c5e1 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java
@@ -35,9 +35,6 @@ public class MockChannel extends AMQChannel
super(session, channelId, messageStore);
}
- public Subscription getSubscription(AMQShortString subscription)
- {
- return _tag2SubscriptionMap.get(subscription);
- }
-
+
+
}
diff --git a/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java b/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java
index ea0946f6d6..2efb22610f 100644
--- a/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java
+++ b/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java
@@ -108,6 +108,8 @@ public class GenerateLogMessages
createMessageClass("ManagementConsole", "MNG");
createMessageClass("VirtualHost", "VHT");
createMessageClass("MessageStore", "MST");
+ createMessageClass("ConfigStore", "CFG");
+ createMessageClass("TransactionLog", "TXN");
createMessageClass("Connection", "CON");
createMessageClass("Channel", "CHN");
createMessageClass("Queue", "QUE");
@@ -465,4 +467,4 @@ public class GenerateLogMessages
super(message);
}
}
-} \ No newline at end of file
+}
diff --git a/qpid/java/build.deps b/qpid/java/build.deps
index 709f2a478e..464afdc136 100644
--- a/qpid/java/build.deps
+++ b/qpid/java/build.deps
@@ -82,7 +82,7 @@ tools.libs=${client.libs}
broker.libs=${common.libs} ${commons-cli} ${commons-logging} ${log4j} \
${slf4j-log4j} ${xalan} ${felix.libs} ${derby-db}
-broker-plugins.libs=${common.libs} ${felix.libs}
+broker-plugins.libs=${common.libs} ${felix.libs} ${log4j}
management-client.libs=${jsp.libs} ${log4j} ${slf4j-log4j} ${slf4j-api} ${commons-pool} ${geronimo-servlet} ${muse.libs} ${javassist} ${xalan} ${mina-core} ${mina-filter-ssl}
management-agent.libs=${client.libs} ${commons-logging} ${geronimo-jms}
diff --git a/qpid/java/client/build.xml b/qpid/java/client/build.xml
index 73252ac124..3c6132dc5b 100644
--- a/qpid/java/client/build.xml
+++ b/qpid/java/client/build.xml
@@ -20,7 +20,8 @@
-->
<project name="AMQ Client" default="build">
- <property name="module.depends" value="common common/test"/>
+ <property name="module.depends" value="common"/>
+ <property name="module.test.depends" value="common/test" />
<property name="module.genpom" value="true"/>
<property name="module.genpom.args" value="-Sgeronimo-jms_1.1_spec=provided"/>
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
index ed122a772e..b57c834598 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
@@ -214,14 +214,14 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
if ((id & FAST_CHANNEL_ACCESS_MASK) == 0)
{
done = (_fastAccessSessions[id] == null);
- }
+ }
else
{
done = (!_slowAccessSessions.keySet().contains(id));
}
}
}
-
+
return id;
}
@@ -320,11 +320,11 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
//Indicates whether we need to sync on every message ack
private boolean _syncAck;
-
+
//Indicates the sync publish options (persistent|all)
//By default it's async publish
- private String _syncPublish = "";
-
+ private String _syncPublish = "";
+
/**
* @param broker brokerdetails
* @param username username
@@ -418,7 +418,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
if (connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_PERSISTENCE) != null)
{
- _syncPersistence =
+ _syncPersistence =
Boolean.parseBoolean(connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_PERSISTENCE));
_logger.warn("sync_persistence is a deprecated property, " +
"please use sync_publish={persistent|all} instead");
@@ -453,10 +453,12 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
// use the default value set for all connections
_syncPublish = System.getProperty((ClientProperties.SYNC_ACK_PROP_NAME),_syncPublish);
}
-
+
+ String amqpVersion = System.getProperty((ClientProperties.AMQP_VERSION), "0-10");
+
_failoverPolicy = new FailoverPolicy(connectionURL, this);
BrokerDetails brokerDetails = _failoverPolicy.getCurrentBrokerDetails();
- if (brokerDetails.getTransport().equals(BrokerDetails.VM))
+ if (brokerDetails.getTransport().equals(BrokerDetails.VM) || "0-8".equals(amqpVersion) || "0-9".equals(amqpVersion))
{
_delegate = new AMQConnectionDelegate_8_0(this);
}
@@ -538,7 +540,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
else if (!_connected)
{
- retryAllowed = _failoverPolicy.failoverAllowed();
+ retryAllowed = _failoverPolicy.failoverAllowed();
brokerDetails = _failoverPolicy.getNextBrokerDetails();
}
}
@@ -591,7 +593,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
throw new AMQConnectionFailureException(message, connectionException);
}
-
+
_connectionMetaData = new QpidConnectionMetaData(this);
}
@@ -1573,7 +1575,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
return _syncPersistence;
}
-
+
/**
* Indicates whether we need to sync on every message ack
*/
@@ -1581,12 +1583,12 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
return _syncAck;
}
-
+
public String getSyncPublish()
{
return _syncPublish;
}
-
+
public void setIdleTimeout(long l)
{
_delegate.setIdleTimeout(l);
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
index 97d0d0516e..e1d9ae735c 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
@@ -89,11 +89,11 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
StateWaiter waiter = _conn._protocolHandler.createWaiter(openOrClosedStates);
// TODO: use system property thingy for this
- if (System.getProperty("UseTransportIo", "false").equals("false"))
+ if (System.getProperty("UseTransportIo", "false").equals("false"))
{
TransportConnection.getInstance(brokerDetail).connect(_conn._protocolHandler, brokerDetail);
- }
- else
+ }
+ else
{
_conn.getProtocolHandler().createIoTransportSession(brokerDetail);
}
@@ -197,7 +197,7 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
* Low = MaxPrefetch / 2
* @return XASession
* @throws JMSException thrown if there is a problem creating the session.
- */
+ */
public XASession createXASession() throws JMSException
{
return createXASession((int) _conn.getMaxPrefetch(), (int) _conn.getMaxPrefetch() / 2);
@@ -214,7 +214,7 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
// todo Be aware of possible changes to parameter order as versions change.
BasicQosBody basicQosBody = _conn.getProtocolHandler().getMethodRegistry().createBasicQosBody(0,prefetchHigh,false);
_conn._protocolHandler.syncWrite(basicQosBody.generateFrame(channelId),BasicQosOkBody.class);
-
+
if (transacted)
{
if (_logger.isDebugEnabled())
@@ -222,7 +222,7 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
_logger.debug("Issuing TxSelect for " + channelId);
}
TxSelectBody body = _conn.getProtocolHandler().getMethodRegistry().createTxSelectBody();
-
+
// TODO: Be aware of possible changes to parameter order as versions change.
_conn._protocolHandler.syncWrite(body.generateFrame(channelId), TxSelectOkBody.class);
}
@@ -299,7 +299,7 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
}
}
}
-
+
public void setIdleTimeout(long l){}
public int getMaxChannelID()
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
index 1587d6a6bf..2324d441cc 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
@@ -468,7 +468,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
public boolean isQueueBound(final AMQShortString exchangeName, final AMQShortString queueName, final AMQShortString routingKey,AMQShortString[] bindingKeys)
throws JMSException
{
- String rk = "";
+ String rk = null;
boolean res;
if (bindingKeys != null && bindingKeys.length>0)
{
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
index 44ce59975a..df59be25d0 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
@@ -46,14 +46,14 @@ import org.slf4j.LoggerFactory;
public abstract class BasicMessageProducer extends Closeable implements org.apache.qpid.jms.MessageProducer
{
- enum PublishMode { ASYNC_PUBLISH_ALL, SYNC_PUBLISH_PERSISTENT, SYNC_PUBLISH_ALL };
-
+ enum PublishMode { ASYNC_PUBLISH_ALL, SYNC_PUBLISH_PERSISTENT, SYNC_PUBLISH_ALL };
+
protected final Logger _logger = LoggerFactory.getLogger(getClass());
private AMQConnection _connection;
/**
- * If true, messages will not get a timestamp.
+ * If true, messages will not get a timestamp.
*/
protected boolean _disableTimestamps;
@@ -105,7 +105,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
private long _producerId;
/**
- * The session used to create this producer
+ * The session used to create this producer
*/
protected AMQSession _session;
@@ -118,11 +118,11 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
private boolean _disableMessageId;
private UUIDGen _messageIdGenerator = UUIDs.newGenerator();
-
+
protected String _userID; // ref user id used in the connection.
private static final ContentBody[] NO_CONTENT_BODIES = new ContentBody[0];
-
+
protected PublishMode publishMode = PublishMode.ASYNC_PUBLISH_ALL;
protected BasicMessageProducer(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId,
@@ -145,14 +145,14 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
_mandatory = mandatory;
_waitUntilSent = waitUntilSent;
_userID = connection.getUsername();
- setPublishMode();
+ setPublishMode();
}
-
+
void setPublishMode()
{
// Publish mode could be configured at destination level as well.
// Will add support for this when we provide a more robust binding URL
-
+
String syncPub = _connection.getSyncPublish();
// Support for deprecated option sync_persistence
if (syncPub.equals("persistent") || _connection.getSyncPersistence())
@@ -163,7 +163,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
{
publishMode = PublishMode.SYNC_PUBLISH_ALL;
}
-
+
_logger.info("MessageProducer " + toString() + " using publish mode : " + publishMode);
}
@@ -277,6 +277,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
checkPreConditions();
checkInitialDestination();
+
synchronized (_connection.getFailoverMutex())
{
sendImpl(_destination, message, _deliveryMode, _messagePriority, _timeToLive, _mandatory, _immediate);
@@ -548,6 +549,10 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
{
throw new javax.jms.IllegalStateException("Invalid Session");
}
+ if(_session.getAMQConnection().isClosed())
+ {
+ throw new javax.jms.IllegalStateException("Connection closed");
+ }
}
private void checkInitialDestination()
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/configuration/ClientProperties.java b/qpid/java/client/src/main/java/org/apache/qpid/client/configuration/ClientProperties.java
index be0d283470..e5050b4fbd 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/configuration/ClientProperties.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/configuration/ClientProperties.java
@@ -33,7 +33,7 @@ public class ClientProperties
public static final String IGNORE_SET_CLIENTID_PROP_NAME = "ignore_setclientID";
/**
- * This property is currently used within the 0.10 code path only
+ * This property is currently used within the 0.10 code path only
* The maximum number of pre-fetched messages per destination
* This property is used for all the connection unless it is overwritten by the connectionURL
* type: long
@@ -46,13 +46,13 @@ public class ClientProperties
* type: boolean
*/
public static final String SYNC_PERSISTENT_PROP_NAME = "sync_persistence";
-
+
/**
* When true a sync command is sent after sending a message ack.
* type: boolean
*/
public static final String SYNC_ACK_PROP_NAME = "sync_ack";
-
+
/**
* sync_publish property - {persistent|all}
* If set to 'persistent',then persistent messages will be publish synchronously
@@ -60,17 +60,17 @@ public class ClientProperties
* published synchronously.
*/
public static final String SYNC_PUBLISH_PROP_NAME = "sync_publish";
-
+
/**
* This value will be used in the following settings
* To calculate the SO_TIMEOUT option of the socket (2*idle_timeout)
* If this values is between the max and min values specified for heartbeat
* by the broker in TuneOK it will be used as the heartbeat interval.
- * If not a warning will be printed and the max value specified for
+ * If not a warning will be printed and the max value specified for
* heartbeat in TuneOK will be used
*/
public static final String IDLE_TIMEOUT_PROP_NAME = "idle_timeout";
-
+
/**
* ==========================================================
@@ -100,4 +100,6 @@ public class ClientProperties
*/
public static final String WRITE_BUFFER_LIMIT_PROP_NAME = "qpid.read.buffer.limit";
public static final String WRITE_BUFFER_LIMIT_DEFAULT = "262144";
+
+ public static final String AMQP_VERSION = "qpid.amqp.version";
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java
index 190776891e..f74dbba939 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java
@@ -21,7 +21,6 @@
package org.apache.qpid.client.failover;
import org.apache.qpid.AMQDisconnectedException;
-import org.apache.qpid.AMQException;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.AMQState;
@@ -94,7 +93,6 @@ public class FailoverHandler implements Runnable
* Creates a failover handler on a protocol session, for a particular MINA session (network connection).
*
* @param amqProtocolHandler The protocol handler that spans the failover.
- * @param session The MINA session, for the failing connection.
*/
public FailoverHandler(AMQProtocolHandler amqProtocolHandler)
{
@@ -135,10 +133,12 @@ public class FailoverHandler implements Runnable
// have a state waiter waiting until the connection is closed for some reason. Or in future we may have
// a slightly more complex state model therefore I felt it was worthwhile doing this.
AMQStateManager existingStateManager = _amqProtocolHandler.getStateManager();
-
+
+
// Use a fresh new StateManager for the reconnection attempts
_amqProtocolHandler.setStateManager(new AMQStateManager());
+
if (!_amqProtocolHandler.getConnection().firePreFailover(_host != null))
{
_logger.info("Failover process veto-ed by client");
@@ -190,7 +190,7 @@ public class FailoverHandler implements Runnable
}
else
{
- // Set the new Protocol Session in the StateManager.
+ // Set the new Protocol Session in the StateManager.
existingStateManager.setProtocolSession(_amqProtocolHandler.getProtocolSession());
// Now that the ProtocolHandler has been reconnected clean up
@@ -198,7 +198,7 @@ public class FailoverHandler implements Runnable
// it any old exception that had occured prior to failover may
// prohibit reconnection.
// e.g. During testing when the broker is shutdown gracefully.
- // The broker
+ // The broker
// Clear any exceptions we gathered
if (existingStateManager.getCurrentState() != AMQState.CONNECTION_OPEN)
{
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
index 35bc521c80..6500a82818 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
@@ -110,10 +110,6 @@ import org.slf4j.LoggerFactory;
* <tr><td>
* </table>
*
- * @todo Explain the system property: amqj.shared_read_write_pool. How does putting the protocol codec filter before the
- * async write filter make it a shared pool? The pooling filter uses the same thread pool for reading and writing
- * anyway, see {@link org.apache.qpid.pool.PoolingFilter}, docs for comments. Will putting the protocol codec
- * filter before it mean not doing the read/write asynchronously but in the main filter thread?
* @todo Use a single handler instance, by shifting everything to do with the 'protocol session' state, including
* failover state, into AMQProtocolSession, and tracking that from AMQConnection? The lifecycles of
* AMQProtocolSesssion and AMQConnection will be the same, so if there is high cohesion between them, they could
@@ -172,10 +168,10 @@ public class AMQProtocolHandler implements ProtocolEngine
private Job _writeJob;
private ReferenceCountingExecutorService _poolReference = ReferenceCountingExecutorService.getInstance();
private NetworkDriver _networkDriver;
-
+
private long _writtenBytes;
private long _readBytes;
-
+
/**
* Creates a new protocol handler, associated with the specified client connection instance.
*
@@ -215,10 +211,6 @@ public class AMQProtocolHandler implements ProtocolEngine
* process will be started, provided that it is the clients policy to allow failover, and provided that a failover
* has not already been started or failed.
*
- * <p/>It is important to note that when the connection dies this method may be called or {@link #exceptionCaught}
- * may be called first followed by this method. This depends on whether the client was trying to send data at the
- * time of the failure.
- *
* @todo Clarify: presumably exceptionCaught is called when the client is sending during a connection failure and
* not otherwise? The above comment doesn't make that clear.
*/
@@ -261,7 +253,7 @@ public class AMQProtocolHandler implements ProtocolEngine
{
_logger.debug("sessionClose() not allowed to failover");
_connection.exceptionReceived(new AMQDisconnectedException(
- "Server closed connection and reconnection " + "not permitted.",
+ "Server closed connection and reconnection " + "not permitted.",
_stateManager.getLastException()));
}
else
@@ -277,12 +269,15 @@ public class AMQProtocolHandler implements ProtocolEngine
/** See {@link FailoverHandler} to see rationale for separate thread. */
private void startFailoverThread()
{
- Thread failoverThread = new Thread(_failoverHandler);
- failoverThread.setName("Failover");
- // Do not inherit daemon-ness from current thread as this can be a daemon
- // thread such as a AnonymousIoService thread.
- failoverThread.setDaemon(false);
- failoverThread.start();
+ if(!_connection.isClosed())
+ {
+ Thread failoverThread = new Thread(_failoverHandler);
+ failoverThread.setName("Failover");
+ // Do not inherit daemon-ness from current thread as this can be a daemon
+ // thread such as a AnonymousIoService thread.
+ failoverThread.setDaemon(false);
+ failoverThread.start();
+ }
}
public void readerIdle()
@@ -293,7 +288,7 @@ public class AMQProtocolHandler implements ProtocolEngine
_logger.warn("Timed out while waiting for heartbeat from peer.");
_networkDriver.close();
}
-
+
public void writerIdle()
{
_logger.debug("Protocol Session [" + this + "] idle: reader");
@@ -365,6 +360,7 @@ public class AMQProtocolHandler implements ProtocolEngine
public void propagateExceptionToAllWaiters(Exception e)
{
getStateManager().error(e);
+
propagateExceptionToFrameListeners(e);
}
@@ -582,7 +578,7 @@ public class AMQProtocolHandler implements ProtocolEngine
}
_connection.bytesSent(_writtenBytes);
-
+
if (wait)
{
_networkDriver.flush();
@@ -642,7 +638,7 @@ public class AMQProtocolHandler implements ProtocolEngine
_frameListeners.add(listener);
//FIXME: At this point here we should check or before add we should check _stateManager is in an open
- // state so as we don't check we are likely just to time out here as I believe is being seen in QPID-1255
+ // state so as we don't check we are likely just to time out here as I believe is being seen in QPID-1255
}
writeFrame(frame);
@@ -828,7 +824,7 @@ public class AMQProtocolHandler implements ProtocolEngine
{
_networkDriver = driver;
}
-
+
/** @param delay delay in seconds (not ms) */
void initHeartbeats(int delay)
{
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
index cd049c24a1..8910920017 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
@@ -102,7 +102,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
public AMQProtocolSession(AMQProtocolHandler protocolHandler, AMQConnection connection)
{
- _protocolHandler = protocolHandler;
+ _protocolHandler = protocolHandler;
_protocolVersion = connection.getProtocolVersion();
_methodDispatcher = ClientMethodDispatcherImpl.newMethodDispatcher(ProtocolVersion.getLatestSupportedVersion(),
this);
@@ -156,7 +156,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
public SaslClient getSaslClient()
{
- return _saslClient;
+ return _saslClient;
}
/**
@@ -192,7 +192,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
* @throws AMQException if this was not expected
*/
public void unprocessedMessageReceived(final int channelId, UnprocessedMessage message) throws AMQException
- {
+ {
if ((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
{
_channelId2UnprocessedMsgArray[channelId] = message;
@@ -468,4 +468,11 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
{
// No-op, interface munging
}
+
+
+ @Override
+ public String toString()
+ {
+ return "AMQProtocolSession[" + _connection + ']';
+ }
}
diff --git a/qpid/java/common/Composite.tpl b/qpid/java/common/Composite.tpl
index c46d0a12cc..97b7d01f3c 100644
--- a/qpid/java/common/Composite.tpl
+++ b/qpid/java/common/Composite.tpl
@@ -127,7 +127,12 @@ if fields:
${
for f in fields:
if f.option: continue
- out(" $(f.set)($(f.name));\n")
+ if f.ref_type != f.type:
+ out(" $(f.set)($(f.name));\n")
+ else:
+ out(" if($(f.name) != null) {\n")
+ out(" $(f.set)($(f.name));\n")
+ out(" }\n")
if segments:
out(" setHeader(header);\n")
diff --git a/qpid/java/common/genutil.py b/qpid/java/common/genutil.py
index 5a75c2e48c..57a461ed40 100644
--- a/qpid/java/common/genutil.py
+++ b/qpid/java/common/genutil.py
@@ -198,6 +198,7 @@ class Field:
self.read = "dec.read%s()" % self.coder
self.write = "enc.write%s(check(struct).%s)" % (self.coder, self.name)
self.type = jtype(self.type_node)
+ self.ref_type = jref(self.type)
self.default = DEFAULTS.get(self.type, "null")
self.has = camel(1, "has", self.name)
self.get = camel(1, "get", self.name)
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java
index 05fd2bb480..374644b4f2 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java
@@ -50,7 +50,7 @@ public final class AMQDataBlockEncoder implements MessageEncoder
{
_logger.debug("Encoded frame byte-buffer is '" + EncodingUtils.convertToHexString(buffer) + "'");
}
-
+
out.write(buffer);
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
index 1ff39ca790..647d531476 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
@@ -22,6 +22,10 @@ package org.apache.qpid.framing;
import org.apache.mina.common.ByteBuffer;
+import java.util.Date;
+import java.util.Map;
+import java.math.BigDecimal;
+
/**
* AMQTypedValue combines together a native Java Object value, and an {@link AMQType}, as a fully typed AMQP parameter
* value. It provides the ability to read and write fully typed parameters to and from byte buffers. It also provides
@@ -113,4 +117,63 @@ public class AMQTypedValue
return _type.hashCode() ^ (_value == null ? 0 : _value.hashCode());
}
+
+ public static AMQTypedValue toTypedValue(Object val)
+ {
+ if(val == null)
+ {
+ return AMQType.VOID.asTypedValue(null);
+ }
+
+ Class klass = val.getClass();
+ if(klass == String.class)
+ {
+ return AMQType.ASCII_STRING.asTypedValue(val);
+ }
+ else if(klass == Character.class)
+ {
+ return AMQType.ASCII_CHARACTER.asTypedValue(val);
+ }
+ else if(klass == Integer.class)
+ {
+ return AMQType.INT.asTypedValue(val);
+ }
+ else if(klass == Long.class)
+ {
+ return AMQType.LONG.asTypedValue(val);
+ }
+ else if(klass == Float.class)
+ {
+ return AMQType.FLOAT.asTypedValue(val);
+ }
+ else if(klass == Double.class)
+ {
+ return AMQType.DOUBLE.asTypedValue(val);
+ }
+ else if(klass == Date.class)
+ {
+ return AMQType.TIMESTAMP.asTypedValue(val);
+ }
+ else if(klass == Byte.class)
+ {
+ return AMQType.BYTE.asTypedValue(val);
+ }
+ else if(klass == Boolean.class)
+ {
+ return AMQType.BOOLEAN.asTypedValue(val);
+ }
+ else if(klass == byte[].class)
+ {
+ return AMQType.BINARY.asTypedValue(val);
+ }
+ else if(klass == BigDecimal.class)
+ {
+ return AMQType.DECIMAL.asTypedValue(val);
+ }
+ else if(val instanceof Map)
+ {
+ return AMQType.FIELD_TABLE.asTypedValue(FieldTable.convertToFieldTable((Map)val));
+ }
+ return null;
+ }
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
index ed01c91804..9b2f9b3969 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
@@ -828,6 +828,7 @@ public class FieldTable
recalculateEncodedSize();
}
+
public static interface FieldTableElementProcessor
{
public boolean processElement(String propertyName, AMQTypedValue value);
@@ -904,10 +905,13 @@ public class FieldTable
}
}
+ public Object get(String key)
+ {
+ return get(new AMQShortString(key));
+ }
public Object get(AMQShortString key)
{
-
return getObject(key);
}
@@ -1184,4 +1188,24 @@ public class FieldTable
return _properties.equals(f._properties);
}
+
+ public static FieldTable convertToFieldTable(Map<String, Object> map)
+ {
+ if (map != null)
+ {
+ FieldTable table = new FieldTable();
+ for(Map.Entry<String,Object> entry : map.entrySet())
+ {
+ table.put(new AMQShortString(entry.getKey()), entry.getValue());
+ }
+
+ return table;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java
index 0a1cedc4e6..7544d9b7e7 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java
@@ -23,10 +23,14 @@ package org.apache.qpid.framing.abstraction;
import org.apache.qpid.framing.AMQBody;
+import java.nio.ByteBuffer;
+
public interface ProtocolVersionMethodConverter extends MessagePublishInfoConverter
{
AMQBody convertToBody(ContentChunk contentBody);
ContentChunk convertToContentChunk(AMQBody body);
void configure();
+
+ AMQBody convertToBody(ByteBuffer buf);
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java
index a5c5e5f22d..1c4a29b106 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java
@@ -72,6 +72,11 @@ public class MethodConverter_0_9 extends AbstractMethodConverter implements Prot
}
+ public AMQBody convertToBody(java.nio.ByteBuffer buf)
+ {
+ return new ContentBody(ByteBuffer.wrap(buf));
+ }
+
public MessagePublishInfo convertToInfo(AMQMethodBody methodBody)
{
final BasicPublishBody publishBody = ((BasicPublishBody) methodBody);
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java
index 1b0be2b9cc..c87820b9b2 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java
@@ -80,6 +80,11 @@ public class MethodConverter_8_0 extends AbstractMethodConverter implements Prot
_basicPublishMethodId = BasicPublishBodyImpl.METHOD_ID;
}
+
+ public AMQBody convertToBody(java.nio.ByteBuffer buf)
+ {
+ return new ContentBody(ByteBuffer.wrap(buf));
+ }
public MessagePublishInfo convertToInfo(AMQMethodBody methodBody)
{
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java
index 5bfc189b02..31953ea6ab 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java
@@ -28,38 +28,34 @@ import org.apache.qpid.transport.Receiver;
/**
* A ProtocolEngine is a Receiver for java.nio.ByteBuffers. It takes the data passed to it in the received
- * decodes it and then process the result.
- */
-public interface ProtocolEngine extends Receiver<java.nio.ByteBuffer>
-{
- // Sets the network driver providing data for this ProtocolEngine
+ * decodes it and then process the result.
+ */
+public interface ProtocolEngine extends Receiver<java.nio.ByteBuffer>
+{
+ // Sets the network driver providing data for this ProtocolEngine
void setNetworkDriver (NetworkDriver driver);
-
- // Returns the remote address of the NetworkDriver
+
+ // Returns the remote address of the NetworkDriver
SocketAddress getRemoteAddress();
- // Returns the local address of the NetworkDriver
+ // Returns the local address of the NetworkDriver
SocketAddress getLocalAddress();
-
- // Returns number of bytes written
+
+ // Returns number of bytes written
long getWrittenBytes();
-
- // Returns number of bytes read
+
+ // Returns number of bytes read
long getReadBytes();
-
- // Called by the NetworkDriver when the socket has been closed for reading
+
+ // Called by the NetworkDriver when the socket has been closed for reading
void closed();
-
- // Called when the NetworkEngine has not written data for the specified period of time (will trigger a
- // heartbeat)
+
+ // Called when the NetworkEngine has not written data for the specified period of time (will trigger a
+ // heartbeat)
void writerIdle();
-
- // Called when the NetworkEngine has not read data for the specified period of time (will close the connection)
+
+ // Called when the NetworkEngine has not read data for the specified period of time (will close the connection)
void readerIdle();
-
- /**
- * Accepts an AMQFrame for writing to the network. The ProtocolEngine encodes the frame into bytes and
- * passes the data onto the NetworkDriver for sending
- */
- void writeFrame(AMQDataBlock frame);
-} \ No newline at end of file
+
+
+} \ No newline at end of file
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Connection.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/Connection.java
index 1cdd1da72b..3403b591f3 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Connection.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/Connection.java
@@ -55,7 +55,7 @@ public class Connection extends ConnectionInvoker
private static final Logger log = Logger.get(Connection.class);
- enum State { NEW, CLOSED, OPENING, OPEN, CLOSING, CLOSE_RCVD }
+ public enum State { NEW, CLOSED, OPENING, OPEN, CLOSING, CLOSE_RCVD }
class DefaultConnectionListener implements ConnectionListener
{
@@ -84,7 +84,8 @@ public class Connection extends ConnectionInvoker
private SaslServer saslServer;
private SaslClient saslClient;
private long idleTimeout = 0;
-
+ private String _authorizationID;
+
// want to make this final
private int _connectionId;
@@ -118,7 +119,7 @@ public class Connection extends ConnectionInvoker
sender.setIdleTimeout(idleTimeout);
}
- void setState(State state)
+ protected void setState(State state)
{
synchronized (lock)
{
@@ -315,7 +316,14 @@ public class Connection extends ConnectionInvoker
public void dispatch(Method method)
{
Session ssn = getSession(method.getChannel());
- ssn.received(method);
+ if(ssn != null)
+ {
+ ssn.received(method);
+ }
+ else
+ {
+ // TODO
+ }
}
public int getChannelMax()
@@ -525,7 +533,17 @@ public class Connection extends ConnectionInvoker
{
return idleTimeout;
}
-
+
+ public void setAuthorizationID(String authorizationID)
+ {
+ _authorizationID = authorizationID;
+ }
+
+ public String getAuthorizationID()
+ {
+ return _authorizationID;
+ }
+
public String toString()
{
return String.format("conn:%x", System.identityHashCode(this));
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Method.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/Method.java
index 611c742fb1..3c80180d0b 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Method.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/Method.java
@@ -35,6 +35,7 @@ import static org.apache.qpid.transport.util.Functions.*;
public abstract class Method extends Struct implements ProtocolEvent
{
+
public static final Method create(int type)
{
// XXX: should generate separate factories for separate
@@ -43,12 +44,18 @@ public abstract class Method extends Struct implements ProtocolEvent
}
// XXX: command subclass?
+ public static interface CompletionListener
+ {
+ public void onComplete(Method method);
+ }
+
private int id;
private int channel;
private boolean idSet = false;
private boolean sync = false;
private boolean batch = false;
private boolean unreliable = false;
+ private CompletionListener completionListener;
public final int getId()
{
@@ -61,6 +68,11 @@ public abstract class Method extends Struct implements ProtocolEvent
this.idSet = true;
}
+ boolean idSet()
+ {
+ return idSet;
+ }
+
public final int getChannel()
{
return channel;
@@ -76,7 +88,7 @@ public abstract class Method extends Struct implements ProtocolEvent
return sync;
}
- final void setSync(boolean value)
+ public final void setSync(boolean value)
{
this.sync = value;
}
@@ -152,6 +164,26 @@ public abstract class Method extends Struct implements ProtocolEvent
}
}
+
+ public void setCompletionListener(CompletionListener completionListener)
+ {
+ this.completionListener = completionListener;
+ }
+
+ public void complete()
+ {
+ if(completionListener!= null)
+ {
+ completionListener.onComplete(this);
+ completionListener = null;
+ }
+ }
+
+ public boolean hasCompletionListener()
+ {
+ return completionListener != null;
+ }
+
public String toString()
{
StringBuilder str = new StringBuilder();
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java
index 9b2744ee8b..3850dc162b 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java
@@ -52,6 +52,11 @@ public final class RangeSet implements Iterable<Range>
return ranges.getFirst();
}
+ public Range getLast()
+ {
+ return ranges.getLast();
+ }
+
public boolean includes(Range range)
{
for (Range r : this)
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
index 2833565afc..453921ea2b 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
@@ -52,13 +52,28 @@ public class ServerDelegate extends ConnectionDelegate
{
private SaslServer saslServer;
+ private List<Object> _locales;
+ private List<Object> _mechanisms;
+ private Map<String, Object> _clientProperties;
+
+
+ public ServerDelegate()
+ {
+ this(null, Collections.EMPTY_LIST, Collections.singletonList((Object)"utf8"));
+ }
+
+ protected ServerDelegate(Map<String, Object> clientProperties, List<Object> mechanisms, List<Object> locales)
+ {
+ _clientProperties = clientProperties;
+ _mechanisms = mechanisms;
+ _locales = locales;
+ }
public void init(Connection conn, ProtocolHeader hdr)
{
conn.send(new ProtocolHeader(1, 0, 10));
- List<Object> utf8 = new ArrayList<Object>();
- utf8.add("utf8");
- conn.connectionStart(null, Collections.EMPTY_LIST, utf8);
+
+ conn.connectionStart(_clientProperties, _mechanisms, _locales);
}
@Override public void connectionStartOk(Connection conn, ConnectionStartOk ok)
@@ -77,8 +92,8 @@ public class ServerDelegate extends ConnectionDelegate
try
{
- SaslServer ss = Sasl.createSaslServer
- (mechanism, "AMQP", "localhost", null, null);
+
+ SaslServer ss = createSaslServer(mechanism);
if (ss == null)
{
conn.connectionClose
@@ -95,6 +110,14 @@ public class ServerDelegate extends ConnectionDelegate
}
}
+ protected SaslServer createSaslServer(String mechanism)
+ throws SaslException
+ {
+ SaslServer ss = Sasl.createSaslServer
+ (mechanism, "AMQP", "localhost", null, null);
+ return ss;
+ }
+
private void secure(Connection conn, byte[] response)
{
SaslServer ss = conn.getSaslServer();
@@ -108,6 +131,7 @@ public class ServerDelegate extends ConnectionDelegate
(Integer.MAX_VALUE,
org.apache.qpid.transport.network.ConnectionBinding.MAX_FRAME_SIZE,
0, Integer.MAX_VALUE);
+ conn.setAuthorizationID(ss.getAuthorizationID());
}
else
{
@@ -133,9 +157,16 @@ public class ServerDelegate extends ConnectionDelegate
@Override public void connectionOpen(Connection conn, ConnectionOpen open)
{
conn.connectionOpenOk(Collections.EMPTY_LIST);
+
conn.setState(OPEN);
}
+ protected Session getSession(Connection conn, SessionDelegate delegate, SessionAttach atc)
+ {
+ return new Session(conn, delegate, new Binary(atc.getName()), 0);
+ }
+
+
public Session getSession(Connection conn, SessionAttach atc)
{
return new Session(conn, new Binary(atc.getName()), 0);
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Session.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/Session.java
index 3dca4fc44e..818bb19c08 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Session.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/Session.java
@@ -81,7 +81,7 @@ public class Session extends SessionInvoker
private Binary name;
private long expiry;
private int channel;
- private SessionDelegate delegate = new SessionDelegate();
+ private SessionDelegate delegate;
private SessionListener listener = new DefaultSessionListener();
private long timeout = 60000;
private boolean autoSync = false;
@@ -111,9 +111,15 @@ public class Session extends SessionInvoker
private Thread resumer = null;
- Session(Connection connection, Binary name, long expiry)
+ protected Session(Connection connection, Binary name, long expiry)
+ {
+ this(connection, new SessionDelegate(), name, expiry);
+ }
+
+ protected Session(Connection connection, SessionDelegate delegate, Binary name, long expiry)
{
this.connection = connection;
+ this.delegate = delegate;
this.name = name;
this.expiry = expiry;
initReceiver();
@@ -440,7 +446,7 @@ public class Session extends SessionInvoker
}
}
- boolean complete(int lower, int upper)
+ protected boolean complete(int lower, int upper)
{
//avoid autoboxing
if(log.isDebugEnabled())
@@ -457,8 +463,9 @@ public class Session extends SessionInvoker
if (m != null)
{
commandBytes -= m.getBodySize();
+ m.complete();
+ commands[idx] = null;
}
- commands[idx] = null;
}
if (le(lower, maxComplete + 1))
{
@@ -486,13 +493,28 @@ public class Session extends SessionInvoker
}
}
- final private boolean isFull(int id)
+ protected boolean isFull(int id)
+ {
+ return isCommandsFull(id) || isBytesFull();
+ }
+
+ protected boolean isBytesFull()
{
- return id - maxComplete >= commands.length || commandBytes >= byteLimit;
+ return commandBytes >= byteLimit;
+ }
+
+ protected boolean isCommandsFull(int id)
+ {
+ return id - maxComplete >= commands.length;
}
public void invoke(Method m)
{
+ invoke(m,(Runnable)null);
+ }
+
+ public void invoke(Method m, Runnable postIdSettingAction)
+ {
if (m.getEncodedTrack() == Frame.L4)
{
if (m.hasPayload())
@@ -553,8 +575,13 @@ public class Session extends SessionInvoker
"(state=%s)", state));
}
- int next = commandsOut++;
+ int next;
+ next = commandsOut++;
m.setId(next);
+ if(postIdSettingAction != null)
+ {
+ postIdSettingAction.run();
+ }
if (isFull(next))
{
@@ -607,7 +634,7 @@ public class Session extends SessionInvoker
{
sessionCommandPoint(0, 0);
}
- if (expiry > 0 && !m.isUnreliable())
+ if ((expiry > 0 && !m.isUnreliable()) || m.hasCompletionListener())
{
commands[mod(next, commands.length)] = m;
commandBytes += m.getBodySize();
@@ -617,6 +644,7 @@ public class Session extends SessionInvoker
m.setSync(true);
}
needSync = !m.isSync();
+
try
{
send(m);
@@ -641,7 +669,7 @@ public class Session extends SessionInvoker
// flush every 64K commands to avoid ambiguity on
// wraparound
- if ((next % 65536) == 0)
+ if (shouldIssueFlush(next))
{
try
{
@@ -669,6 +697,11 @@ public class Session extends SessionInvoker
}
}
+ protected boolean shouldIssueFlush(int next)
+ {
+ return (next % 65536) == 0;
+ }
+
public void sync()
{
sync(timeout);
@@ -910,6 +943,14 @@ public class Session extends SessionInvoker
}
}
}
+ if(state == CLOSED)
+ {
+ delegate.closed(this);
+ }
+ else
+ {
+ delegate.detached(this);
+ }
}
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java
index c8d0855607..6146f029b2 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java
@@ -184,4 +184,11 @@ public class SessionDelegate
}
}
+ public void closed(Session session)
+ {
+ }
+
+ public void detached(Session session)
+ {
+ }
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
index 33d552b91e..357caa26e1 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
@@ -186,8 +186,9 @@ public class Assembler implements Receiver<NetworkEvent>, NetworkDelegate
case COMMAND:
int commandType = dec.readUint16();
// read in the session header, right now we don't use it
- dec.readUint16();
+ int hdr = dec.readUint16();
command = Method.create(commandType);
+ command.setSync((0x0001 & hdr) != 0);
command.read(dec);
if (command.hasPayload())
{
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java
index 408c95e075..2132fc2c03 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java
@@ -39,7 +39,7 @@ import static org.apache.qpid.transport.network.InputHandler.State.*;
* @author Rafael H. Schloming
*/
-public final class InputHandler implements Receiver<ByteBuffer>
+public class InputHandler implements Receiver<ByteBuffer>
{
public enum State
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
index 6144edb947..ea48e48721 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
@@ -137,6 +137,7 @@ final class IoReceiver implements Runnable
}
catch (Throwable t)
{
+ t.printStackTrace();
if (!(shutdownBroken &&
t instanceof SocketException &&
t.getMessage().equalsIgnoreCase("socket closed") &&
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java
index b0d1c46572..3838bf76be 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java
@@ -229,7 +229,7 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver
if (_socketConnector instanceof SocketConnector)
{
((SocketConnector) _socketConnector).setWorkerTimeout(0);
- }
+ }
ConnectFuture future = _socketConnector.connect(new InetSocketAddress(destination, port), this, cfg);
future.join();
@@ -279,7 +279,10 @@ public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver
public void send(ByteBuffer msg)
{
- _lastWriteFuture = _ioSession.write(org.apache.mina.common.ByteBuffer.wrap(msg));
+ org.apache.mina.common.ByteBuffer minaBuf = org.apache.mina.common.ByteBuffer.allocate(msg.capacity());
+ minaBuf.put(msg);
+ minaBuf.flip();
+ _lastWriteFuture = _ioSession.write(minaBuf);
}
public void setIdleTimeout(long l)
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java
index 784943b404..b2fdf48267 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java
@@ -113,12 +113,12 @@ public class MessageListenerMultiConsumerTest extends QpidTestCase
for (int loops = 0; (msg < MSG_COUNT) || (loops < MAX_LOOPS); loops++)
{
- if (_consumer1.receive(100) != null)
+ if (_consumer1.receive(1000) != null)
{
msg++;
}
- if (_consumer2.receive(100) != null)
+ if (_consumer2.receive(1000) != null)
{
msg++;
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java
index ba05dc6b3e..266cb42ad7 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java
@@ -215,7 +215,7 @@ public class BindingLoggingTest extends AbstractTestLogging
List<String> results = _monitor.findMatches(BND_PREFIX);
// We will have two binds as we bind all queues to the default exchange
- assertEquals("Result set larger than expected.", 4, results.size());
+ assertEquals("Result not as expected." + results, 4, results.size());
String messageID = "BND-1001";
@@ -241,7 +241,7 @@ public class BindingLoggingTest extends AbstractTestLogging
String subject = fromSubject(log);
- assertTrue("Routing Key does not start with TempQueue:"+AbstractTestLogSubject.getSlice("rk", subject),
+ assertTrue("Routing Key does not start with TempQueue:"+AbstractTestLogSubject.getSlice("rk", subject),
AbstractTestLogSubject.getSlice("rk", subject).startsWith("TempQueue"));
assertEquals("Virtualhost not correct.", "/test",
AbstractTestLogSubject.getSlice("vh", subject));
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java
index 509c027cbf..fe25bf07f0 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -34,6 +34,7 @@ public class SubscriptionTestHelper implements Subscription
private final List<QueueEntry> messages;
private final Object key;
private boolean isSuspended;
+ private AMQQueue.Context _queueContext;
public SubscriptionTestHelper(Object key)
{
@@ -59,6 +60,11 @@ public class SubscriptionTestHelper implements Subscription
public void setQueue(AMQQueue queue, boolean exclusive)
{
+
+ }
+
+ public void setNoLocal(boolean noLocal)
+ {
}
@@ -102,24 +108,34 @@ public class SubscriptionTestHelper implements Subscription
//To change body of implemented methods use File | Settings | File Templates.
}
- public void restoreCredit(final QueueEntry queueEntry)
+ public void onDequeue(final QueueEntry queueEntry)
{
}
+ public void restoreCredit(QueueEntry queueEntry)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public void setStateListener(final StateListener listener)
{
//To change body of implemented methods use File | Settings | File Templates.
}
-
+
public State getState()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
- public QueueEntry getLastSeenEntry()
+ public AMQQueue.Context getQueueContext()
{
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ return _queueContext;
+ }
+
+ public void setQueueContext(AMQQueue.Context queueContext)
+ {
+ _queueContext = queueContext;
}
public boolean setLastSeenEntry(QueueEntry expected, QueueEntry newValue)
@@ -131,7 +147,7 @@ public class SubscriptionTestHelper implements Subscription
{
return null;
}
-
+
public void start()
{
//no-op
@@ -152,6 +168,21 @@ public class SubscriptionTestHelper implements Subscription
return false; //To change body of implemented methods use File | Settings | File Templates.
}
+ public void confirmAutoClose()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void set(String key, Object value)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Object get(String key)
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public LogActor getLogActor()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
@@ -167,6 +198,11 @@ public class SubscriptionTestHelper implements Subscription
return null; //To change body of implemented methods use File | Settings | File Templates.
}
+ public QueueEntry.SubscriptionAssignedState getAssignedState()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public void queueDeleted(AMQQueue queue)
{
}
@@ -216,6 +252,16 @@ public class SubscriptionTestHelper implements Subscription
return false;
}
+ public boolean acquires()
+ {
+ return true;
+ }
+
+ public boolean seesRequeues()
+ {
+ return true;
+ }
+
public boolean isBrowser()
{
return false;
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java
index dde235f73e..9487f72ac8 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java
@@ -873,7 +873,12 @@ public class SimpleACLTest extends QpidTestCase implements ConnectionListener
{
Throwable cause = e.getLinkedException();
- if (!(cause instanceof AMQAuthenticationException))
+ if (cause == null)
+ {
+ e.printStackTrace(System.out);
+ fail("JMS Exception did not have cause");
+ }
+ else if (!(cause instanceof AMQAuthenticationException))
{
cause.printStackTrace(System.out);
assertEquals("Incorrect exception", IllegalStateException.class, cause.getClass());
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
index 7d8c81f4d5..b41aa661ea 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
@@ -25,15 +25,14 @@ 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.abstraction.ContentChunk;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.MessageMetaData;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.logging.LogSubject;
import java.util.HashMap;
import java.util.Iterator;
+import java.nio.ByteBuffer;
public class SlowMessageStore implements MessageStore
{
@@ -47,14 +46,21 @@ public class SlowMessageStore implements MessageStore
private static final String POST = "post";
private String DEFAULT_DELAY = "default";
- public void configure(VirtualHost virtualHost, String base, VirtualHostConfiguration config) throws Exception
+ // ***** MessageStore Interface.
+
+ public void configureConfigStore(String name,
+ ConfigurationRecoveryHandler recoveryHandler,
+ Configuration config,
+ LogSubject logSubject) throws Exception
{
- _logger.info("Starting SlowMessageStore on Virtualhost:" + virtualHost.getName());
- Configuration delays = config.getStoreConfiguration().subset(DELAYS);
+ //To change body of implemented methods use File | Settings | File Templates.
+
+ _logger.info("Starting SlowMessageStore on Virtualhost:" + name);
+ Configuration delays = config.subset(DELAYS);
configureDelays(delays);
- String messageStoreClass = config.getStoreConfiguration().getString("realStore");
+ String messageStoreClass = config.getString("realStore");
if (delays.containsKey(DEFAULT_DELAY))
{
@@ -73,11 +79,11 @@ public class SlowMessageStore implements MessageStore
" does not.");
}
_realStore = (MessageStore) o;
- _realStore.configure(virtualHost, base + ".store", config);
+ _realStore.configureConfigStore(name, recoveryHandler, config, logSubject);
}
else
{
- _realStore.configure(virtualHost, base + ".store", config);
+ _realStore.configureConfigStore(name, recoveryHandler, config, logSubject);
}
}
@@ -133,7 +139,7 @@ public class SlowMessageStore implements MessageStore
}
long slept = (System.nanoTime() - start) / 1000000;
-
+
if (slept >= delay)
{
_logger.info("Done sleep for:" + slept+":"+delay);
@@ -146,7 +152,14 @@ public class SlowMessageStore implements MessageStore
}
}
- // ***** MessageStore Interface.
+
+ public void configureMessageStore(String name,
+ MessageStoreRecoveryHandler recoveryHandler,
+ Configuration config,
+ LogSubject logSubject) throws Exception
+ {
+ _realStore.configureMessageStore(name, recoveryHandler, config, logSubject);
+ }
public void close() throws Exception
{
@@ -155,13 +168,12 @@ public class SlowMessageStore implements MessageStore
doPostDelay("close");
}
- public void removeMessage(StoreContext storeContext, Long messageId) throws AMQException
+ public <M extends StorableMessageMetaData> StoredMessage<M> addMessage(M metaData)
{
- doPreDelay("removeMessage");
- _realStore.removeMessage(storeContext, messageId);
- doPostDelay("removeMessage");
+ return _realStore.addMessage(metaData);
}
+
public void createExchange(Exchange exchange) throws AMQException
{
doPreDelay("createExchange");
@@ -209,90 +221,93 @@ public class SlowMessageStore implements MessageStore
doPostDelay("removeQueue");
}
- public void enqueueMessage(StoreContext context, AMQQueue queue, Long messageId) throws AMQException
- {
- doPreDelay("enqueueMessage");
- _realStore.enqueueMessage(context, queue, messageId);
- doPostDelay("enqueueMessage");
- }
-
- public void dequeueMessage(StoreContext context, AMQQueue queue, Long messageId) throws AMQException
+ public void configureTransactionLog(String name,
+ TransactionLogRecoveryHandler recoveryHandler,
+ Configuration storeConfiguration, LogSubject logSubject)
+ throws Exception
{
- doPreDelay("dequeueMessage");
- _realStore.dequeueMessage(context, queue, messageId);
- doPostDelay("dequeueMessage");
+ _realStore.configureTransactionLog(name, recoveryHandler, storeConfiguration, logSubject);
}
- public void beginTran(StoreContext context) throws AMQException
+ public Transaction newTransaction()
{
doPreDelay("beginTran");
- _realStore.beginTran(context);
+ Transaction txn = new SlowTransaction(_realStore.newTransaction());
doPostDelay("beginTran");
+ return txn;
}
- public void commitTran(StoreContext context) throws AMQException
- {
- doPreDelay("commitTran");
- _realStore.commitTran(context);
- doPostDelay("commitTran");
- }
- public void abortTran(StoreContext context) throws AMQException
+ public boolean isPersistent()
{
- doPreDelay("abortTran");
- _realStore.abortTran(context);
- doPostDelay("abortTran");
+ return _realStore.isPersistent();
}
- public boolean inTran(StoreContext context)
+ public void storeMessageHeader(Long messageNumber, ServerMessage message)
{
- doPreDelay("inTran");
- boolean b = _realStore.inTran(context);
- doPostDelay("inTran");
- return b;
+ //To change body of implemented methods use File | Settings | File Templates.
}
- public Long getNewMessageId()
+ public void storeContent(Long messageNumber, long offset, ByteBuffer body)
{
- doPreDelay("getNewMessageId");
- Long l = _realStore.getNewMessageId();
- doPostDelay("getNewMessageId");
- return l;
+ //To change body of implemented methods use File | Settings | File Templates.
}
- public void storeContentBodyChunk(StoreContext context, Long messageId, int index, ContentChunk contentBody, boolean lastContentBody) throws AMQException
+ public ServerMessage getMessage(Long messageNumber)
{
- doPreDelay("storeContentBodyChunk");
- _realStore.storeContentBodyChunk(context, messageId, index, contentBody, lastContentBody);
- doPostDelay("storeContentBodyChunk");
+ return null; //To change body of implemented methods use File | Settings | File Templates.
}
- public void storeMessageMetaData(StoreContext context, Long messageId, MessageMetaData messageMetaData) throws AMQException
+ private class SlowTransaction implements Transaction
{
- doPreDelay("storeMessageMetaData");
- _realStore.storeMessageMetaData(context, messageId, messageMetaData);
- doPostDelay("storeMessageMetaData");
- }
+ private final Transaction _underlying;
- public MessageMetaData getMessageMetaData(StoreContext context, Long messageId) throws AMQException
- {
- doPreDelay("getMessageMetaData");
- MessageMetaData mmd = _realStore.getMessageMetaData(context, messageId);
- doPostDelay("getMessageMetaData");
- return mmd;
- }
+ private SlowTransaction(Transaction underlying)
+ {
+ _underlying = underlying;
+ }
- public ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException
- {
- doPreDelay("getContentBodyChunk");
- ContentChunk c = _realStore.getContentBodyChunk(context, messageId, index);
- doPostDelay("getContentBodyChunk");
- return c;
- }
+ public void enqueueMessage(TransactionLogResource queue, Long messageId)
+ throws AMQException
+ {
+ doPreDelay("enqueueMessage");
+ _underlying.enqueueMessage(queue, messageId);
+ doPostDelay("enqueueMessage");
+ }
- public boolean isPersistent()
- {
- return _realStore.isPersistent();
+ public void dequeueMessage(TransactionLogResource queue, Long messageId)
+ throws AMQException
+ {
+ doPreDelay("dequeueMessage");
+ _underlying.dequeueMessage(queue, messageId);
+ doPostDelay("dequeueMessage");
+ }
+
+ public void commitTran()
+ throws AMQException
+ {
+ doPreDelay("commitTran");
+ _underlying.commitTran();
+ doPostDelay("commitTran");
+ }
+
+ public StoreFuture commitTranAsync()
+ throws AMQException
+ {
+ doPreDelay("commitTran");
+ StoreFuture future = _underlying.commitTranAsync();
+ doPostDelay("commitTran");
+ return future;
+ }
+
+ public void abortTran()
+ throws AMQException
+ {
+ doPreDelay("abortTran");
+ _underlying.abortTran();
+ doPostDelay("abortTran");
+ }
}
+
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
index 25b9b0ba14..5ea203bda3 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
@@ -81,9 +81,14 @@ public class CancelTest extends QpidTestCase
assertTrue(e.hasMoreElements());
+ int i = 0;
while (e.hasMoreElements())
{
e.nextElement();
+ if(++i > 1)
+ {
+ fail("Two many elemnts to browse!");
+ }
}
browser.close();
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java
index d1bcaa1bb8..eb0c539a6e 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java
@@ -79,7 +79,7 @@ public class DupsOkTest extends QpidTestCase
* This test sends x messages and receives them with an async consumer.
* Waits for all messages to be received or for 60 s
* and checks whether the queue is empty.
- *
+ *
* @throws Exception
*/
public void testDupsOK() throws Exception
@@ -93,7 +93,7 @@ public class DupsOkTest extends QpidTestCase
assertEquals("The queue should have msgs at start", MSG_COUNT, ((AMQSession) clientSession).getQueueDepth((AMQDestination) _queue));
- clientConnection.start();
+ clientConnection.start();
consumer.setMessageListener(new MessageListener()
{
@@ -110,7 +110,7 @@ public class DupsOkTest extends QpidTestCase
if (message instanceof TextMessage)
{
try
- {
+ {
if (message.getIntProperty("count") == MSG_COUNT)
{
try
@@ -156,7 +156,11 @@ public class DupsOkTest extends QpidTestCase
// before the dispatcher has sent the ack back to the broker.
consumer.close();
- assertEquals("The queue should have 0 msgs left", 0, ((AMQSession) clientSession).getQueueDepth((AMQDestination) _queue));
+ clientSession.close();
+
+ final Session clientSession2 = clientConnection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
+
+ assertEquals("The queue should have 0 msgs left", 0, ((AMQSession) clientSession2).getQueueDepth((AMQDestination) _queue));
clientConnection.close();
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java
index e9aed4de01..9558f23b89 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java
@@ -79,16 +79,22 @@ public class LargeMessageTest extends QpidTestCase
}
// Test boundary of 1 packet to 2 packets
- public void test64kminus1()
+ public void test64kminus9()
{
- checkLargeMessage((64 * 1024) - 1);
+ checkLargeMessage((64 * 1024) - 9);
}
- public void test64k()
+ public void test64kminus8()
{
- checkLargeMessage(64 * 1024);
+ checkLargeMessage((64 * 1024)-8);
}
+ public void test64kminus7()
+ {
+ checkLargeMessage((64 * 1024)-7);
+ }
+
+
public void test64kplus1()
{
checkLargeMessage((64 * 1024) + 1);
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
index ec23256f38..f1cac22f08 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
@@ -50,7 +50,8 @@ public class MessageRequeueTest extends QpidTestCase
protected final String queue = "direct://amq.direct//message-requeue-test-queue";
protected String payload = "Message:";
- protected final String BROKER = "vm://:1";
+ //protected final String BROKER = "vm://:1";
+ protected final String BROKER = "tcp://127.0.0.1:5672";
private boolean testReception = true;
private long[] receieved = new long[numTestMessages + 1];
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
index f8ba7060a9..742e2ac518 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
@@ -311,11 +311,13 @@ public class TopicSessionTest extends QpidTestCase
AMQTopic topic = new AMQTopic(con, "testNoLocal");
- TopicSession session1 = con.createTopicSession(true, AMQSession.NO_ACKNOWLEDGE);
+ TopicSession session1 = con.createTopicSession(true, AMQSession.AUTO_ACKNOWLEDGE);
TopicSubscriber noLocal = session1.createSubscriber(topic, "", true);
+
TopicSubscriber select = session1.createSubscriber(topic, "Selector = 'select'", false);
TopicSubscriber normal = session1.createSubscriber(topic);
+
TopicPublisher publisher = session1.createPublisher(topic);
con.start();
@@ -329,12 +331,12 @@ public class TopicSessionTest extends QpidTestCase
m = (TextMessage) normal.receive(1000);
assertNotNull(m);
session1.commit();
-
+
//test selector subscriber doesn't message
m = (TextMessage) select.receive(1000);
assertNull(m);
session1.commit();
-
+
//test nolocal subscriber doesn't message
m = (TextMessage) noLocal.receive(1000);
if (m != null)
@@ -349,12 +351,12 @@ public class TopicSessionTest extends QpidTestCase
publisher.publish(message);
session1.commit();
-
+
//test normal subscriber gets message
m = (TextMessage) normal.receive(1000);
assertNotNull(m);
session1.commit();
-
+
//test selector subscriber does get message
m = (TextMessage) select.receive(1000);
assertNotNull(m);
@@ -365,7 +367,7 @@ public class TopicSessionTest extends QpidTestCase
assertNull(m);
AMQConnection con2 = (AMQConnection) getConnection("guest", "guest", "foo");
- TopicSession session2 = con2.createTopicSession(true, AMQSession.NO_ACKNOWLEDGE);
+ TopicSession session2 = con2.createTopicSession(true, AMQSession.AUTO_ACKNOWLEDGE);
TopicPublisher publisher2 = session2.createPublisher(topic);
@@ -386,18 +388,18 @@ public class TopicSessionTest extends QpidTestCase
session1.commit();
//test nolocal subscriber does message
- m = (TextMessage) noLocal.receive(100);
+ m = (TextMessage) noLocal.receive(1000);
assertNotNull(m);
con.close();
con2.close();
}
-
+
/**
* This tests QPID-1191, where messages which are sent to a topic but are not consumed by a subscriber
* due to a selector can be leaked.
- * @throws Exception
+ * @throws Exception
*/
public void testNonMatchingMessagesDoNotFillQueue() throws Exception
{
@@ -420,27 +422,27 @@ public class TopicSessionTest extends QpidTestCase
message = session.createTextMessage("non-matching 1");
publisher.publish(message);
session.commit();
-
+
// Send and consume matching message
message = session.createTextMessage("hello");
message.setStringProperty("Selector", "select");
publisher.publish(message);
session.commit();
-
+
m = (TextMessage) selector.receive(1000);
assertNotNull("should have received message", m);
assertEquals("Message contents were wrong", "hello", m.getText());
-
+
// Send non-matching message
message = session.createTextMessage("non-matching 2");
publisher.publish(message);
session.commit();
-
+
// Assert queue count is 0
long depth = ((AMQTopicSessionAdaptor) session).getSession().getQueueDepth(topic);
assertEquals("Queue depth was wrong", 0, depth);
-
+
}
public static junit.framework.Test suite()
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java
index 0426c4f45f..b1d14721bd 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java
@@ -23,6 +23,8 @@ package org.apache.qpid.test.utils;
import org.apache.qpid.util.FileUtils;
import javax.naming.NamingException;
+import javax.jms.JMSException;
+import javax.naming.NamingException;
import org.apache.qpid.client.AMQConnectionFactory;
import org.slf4j.Logger;
diff --git a/qpid/java/test-profiles/java-derby.testprofile b/qpid/java/test-profiles/java-derby.testprofile
index e7c1dc1fd6..2887501a9b 100644
--- a/qpid/java/test-profiles/java-derby.testprofile
+++ b/qpid/java/test-profiles/java-derby.testprofile
@@ -1,8 +1,8 @@
broker.language=java
-broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml
+broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT --exclude-0-10 @PORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml
broker.clean=${test.profiles}/clean-dir ${build.data} ${project.root}/build/work/derbyDB
broker.ready=BRK-1004
broker.stopped=Exception
broker.config=${project.root}/build/etc/config-systests-derby.xml
-
+qpid.amqp.version=0-9
profile.excludes=08StandaloneExcludes
diff --git a/qpid/java/test-profiles/java.0.10.testprofile b/qpid/java/test-profiles/java.0.10.testprofile
new file mode 100755
index 0000000000..35e3530cab
--- /dev/null
+++ b/qpid/java/test-profiles/java.0.10.testprofile
@@ -0,0 +1,8 @@
+broker.language=java
+broker.version=0-10
+broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml
+broker.clean=${test.profiles}/clean-dir ${build.data} ${project.root}/build/work/derbyDB
+broker.ready=BRK-1004
+broker.stopped=Exception
+
+profile.excludes=08TransientExcludes 08StandaloneExcludes 010Excludes 010TransientExcludes
diff --git a/qpid/java/test-profiles/java.testprofile b/qpid/java/test-profiles/java.testprofile
index 05a801ee06..8dd835a335 100644
--- a/qpid/java/test-profiles/java.testprofile
+++ b/qpid/java/test-profiles/java.testprofile
@@ -1,7 +1,7 @@
broker.language=java
-broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml
+broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT --exclude-0-10 @PORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml
broker.clean=${test.profiles}/clean-dir ${build.data} ${project.root}/build/work/derbyDB
broker.ready=BRK-1004
broker.stopped=Exception
-
+qpid.amqp.version=0-9
profile.excludes=08TransientExcludes 08StandaloneExcludes