summaryrefslogtreecommitdiff
path: root/qpid/cpp/src
diff options
context:
space:
mode:
authorKim van der Riet <kpvdr@apache.org>2013-09-20 18:59:30 +0000
committerKim van der Riet <kpvdr@apache.org>2013-09-20 18:59:30 +0000
commitc70bf3ea28cdf6bafd8571690d3e5c466a0658a2 (patch)
tree68b24940e433f3f9c278b054d9ea1622389bd332 /qpid/cpp/src
parentfcdf1723c7b5cdf0772054a93edb6e7d97c4bb1e (diff)
downloadqpid-python-c70bf3ea28cdf6bafd8571690d3e5c466a0658a2.tar.gz
QPID-4984: WIP - Merge from trunk r.1525056
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/linearstore@1525101 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/cpp/src')
-rw-r--r--qpid/cpp/src/CMakeLists.txt410
-rw-r--r--qpid/cpp/src/Makefile.am1119
-rw-r--r--qpid/cpp/src/amqp.cmake70
-rwxr-xr-xqpid/cpp/src/check-abi81
-rw-r--r--qpid/cpp/src/finddb.cmake20
-rw-r--r--qpid/cpp/src/ha.mk72
-rw-r--r--qpid/cpp/src/legacystore.cmake4
-rw-r--r--qpid/cpp/src/legacystore.mk110
-rw-r--r--qpid/cpp/src/libqpidmessaging-api-symbols.txt214
-rw-r--r--qpid/cpp/src/libqpidtypes-api-symbols.txt122
-rwxr-xr-xqpid/cpp/src/prof4
-rw-r--r--qpid/cpp/src/qmf.mk177
-rw-r--r--qpid/cpp/src/qmf/engine/Agent.cpp915
-rw-r--r--qpid/cpp/src/qmf/engine/BrokerProxyImpl.cpp827
-rw-r--r--qpid/cpp/src/qmf/engine/BrokerProxyImpl.h241
-rw-r--r--qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp278
-rw-r--r--qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.h63
-rw-r--r--qpid/cpp/src/qmf/engine/ConsoleImpl.cpp458
-rw-r--r--qpid/cpp/src/qmf/engine/ConsoleImpl.h148
-rw-r--r--qpid/cpp/src/qmf/engine/EventImpl.cpp120
-rw-r--r--qpid/cpp/src/qmf/engine/EventImpl.h57
-rw-r--r--qpid/cpp/src/qmf/engine/ObjectIdImpl.cpp210
-rw-r--r--qpid/cpp/src/qmf/engine/ObjectIdImpl.h72
-rw-r--r--qpid/cpp/src/qmf/engine/ObjectImpl.cpp232
-rw-r--r--qpid/cpp/src/qmf/engine/ObjectImpl.h76
-rw-r--r--qpid/cpp/src/qmf/engine/Protocol.cpp52
-rw-r--r--qpid/cpp/src/qmf/engine/Protocol.h69
-rw-r--r--qpid/cpp/src/qmf/engine/QueryImpl.cpp103
-rw-r--r--qpid/cpp/src/qmf/engine/QueryImpl.h102
-rw-r--r--qpid/cpp/src/qmf/engine/ResilientConnection.cpp512
-rw-r--r--qpid/cpp/src/qmf/engine/SchemaImpl.cpp610
-rw-r--r--qpid/cpp/src/qmf/engine/SchemaImpl.h230
-rw-r--r--qpid/cpp/src/qmf/engine/SequenceManager.cpp96
-rw-r--r--qpid/cpp/src/qmf/engine/SequenceManager.h68
-rw-r--r--qpid/cpp/src/qmf/engine/ValueImpl.cpp571
-rw-r--r--qpid/cpp/src/qmf/engine/ValueImpl.h166
-rw-r--r--qpid/cpp/src/qmfc.mk57
-rw-r--r--qpid/cpp/src/qpid.linkmap10
-rwxr-xr-xqpid/cpp/src/qpid/Address.h56
-rw-r--r--qpid/cpp/src/qpid/CommonImportExport.h35
-rw-r--r--qpid/cpp/src/qpid/Exception.h91
-rw-r--r--qpid/cpp/src/qpid/InlineAllocator.h101
-rw-r--r--qpid/cpp/src/qpid/InlineVector.h68
-rw-r--r--qpid/cpp/src/qpid/Msg.h79
-rw-r--r--qpid/cpp/src/qpid/NullSaslClient.cpp (renamed from qpid/cpp/src/tests/ConsoleTest.cpp)52
-rw-r--r--qpid/cpp/src/qpid/NullSaslClient.h41
-rw-r--r--qpid/cpp/src/qpid/NullSaslServer.h3
-rw-r--r--qpid/cpp/src/qpid/Options.h193
-rw-r--r--qpid/cpp/src/qpid/RangeSet.h328
-rw-r--r--qpid/cpp/src/qpid/Sasl.h3
-rw-r--r--qpid/cpp/src/qpid/SaslFactory.cpp4
-rw-r--r--qpid/cpp/src/qpid/SaslFactory.h1
-rw-r--r--qpid/cpp/src/qpid/SaslServer.h2
-rw-r--r--qpid/cpp/src/qpid/SessionId.h60
-rw-r--r--qpid/cpp/src/qpid/Url.h96
-rw-r--r--qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp4
-rw-r--r--qpid/cpp/src/qpid/agent/ManagementAgentImpl.cpp1434
-rw-r--r--qpid/cpp/src/qpid/agent/ManagementAgentImpl.h294
-rw-r--r--qpid/cpp/src/qpid/amqp/DataBuilder.cpp194
-rw-r--r--qpid/cpp/src/qpid/amqp/DataBuilder.h79
-rw-r--r--qpid/cpp/src/qpid/amqp/Decoder.cpp130
-rw-r--r--qpid/cpp/src/qpid/amqp/Decoder.h3
-rw-r--r--qpid/cpp/src/qpid/amqp/Descriptor.cpp2
-rw-r--r--qpid/cpp/src/qpid/amqp/Descriptor.h10
-rw-r--r--qpid/cpp/src/qpid/amqp/Encoder.cpp85
-rw-r--r--qpid/cpp/src/qpid/amqp/Encoder.h13
-rw-r--r--qpid/cpp/src/qpid/amqp/ListBuilder.cpp (renamed from qpid/cpp/src/qpid/console/Agent.cpp)17
-rw-r--r--qpid/cpp/src/qpid/amqp/ListBuilder.h41
-rw-r--r--qpid/cpp/src/qpid/amqp/ListReader.h8
-rw-r--r--qpid/cpp/src/qpid/amqp/MapBuilder.cpp104
-rw-r--r--qpid/cpp/src/qpid/amqp/MapBuilder.h34
-rw-r--r--qpid/cpp/src/qpid/amqp/MapReader.cpp4
-rw-r--r--qpid/cpp/src/qpid/amqp/MapReader.h54
-rw-r--r--qpid/cpp/src/qpid/amqp/MessageEncoder.cpp168
-rw-r--r--qpid/cpp/src/qpid/amqp/MessageEncoder.h38
-rw-r--r--qpid/cpp/src/qpid/amqp/MessageReader.cpp242
-rw-r--r--qpid/cpp/src/qpid/amqp/MessageReader.h196
-rw-r--r--qpid/cpp/src/qpid/amqp/Reader.h4
-rw-r--r--qpid/cpp/src/qpid/amqp/Sasl.h12
-rw-r--r--qpid/cpp/src/qpid/amqp/SaslClient.cpp2
-rw-r--r--qpid/cpp/src/qpid/amqp/SaslClient.h21
-rw-r--r--qpid/cpp/src/qpid/amqp/SaslServer.cpp2
-rw-r--r--qpid/cpp/src/qpid/amqp/SaslServer.h12
-rw-r--r--qpid/cpp/src/qpid/amqp/descriptors.h1
-rw-r--r--qpid/cpp/src/qpid/amqp/typecodes.h2
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/Codecs.h86
-rw-r--r--qpid/cpp/src/qpid/broker/Broker.cpp11
-rw-r--r--qpid/cpp/src/qpid/broker/Broker.h10
-rw-r--r--qpid/cpp/src/qpid/broker/BrokerObserver.h (renamed from qpid/cpp/src/qpid/broker/ConfigurationObserver.h)15
-rw-r--r--qpid/cpp/src/qpid/broker/BrokerObservers.h (renamed from qpid/cpp/src/qpid/broker/ConfigurationObservers.h)33
-rw-r--r--qpid/cpp/src/qpid/broker/DeliveryRecord.cpp4
-rw-r--r--qpid/cpp/src/qpid/broker/DirectExchange.cpp5
-rw-r--r--qpid/cpp/src/qpid/broker/DirectExchange.h2
-rw-r--r--qpid/cpp/src/qpid/broker/DtxAck.h3
-rw-r--r--qpid/cpp/src/qpid/broker/Exchange.cpp1
-rw-r--r--qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp4
-rw-r--r--qpid/cpp/src/qpid/broker/FanOutExchange.cpp5
-rw-r--r--qpid/cpp/src/qpid/broker/HeadersExchange.cpp5
-rw-r--r--qpid/cpp/src/qpid/broker/HeadersExchange.h2
-rw-r--r--qpid/cpp/src/qpid/broker/IngressCompletion.h2
-rw-r--r--qpid/cpp/src/qpid/broker/Link.cpp2
-rw-r--r--qpid/cpp/src/qpid/broker/Link.h4
-rw-r--r--qpid/cpp/src/qpid/broker/LossyQueue.cpp2
-rw-r--r--qpid/cpp/src/qpid/broker/Lvq.cpp3
-rw-r--r--qpid/cpp/src/qpid/broker/Message.cpp4
-rw-r--r--qpid/cpp/src/qpid/broker/Message.h6
-rw-r--r--qpid/cpp/src/qpid/broker/MessageStoreModule.cpp2
-rw-r--r--qpid/cpp/src/qpid/broker/MessageStoreModule.h2
-rw-r--r--qpid/cpp/src/qpid/broker/ObjectFactory.h3
-rw-r--r--qpid/cpp/src/qpid/broker/PagedQueue.cpp8
-rw-r--r--qpid/cpp/src/qpid/broker/PersistableMessage.h4
-rw-r--r--qpid/cpp/src/qpid/broker/PersistableObject.h15
-rw-r--r--qpid/cpp/src/qpid/broker/PriorityQueue.cpp7
-rw-r--r--qpid/cpp/src/qpid/broker/Protocol.h2
-rw-r--r--qpid/cpp/src/qpid/broker/Queue.cpp44
-rw-r--r--qpid/cpp/src/qpid/broker/Queue.h4
-rw-r--r--qpid/cpp/src/qpid/broker/QueueFactory.cpp3
-rw-r--r--qpid/cpp/src/qpid/broker/QueueRegistry.cpp10
-rw-r--r--qpid/cpp/src/qpid/broker/QueueSettings.cpp6
-rw-r--r--qpid/cpp/src/qpid/broker/QueueSettings.h1
-rw-r--r--qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h2
-rw-r--r--qpid/cpp/src/qpid/broker/RecoveredDequeue.h2
-rw-r--r--qpid/cpp/src/qpid/broker/RecoveredEnqueue.h2
-rw-r--r--qpid/cpp/src/qpid/broker/Selector.h2
-rw-r--r--qpid/cpp/src/qpid/broker/SelfDestructQueue.cpp45
-rw-r--r--qpid/cpp/src/qpid/broker/SelfDestructQueue.h (renamed from qpid/cpp/src/qpid/console/SequenceManager.cpp)49
-rw-r--r--qpid/cpp/src/qpid/broker/SemanticState.cpp18
-rw-r--r--qpid/cpp/src/qpid/broker/SessionAdapter.cpp4
-rw-r--r--qpid/cpp/src/qpid/broker/SessionHandler.cpp6
-rw-r--r--qpid/cpp/src/qpid/broker/SessionState.cpp20
-rw-r--r--qpid/cpp/src/qpid/broker/SessionState.h5
-rw-r--r--qpid/cpp/src/qpid/broker/System.cpp6
-rw-r--r--qpid/cpp/src/qpid/broker/System.h2
-rw-r--r--qpid/cpp/src/qpid/broker/TopicExchange.cpp5
-rw-r--r--qpid/cpp/src/qpid/broker/TopicExchange.h2
-rw-r--r--qpid/cpp/src/qpid/broker/TransactionObserver.h82
-rw-r--r--qpid/cpp/src/qpid/broker/TxAccept.cpp76
-rw-r--r--qpid/cpp/src/qpid/broker/TxAccept.h79
-rw-r--r--qpid/cpp/src/qpid/broker/TxBuffer.cpp7
-rw-r--r--qpid/cpp/src/qpid/broker/TxBuffer.h131
-rw-r--r--qpid/cpp/src/qpid/broker/TxOp.h20
-rw-r--r--qpid/cpp/src/qpid/broker/Vhost.cpp5
-rw-r--r--qpid/cpp/src/qpid/broker/Vhost.h2
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Connection.cpp3
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/DataReader.cpp4
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Incoming.cpp4
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Incoming.h1
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Message.cpp127
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Message.h20
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp46
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Outgoing.h11
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Relay.cpp13
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Relay.h5
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp8
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/SaslClient.h1
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Session.cpp138
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Topic.cpp17
-rw-r--r--qpid/cpp/src/qpid/broker/amqp/Translation.cpp124
-rw-r--r--qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp1
-rw-r--r--qpid/cpp/src/qpid/client/AsyncSession.h38
-rw-r--r--qpid/cpp/src/qpid/client/ClientImportExport.h35
-rw-r--r--qpid/cpp/src/qpid/client/Completion.h71
-rw-r--r--qpid/cpp/src/qpid/client/Connection.cpp2
-rw-r--r--qpid/cpp/src/qpid/client/Connection.h228
-rw-r--r--qpid/cpp/src/qpid/client/ConnectionHandler.cpp24
-rw-r--r--qpid/cpp/src/qpid/client/ConnectionSettings.h140
-rw-r--r--qpid/cpp/src/qpid/client/FailoverListener.h88
-rw-r--r--qpid/cpp/src/qpid/client/FailoverManager.h138
-rw-r--r--qpid/cpp/src/qpid/client/FlowControl.h75
-rw-r--r--qpid/cpp/src/qpid/client/Future.h59
-rw-r--r--qpid/cpp/src/qpid/client/FutureCompletion.h (renamed from qpid/cpp/src/qmf/engine/MessageImpl.cpp)44
-rw-r--r--qpid/cpp/src/qpid/client/FutureResult.h49
-rw-r--r--qpid/cpp/src/qpid/client/Handle.h71
-rw-r--r--qpid/cpp/src/qpid/client/LocalQueue.h120
-rw-r--r--qpid/cpp/src/qpid/client/Message.h175
-rw-r--r--qpid/cpp/src/qpid/client/MessageListener.h101
-rw-r--r--qpid/cpp/src/qpid/client/MessageReplayTracker.h73
-rw-r--r--qpid/cpp/src/qpid/client/QueueOptions.h129
-rw-r--r--qpid/cpp/src/qpid/client/Session.h39
-rw-r--r--qpid/cpp/src/qpid/client/SessionBase_0_10.h109
-rw-r--r--qpid/cpp/src/qpid/client/Subscription.h123
-rw-r--r--qpid/cpp/src/qpid/client/SubscriptionManager.h292
-rw-r--r--qpid/cpp/src/qpid/client/SubscriptionSettings.h135
-rw-r--r--qpid/cpp/src/qpid/client/TypedResult.h65
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp20
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp58
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h7
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp2
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp22
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp33
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h3
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp2
-rw-r--r--qpid/cpp/src/qpid/client/windows/SaslFactory.cpp7
-rw-r--r--qpid/cpp/src/qpid/console/Broker.cpp333
-rw-r--r--qpid/cpp/src/qpid/console/ClassKey.cpp106
-rw-r--r--qpid/cpp/src/qpid/console/Event.cpp205
-rw-r--r--qpid/cpp/src/qpid/console/Object.cpp384
-rw-r--r--qpid/cpp/src/qpid/console/ObjectId.cpp91
-rw-r--r--qpid/cpp/src/qpid/console/Schema.cpp165
-rw-r--r--qpid/cpp/src/qpid/console/SessionManager.cpp516
-rw-r--r--qpid/cpp/src/qpid/console/Value.cpp171
-rw-r--r--qpid/cpp/src/qpid/framing/Array.h99
-rw-r--r--qpid/cpp/src/qpid/framing/Buffer.cpp16
-rw-r--r--qpid/cpp/src/qpid/framing/Buffer.h115
-rw-r--r--qpid/cpp/src/qpid/framing/FieldTable.h139
-rw-r--r--qpid/cpp/src/qpid/framing/FieldValue.h484
-rw-r--r--qpid/cpp/src/qpid/framing/FrameSet.h14
-rw-r--r--qpid/cpp/src/qpid/framing/List.h78
-rw-r--r--qpid/cpp/src/qpid/framing/ProtocolVersion.h67
-rw-r--r--qpid/cpp/src/qpid/framing/SequenceNumber.h85
-rw-r--r--qpid/cpp/src/qpid/framing/SequenceSet.h69
-rw-r--r--qpid/cpp/src/qpid/framing/StructHelper.h57
-rw-r--r--qpid/cpp/src/qpid/framing/Uuid.h94
-rw-r--r--qpid/cpp/src/qpid/framing/amqp_types.h64
-rw-r--r--qpid/cpp/src/qpid/framing/amqp_types_full.h38
-rw-r--r--qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h1
-rw-r--r--qpid/cpp/src/qpid/ha/Backup.cpp4
-rw-r--r--qpid/cpp/src/qpid/ha/Backup.h2
-rw-r--r--qpid/cpp/src/qpid/ha/BrokerInfo.h3
-rw-r--r--qpid/cpp/src/qpid/ha/BrokerReplicator.cpp117
-rw-r--r--qpid/cpp/src/qpid/ha/BrokerReplicator.h11
-rw-r--r--qpid/cpp/src/qpid/ha/Event.cpp (renamed from qpid/cpp/src/qpid/ha/makeMessage.cpp)58
-rw-r--r--qpid/cpp/src/qpid/ha/Event.h193
-rw-r--r--qpid/cpp/src/qpid/ha/FailoverExchange.cpp4
-rw-r--r--qpid/cpp/src/qpid/ha/HaBroker.cpp11
-rw-r--r--qpid/cpp/src/qpid/ha/HaBroker.h7
-rw-r--r--qpid/cpp/src/qpid/ha/Membership.cpp15
-rw-r--r--qpid/cpp/src/qpid/ha/Membership.h10
-rw-r--r--qpid/cpp/src/qpid/ha/Primary.cpp101
-rw-r--r--qpid/cpp/src/qpid/ha/Primary.h41
-rw-r--r--qpid/cpp/src/qpid/ha/PrimaryTxObserver.cpp227
-rw-r--r--qpid/cpp/src/qpid/ha/PrimaryTxObserver.h115
-rw-r--r--qpid/cpp/src/qpid/ha/QueueGuard.h2
-rw-r--r--qpid/cpp/src/qpid/ha/QueueReplicator.cpp105
-rw-r--r--qpid/cpp/src/qpid/ha/QueueReplicator.h54
-rw-r--r--qpid/cpp/src/qpid/ha/QueueSnapshots.h10
-rw-r--r--qpid/cpp/src/qpid/ha/RemoteBackup.cpp5
-rw-r--r--qpid/cpp/src/qpid/ha/RemoteBackup.h10
-rw-r--r--qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp50
-rw-r--r--qpid/cpp/src/qpid/ha/ReplicatingSubscription.h11
-rw-r--r--qpid/cpp/src/qpid/ha/ReplicationTest.h7
-rw-r--r--qpid/cpp/src/qpid/ha/StatusCheck.cpp48
-rw-r--r--qpid/cpp/src/qpid/ha/StatusCheck.h10
-rw-r--r--qpid/cpp/src/qpid/ha/TxReplicator.cpp247
-rw-r--r--qpid/cpp/src/qpid/ha/TxReplicator.h131
-rw-r--r--qpid/cpp/src/qpid/ha/hash.h43
-rw-r--r--qpid/cpp/src/qpid/ha/makeMessage.h66
-rw-r--r--qpid/cpp/src/qpid/ha/types.cpp30
-rw-r--r--qpid/cpp/src/qpid/ha/types.h23
-rw-r--r--qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp4
-rw-r--r--qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h4
-rw-r--r--qpid/cpp/src/qpid/log/Logger.cpp1
-rw-r--r--qpid/cpp/src/qpid/log/Logger.h122
-rw-r--r--qpid/cpp/src/qpid/log/Options.h51
-rw-r--r--qpid/cpp/src/qpid/log/Selector.h99
-rw-r--r--qpid/cpp/src/qpid/log/SinkOptions.h64
-rw-r--r--qpid/cpp/src/qpid/log/Statement.h242
-rw-r--r--qpid/cpp/src/qpid/management/Args.h44
-rw-r--r--qpid/cpp/src/qpid/management/Buffer.h105
-rw-r--r--qpid/cpp/src/qpid/management/ConnectionSettings.h118
-rw-r--r--qpid/cpp/src/qpid/management/Manageable.h81
-rw-r--r--qpid/cpp/src/qpid/management/ManagementAgent.cpp19
-rw-r--r--qpid/cpp/src/qpid/management/ManagementAgent.h2
-rw-r--r--qpid/cpp/src/qpid/management/ManagementEvent.h53
-rw-r--r--qpid/cpp/src/qpid/management/ManagementObject.h246
-rw-r--r--qpid/cpp/src/qpid/management/Mutex.h67
-rw-r--r--qpid/cpp/src/qpid/messaging/Connection.cpp16
-rw-r--r--qpid/cpp/src/qpid/messaging/ConnectionImpl.h3
-rw-r--r--qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp4
-rw-r--r--qpid/cpp/src/qpid/messaging/ConnectionOptions.h7
-rw-r--r--qpid/cpp/src/qpid/messaging/Message.cpp12
-rw-r--r--qpid/cpp/src/qpid/messaging/MessageImpl.cpp69
-rw-r--r--qpid/cpp/src/qpid/messaging/MessageImpl.h45
-rw-r--r--qpid/cpp/src/qpid/messaging/ProtocolRegistry.h5
-rw-r--r--qpid/cpp/src/qpid/messaging/Receiver.cpp7
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp154
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h9
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp470
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h36
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.cpp13
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.h3
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.cpp97
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.h53
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp26
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h3
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp2
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp2
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp118
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/SenderContext.h14
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp2
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp29
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/SessionContext.h8
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp18
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp7
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/SslTransport.h3
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp4
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/TcpTransport.h1
-rw-r--r--qpid/cpp/src/qpid/messaging/amqp/Transport.h7
-rw-r--r--qpid/cpp/src/qpid/store/CMakeLists.txt2
-rw-r--r--qpid/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp3
-rw-r--r--qpid/cpp/src/qpid/sys/Condition.h33
-rw-r--r--qpid/cpp/src/qpid/sys/ExceptionHolder.h71
-rw-r--r--qpid/cpp/src/qpid/sys/IOHandle.h36
-rw-r--r--qpid/cpp/src/qpid/sys/Monitor.h49
-rw-r--r--qpid/cpp/src/qpid/sys/Mutex.h91
-rw-r--r--qpid/cpp/src/qpid/sys/Runnable.h (renamed from qpid/cpp/src/qpid/console/Package.cpp)48
-rw-r--r--qpid/cpp/src/qpid/sys/StrError.h (renamed from qpid/cpp/src/qmf/engine/MessageImpl.h)34
-rw-r--r--qpid/cpp/src/qpid/sys/SystemInfo.h109
-rw-r--r--qpid/cpp/src/qpid/sys/Thread.h71
-rw-r--r--qpid/cpp/src/qpid/sys/Time.h176
-rw-r--r--qpid/cpp/src/qpid/sys/posix/Condition.h86
-rw-r--r--qpid/cpp/src/qpid/sys/posix/Mutex.h158
-rw-r--r--qpid/cpp/src/qpid/sys/posix/PrivatePosix.h65
-rwxr-xr-xqpid/cpp/src/qpid/sys/posix/Time.h34
-rw-r--r--qpid/cpp/src/qpid/sys/posix/check.h53
-rwxr-xr-xqpid/cpp/src/qpid/sys/windows/Condition.h77
-rwxr-xr-xqpid/cpp/src/qpid/sys/windows/Mutex.h188
-rw-r--r--qpid/cpp/src/qpid/sys/windows/Time.h36
-rwxr-xr-xqpid/cpp/src/qpid/sys/windows/check.h49
-rw-r--r--qpid/cpp/src/qpid/types/Uuid.cpp5
-rw-r--r--qpid/cpp/src/qpid/types/Variant.cpp1
-rw-r--r--qpid/cpp/src/qpid/types/encodings.h33
-rw-r--r--qpid/cpp/src/qpid/xml/XmlExchange.cpp2
-rw-r--r--qpid/cpp/src/rdma.cmake4
-rw-r--r--qpid/cpp/src/ssl.mk47
-rw-r--r--qpid/cpp/src/tests/BrokerFixture.h70
-rw-r--r--qpid/cpp/src/tests/BrokerMgmtAgent.cpp1
-rw-r--r--qpid/cpp/src/tests/CMakeLists.txt71
-rw-r--r--qpid/cpp/src/tests/ClientSessionTest.cpp1
-rw-r--r--qpid/cpp/src/tests/Makefile.am410
-rw-r--r--qpid/cpp/src/tests/ManagementTest.cpp27
-rw-r--r--qpid/cpp/src/tests/MessageReplayTracker.cpp2
-rw-r--r--qpid/cpp/src/tests/MessagingFixture.h17
-rw-r--r--qpid/cpp/src/tests/MessagingSessionTests.cpp89
-rw-r--r--qpid/cpp/src/tests/QueuePolicyTest.cpp2
-rw-r--r--qpid/cpp/src/tests/Shlib.cpp10
-rw-r--r--qpid/cpp/src/tests/TransactionObserverTest.cpp144
-rw-r--r--qpid/cpp/src/tests/TxMocks.h3
-rw-r--r--qpid/cpp/src/tests/brokermgmt.mk44
-rw-r--r--qpid/cpp/src/tests/brokertest.py64
-rwxr-xr-xqpid/cpp/src/tests/cli_tests.py32
-rw-r--r--qpid/cpp/src/tests/failing-amqp0-10-python-tests7
-rw-r--r--qpid/cpp/src/tests/failing-amqp1.0-python-tests2
-rwxr-xr-xqpid/cpp/src/tests/ha_test.py72
-rwxr-xr-xqpid/cpp/src/tests/ha_tests.py240
-rwxr-xr-xqpid/cpp/src/tests/interlink_tests.py80
-rwxr-xr-xqpid/cpp/src/tests/qpid-cluster-lag.py93
-rw-r--r--qpid/cpp/src/tests/qpid-receive.cpp18
-rw-r--r--qpid/cpp/src/tests/qpid-send.cpp8
-rwxr-xr-xqpid/cpp/src/tests/qpidd_qmfv2_tests.py103
-rwxr-xr-xqpid/cpp/src/tests/qpidt2
-rw-r--r--qpid/cpp/src/tests/queue_flow_limit_tests.py10
-rwxr-xr-xqpid/cpp/src/tests/rsynchosts12
-rwxr-xr-xqpid/cpp/src/tests/run-unit-tests48
-rwxr-xr-xqpid/cpp/src/tests/run_cli_tests4
-rwxr-xr-xqpid/cpp/src/tests/run_federation_tests2
-rw-r--r--qpid/cpp/src/tests/run_msg_group_tests.ps171
-rw-r--r--qpid/cpp/src/tests/sasl.mk44
-rw-r--r--qpid/cpp/src/tests/ssl.mk22
-rwxr-xr-xqpid/cpp/src/tests/swig_python_tests62
-rw-r--r--qpid/cpp/src/tests/test_env.ps1.in1
-rw-r--r--qpid/cpp/src/tests/test_env.sh.in9
-rw-r--r--qpid/cpp/src/tests/test_store.cpp121
-rw-r--r--qpid/cpp/src/tests/test_tools.h1
-rw-r--r--qpid/cpp/src/tests/testagent.cpp208
-rw-r--r--qpid/cpp/src/tests/testagent.mk51
-rw-r--r--qpid/cpp/src/tests/testagent.xml64
-rw-r--r--qpid/cpp/src/xml.mk29
368 files changed, 13748 insertions, 15076 deletions
diff --git a/qpid/cpp/src/CMakeLists.txt b/qpid/cpp/src/CMakeLists.txt
index dcbb17d1e0..e7cf72e745 100644
--- a/qpid/cpp/src/CMakeLists.txt
+++ b/qpid/cpp/src/CMakeLists.txt
@@ -26,6 +26,16 @@ foreach (r ${REQUIRE})
message(STATUS "Forcing ${r} to ${${r}_force}")
endforeach(r)
+# Capture specified C++ compiler (if any)
+if (NOT ENV_CXX)
+ if (NOT "$ENV{CXX}" STREQUAL "")
+ set(CXX $ENV{CXX})
+ else(NOT "$ENV{CXX}" STREQUAL "")
+ set(CXX ${CMAKE_CXX_COMPILER})
+ endif(NOT "$ENV{CXX}" STREQUAL "")
+ set(ENV_CXX ${CXX} CACHE INTERNAL "C++ compiler specified in cmake environment")
+endif (NOT ENV_CXX)
+
include(CheckFunctionExists)
include(CheckIncludeFileCXX)
include(CheckIncludeFiles)
@@ -145,6 +155,13 @@ MACRO (add_msvc_version verProject verProjectType verProjectFileExt)
endif (MSVC)
ENDMACRO (add_msvc_version)
+# Add a test to check the exported library API against expected API symbols
+MACRO (add_api_test libname)
+ if (NOT CMAKE_SYSTEM_NAME STREQUAL Windows)
+ add_test(api_check_${libname} ${CMAKE_CURRENT_SOURCE_DIR}/check-abi "${ENV_CXX}" ${CMAKE_CURRENT_BINARY_DIR}/lib${libname}.so ${CMAKE_CURRENT_SOURCE_DIR}/lib${libname}-api-symbols.txt)
+ endif (NOT CMAKE_SYSTEM_NAME STREQUAL Windows)
+ENDMACRO (add_api_test libname)
+
#
# Install optional windows version settings. Override variables are specified in a file.
@@ -263,6 +280,9 @@ if (ENABLE_VALGRIND AND NOT VALGRIND)
message(STATUS "Can't locate the valgrind command; no run-time error detection")
endif (ENABLE_VALGRIND AND NOT VALGRIND)
+# Do not keep on linking against transitive library dependencies
+set (CMAKE_LINK_INTERFACE_LIBRARIES "")
+
if (CMAKE_COMPILER_IS_GNUCXX)
# Warnings: Enable as many as possible, keep the code clean. Please
# do not disable warnings or remove -Werror without discussing on
@@ -279,18 +299,24 @@ if (CMAKE_COMPILER_IS_GNUCXX)
if (CMAKE_SYSTEM_NAME STREQUAL SunOS)
set (CATCH_UNDEFINED "")
endif (CMAKE_SYSTEM_NAME STREQUAL SunOS)
- set (COMPILER_FLAGS "-fvisibility-inlines-hidden")
+ set (COMPILER_FLAGS "-fvisibility-inlines-hidden -Wl,--as-needed")
# gcc 4.1.2 on RHEL 5 needs -Wno-attributes to avoid an error that's fixed
# in later gcc versions.
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
if (GCC_VERSION VERSION_EQUAL 4.1.2)
+ set (COMPILER_FLAGS "-Wl,--as-needed")
message (STATUS "Cannot use -fvisibility=hidden on gcc 4.1.2")
else (GCC_VERSION VERSION_EQUAL 4.1.2)
- set (HIDE_SYMBOL_FLAGS "-fvisibility=hidden")
+ set (HIDE_SYMBOL_FLAGS "-fno-visibility-inlines-hidden -fvisibility=hidden")
endif (GCC_VERSION VERSION_EQUAL 4.1.2)
endif (CMAKE_COMPILER_IS_GNUCXX)
+if (CMAKE_SYSTEM_NAME STREQUAL Linux)
+ set (QPID_LINKMAP ${CMAKE_CURRENT_SOURCE_DIR}/qpid.linkmap)
+ set (LINK_VERSION_SCRIPT_FLAG "-Wl,--version-script=${QPID_LINKMAP}")
+endif (CMAKE_SYSTEM_NAME STREQUAL Linux)
+
if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro)
set (COMPILER_FLAGS "-library=stlport4 -mt")
set (WARNING_FLAGS "+w")
@@ -301,9 +327,9 @@ endif (CMAKE_CXX_COMPILER_ID STREQUAL SunPro)
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
# Allow MSVC user to select 'WinXP-SP3/Windows Server 2003' as build target version
set (win32_winnt_default OFF)
- if (MSVC)
- set (win32_winnt_default ON)
- endif (MSVC)
+ if (MSVC)
+ set (win32_winnt_default ON)
+ endif (MSVC)
option(SET_WIN32_WINNT "In Windows-MSVC build: define _WIN32_WINNT=0x0502 to select target version: Windows XP with SP3" ${win32_winnt_default})
endif (CMAKE_SYSTEM_NAME STREQUAL Windows)
@@ -356,7 +382,7 @@ endif (CMAKE_SYSTEM_NAME STREQUAL Windows)
# where Boost 1.45 is supported, or we can just accept some versions using
# the Additional_versions variable.
if (NOT DEFINED Boost_ADDITIONAL_VERSIONS)
- set (Boost_ADDITIONAL_VERSIONS
+ set (Boost_ADDITIONAL_VERSIONS
"1.45" "1.45.0" "1.46" "1.46.0" "1.47" "1.47.0"
"1.48" "1.48.0" "1.49" "1.49.0" "1.50" "1.50.0"
"1.51" "1.51.0" "1.52" "1.52.0" "1.53" "1.53.0")
@@ -513,44 +539,49 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../include )
link_directories( ${Boost_LIBRARY_DIRS} )
-CHECK_LIBRARY_EXISTS (rt clock_gettime "" CLOCK_GETTIME_IN_RT)
-if (NOT CLOCK_GETTIME_IN_RT)
- CHECK_FUNCTION_EXISTS (clock_gettime QPID_HAS_CLOCK_GETTIME)
-else (NOT CLOCK_GETTIME_IN_RT)
- set(CMAKE_REQUIRED_LIBS ${CMAKE_REQUIRED_LIBS} rt)
- set(QPID_HAS_CLOCK_GETTIME YES CACHE BOOL "Platform has clock_gettime")
-endif (NOT CLOCK_GETTIME_IN_RT)
-
-# Check for header file for dtrace static probes
-check_include_files(sys/sdt.h HAVE_SYS_SDT_H)
-if (HAVE_SYS_SDT_H)
- set(probes_default ON)
-endif (HAVE_SYS_SDT_H)
-option(BUILD_PROBES "Build with DTrace/systemtap static probes" ${probes_default})
-if (NOT BUILD_PROBES)
- set (HAVE_SYS_SDT_H 0)
-endif (NOT BUILD_PROBES)
-
-# Check for poll/epoll header files
-check_include_files(sys/poll.h HAVE_POLL)
-check_include_files(sys/epoll.h HAVE_EPOLL)
-
-# Set default poller implementation (check from general to specific to allow overriding)
-if (HAVE_POLL)
- set(poller_default poll)
-endif (HAVE_POLL)
-if (HAVE_EPOLL)
- set(poller_default epoll)
-endif (HAVE_EPOLL)
-set(POLLER ${poller_default} CACHE STRING "Poller implementation (poll/epoll)")
-
-# If not windows ensure that we have uuid library
+# These dependencies aren't found on windows
if (NOT CMAKE_SYSTEM_NAME STREQUAL Windows)
+ # Ensure we have clock_gettime
+ CHECK_FUNCTION_EXISTS (clock_gettime CLOCK_GETTIME_IN_LIBC)
+ if (NOT CLOCK_GETTIME_IN_LIBC)
+ CHECK_LIBRARY_EXISTS (rt clock_gettime "" CLOCK_GETTIME_IN_RT)
+ if (CLOCK_GETTIME_IN_RT)
+ set(clock_gettime_LIB "rt")
+ else ()
+ message(FATAL_ERROR "Cannot find clock_gettime()")
+ endif (CLOCK_GETTIME_IN_RT)
+ endif (NOT CLOCK_GETTIME_IN_LIBC)
+
+ # Ensure we have uuid library
CHECK_LIBRARY_EXISTS (uuid uuid_compare "" HAVE_UUID)
CHECK_INCLUDE_FILES(uuid/uuid.h HAVE_UUID_H)
if (NOT HAVE_UUID AND NOT HAVE_UUID_H)
message(FATAL_ERROR "Uuid library and/or header file not found")
endif (NOT HAVE_UUID AND NOT HAVE_UUID_H)
+ set (uuid_LIB "uuid")
+
+ # Check for header file for dtrace static probes
+ check_include_files(sys/sdt.h HAVE_SYS_SDT_H)
+ if (HAVE_SYS_SDT_H)
+ set(probes_default ON)
+ endif (HAVE_SYS_SDT_H)
+ option(BUILD_PROBES "Build with DTrace/systemtap static probes" ${probes_default})
+ if (NOT BUILD_PROBES)
+ set (HAVE_SYS_SDT_H 0)
+ endif (NOT BUILD_PROBES)
+
+ # Check for poll/epoll header files
+ check_include_files(sys/poll.h HAVE_POLL)
+ check_include_files(sys/epoll.h HAVE_EPOLL)
+
+ # Set default poller implementation (check from general to specific to allow overriding)
+ if (HAVE_POLL)
+ set(poller_default poll)
+ endif (HAVE_POLL)
+ if (HAVE_EPOLL)
+ set(poller_default epoll)
+ endif (HAVE_EPOLL)
+ set(POLLER ${poller_default} CACHE STRING "Poller implementation (poll/epoll)")
endif (NOT CMAKE_SYSTEM_NAME STREQUAL Windows)
# See if Cyrus SASL is desired and available
@@ -578,7 +609,10 @@ if (BUILD_SASL)
qpid/sys/cyrus/CyrusSecurityLayer.h
qpid/sys/cyrus/CyrusSecurityLayer.cpp
)
- set(qpidcommon_sasl_lib sasl2)
+ set(sasl_LIB sasl2)
+else (BUILD_SASL)
+ set(HAVE_SASL OFF)
+ set(BROKER_SASL_NAME "qpidd" CACHE STRING "SASL app name for the qpid broker")
endif (BUILD_SASL)
# Optional SSL/TLS support. Requires Netscape Portable Runtime on Linux.
@@ -604,27 +638,23 @@ if (BUILD_SSL)
set (sslcommon_SOURCES
qpid/sys/windows/SslAsynchIO.cpp
)
+
set (ssl_SOURCES
qpid/broker/windows/SslProtocolFactory.cpp
)
+
set (sslconnector_SOURCES
qpid/client/windows/SslConnector.cpp
)
- set (windows_ssl_libs Secur32.lib)
- set (windows_ssl_server_libs Crypt32.lib)
+ set (ssl_INCLUDES "")
+ set (ssl_LIBDIRS "")
+ set (ssl_LIBS Secur32.lib)
+ set (ssl_server_LIBS Crypt32.lib Secur32.lib)
else (CMAKE_SYSTEM_NAME STREQUAL Windows)
if (NOT NSS_FOUND)
message(FATAL_ERROR "nss/nspr not found, required for ssl support")
endif (NOT NSS_FOUND)
- foreach(f ${NSS_CFLAGS})
- set (NSS_COMPILE_FLAGS "${NSS_COMPILE_FLAGS} ${f}")
- endforeach(f)
-
- foreach(f ${NSS_LDFLAGS})
- set (NSS_LINK_FLAGS "${NSS_LINK_FLAGS} ${f}")
- endforeach(f)
-
set (sslcommon_SOURCES
qpid/sys/ssl/check.h
qpid/sys/ssl/check.cpp
@@ -643,14 +673,17 @@ if (BUILD_SSL)
qpid/messaging/amqp/SslTransport.cpp
)
- set_source_files_properties (
- ${sslcommon_SOURCES}
- ${ssl_SOURCES}
- ${sslconnector_SOURCES}
- PROPERTIES
- COMPILE_FLAGS "${NSS_COMPILE_FLAGS}"
- )
+ set (ssl_INCLUDES "${NSS_INCLUDE_DIRS}")
+ set (ssl_LIBDIRS "${NSS_LIBRARY_DIRS}")
+ set (ssl_LIBS "${NSS_LIBRARIES}")
+ set (ssl_server_LIBS "${NSS_LIBRARIES}")
endif (CMAKE_SYSTEM_NAME STREQUAL Windows)
+
+ # Add include directories and link directories for NSS
+ # unfortunately this doesn't get done automatically for
+ # libraries detected by FindPkgConfig
+ include_directories(${ssl_INCLUDES})
+ link_directories(${ssl_LIBDIRS})
endif (BUILD_SSL)
# See if XML Exchange is desired and prerequisites are available
@@ -690,7 +723,7 @@ if (BUILD_XML)
qpid/xml/XmlExchange.cpp
qpid/xml/XmlExchange.h
qpid/xml/XmlExchangePlugin.cpp)
- target_link_libraries (xml xerces-c xqilla qpidbroker pthread)
+ target_link_libraries (xml xerces-c xqilla qpidbroker qpidcommon)
set_target_properties (xml PROPERTIES
PREFIX ""
COMPILE_DEFINITIONS _IN_QPID_BROKER
@@ -744,16 +777,15 @@ if (BUILD_HA)
qpid/ha/BrokerReplicator.h
qpid/ha/ConnectionObserver.cpp
qpid/ha/ConnectionObserver.h
+ qpid/ha/Event.cpp
+ qpid/ha/Event.h
qpid/ha/FailoverExchange.cpp
qpid/ha/FailoverExchange.h
qpid/ha/HaBroker.cpp
qpid/ha/HaBroker.h
qpid/ha/HaPlugin.cpp
- qpid/ha/hash.h
qpid/ha/IdSetter.h
qpid/ha/QueueSnapshot.h
- qpid/ha/makeMessage.cpp
- qpid/ha/makeMessage.h
qpid/ha/Membership.cpp
qpid/ha/Membership.h
qpid/ha/Primary.cpp
@@ -773,18 +805,22 @@ if (BUILD_HA)
qpid/ha/StandAlone.h
qpid/ha/StatusCheck.cpp
qpid/ha/StatusCheck.h
+ qpid/ha/PrimaryTxObserver.cpp
+ qpid/ha/PrimaryTxObserver.h
qpid/ha/types.cpp
+ qpid/ha/TxReplicator.cpp
+ qpid/ha/TxReplicator.h
qpid/ha/types.h
)
add_library (ha MODULE ${ha_SOURCES})
- set_target_properties (ha PROPERTIES PREFIX "" COMPILE_DEFINITIONS _IN_QPID_BROKER)
- target_link_libraries (ha qpidtypes qpidcommon qpidbroker qpidmessaging)
- if (CMAKE_COMPILER_IS_GNUCXX)
- set_target_properties (ha PROPERTIES
- PREFIX ""
- LINK_FLAGS -Wl,--no-undefined)
- endif (CMAKE_COMPILER_IS_GNUCXX)
+ target_link_libraries (ha
+ qpidtypes qpidcommon qpidbroker qpidmessaging
+ "${Boost_PROGRAM_OPTIONS_LIBRARY}")
+ set_target_properties (ha PROPERTIES
+ PREFIX ""
+ COMPILE_DEFINITIONS _IN_QPID_BROKER
+ LINK_FLAGS "${CATCH_UNDEFINED}")
install (TARGETS ha
DESTINATION ${QPIDD_MODULE_DIR}
COMPONENT ${QPID_COMPONENT_BROKER})
@@ -799,7 +835,7 @@ include (amqp.cmake)
# Check for syslog capabilities not present on all systems
check_symbol_exists (LOG_AUTHPRIV "sys/syslog.h" HAVE_LOG_AUTHPRIV)
check_symbol_exists (LOG_FTP "sys/syslog.h" HAVE_LOG_FTP)
-
+
# Set default Memory Status module (Null implementation)
set (qpid_memstat_module
qpid/sys/MemStat.cpp
@@ -834,20 +870,20 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
)
set (qpidcommon_platform_LIBS
- ${Boost_THREAD_LIBRARY} ${windows_ssl_libs} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_SYSTEM_LIBRARY} ws2_32 )
+ ${Boost_THREAD_LIBRARY}
+ ${Boost_DATE_TIME_LIBRARY}
+ ${Boost_SYSTEM_LIBRARY}
+ ws2_32
+ )
+
set (qpidbroker_platform_SOURCES
qpid/broker/windows/BrokerDefaults.cpp
qpid/broker/windows/SaslAuthenticator.cpp
)
- set (qpidbroker_platform_LIBS
- ${windows_ssl_libs} ${windows_ssl_server_libs}
- )
+
set (qpidclient_platform_SOURCES
qpid/client/windows/ClientDllMain.cpp
)
- set (qpidclient_platform_LIBS
- ${windows_ssl_libs}
- )
set (qpidd_platform_SOURCES
windows/QpiddBroker.cpp
@@ -885,7 +921,7 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
# On Linux override memory status module
set (qpid_memstat_module
qpid/sys/posix/MemStat.cpp
- )
+ )
endif (CMAKE_SYSTEM_NAME STREQUAL Linux)
if (CMAKE_SYSTEM_NAME STREQUAL SunOS)
@@ -908,8 +944,7 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
set (qpidtypes_platform_SOURCES)
set (qpidtypes_platform_LIBS
- uuid
- ${Boost_SYSTEM_LIBRARY}
+ "${uuid_LIB}"
)
set (qpidcommon_platform_SOURCES
@@ -934,9 +969,11 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
${qpid_system_module}
${qpid_poller_module}
)
+
set (qpidcommon_platform_LIBS
- ${Boost_PROGRAM_OPTIONS_LIBRARY}
- ${CMAKE_DL_LIBS}
+ "${CMAKE_DL_LIBS}"
+ "${clock_gettime_LIB}"
+ "${uuid_LIB}"
)
set (qpidbroker_platform_SOURCES
@@ -977,6 +1014,7 @@ set (qpidcommon_SOURCES
qpid/StringUtils.cpp
qpid/Url.cpp
qpid/UrlArray.cpp
+ qpid/NullSaslClient.cpp
qpid/NullSaslServer.cpp
qpid/amqp_0_10/SessionHandler.cpp
qpid/framing/AccumulatedAck.cpp
@@ -1024,12 +1062,16 @@ set (qpidcommon_SOURCES
qpid/amqp_0_10/Codecs.cpp
qpid/amqp/CharSequence.h
qpid/amqp/CharSequence.cpp
+ qpid/amqp/DataBuilder.h
+ qpid/amqp/DataBuilder.cpp
qpid/amqp/Decoder.h
qpid/amqp/Decoder.cpp
qpid/amqp/Descriptor.h
qpid/amqp/Descriptor.cpp
qpid/amqp/Encoder.h
qpid/amqp/Encoder.cpp
+ qpid/amqp/ListBuilder.h
+ qpid/amqp/ListBuilder.cpp
qpid/amqp/MapHandler.h
qpid/amqp/MapEncoder.h
qpid/amqp/MapEncoder.cpp
@@ -1060,20 +1102,17 @@ set (qpidcommon_SOURCES
add_msvc_version (qpidcommon library dll)
add_library (qpidcommon SHARED ${qpidcommon_SOURCES})
-if (CLOCK_GETTIME_IN_RT)
- set (qpidcommon_platform_LIBS ${qpidcommon_platform_LIBS} rt)
-endif (CLOCK_GETTIME_IN_RT)
-# Not all platforms have NSS_LINK_FLAGS
-if (NSS_LINK_FLAGS)
- set (qpidcommon_LINK_FLAGS LINK_FLAGS ${NSS_LINK_FLAGS})
-endif (NSS_LINK_FLAGS)
+
target_link_libraries (qpidcommon qpidtypes
${qpidcommon_platform_LIBS}
- ${qpidcommon_sasl_lib})
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ "${sasl_LIB}"
+ ${ssl_LIBS})
+
set_target_properties (qpidcommon PROPERTIES
- VERSION ${qpidcommon_version}
- SOVERSION ${qpidcommon_version_major}
- ${qpidcommon_LINK_FLAGS})
+ VERSION ${qpidcommon_version}
+ SOVERSION ${qpidcommon_version_major})
+
install (TARGETS qpidcommon
DESTINATION ${QPID_INSTALL_LIBDIR}
COMPONENT ${QPID_COMPONENT_COMMON})
@@ -1085,17 +1124,26 @@ set(qpidtypes_SOURCES
qpid/types/Variant.cpp
${qpidtypes_platform_SOURCES}
)
+set_source_files_properties(
+ ${qpidtypes_SOURCES}
+ PROPERTIES
+ COMPILE_FLAGS "${HIDE_SYMBOL_FLAGS}")
+
add_msvc_version (qpidtypes library dll)
add_library(qpidtypes SHARED ${qpidtypes_SOURCES})
target_link_libraries(qpidtypes ${qpidtypes_platform_LIBS})
-set_target_properties (qpidtypes PROPERTIES
+set_target_properties (qpidtypes PROPERTIES
+ LINK_FLAGS "${HIDE_SYMBOL_FLAGS} ${LINK_VERSION_SCRIPT_FLAG}"
VERSION ${qpidtypes_version}
SOVERSION ${qpidtypes_version_major})
+
install(TARGETS qpidtypes
DESTINATION ${QPID_INSTALL_LIBDIR}
COMPONENT ${QPID_COMPONENT_COMMON})
install_pdb (qpidtypes ${QPID_COMPONENT_COMMON})
+add_api_test(qpidtypes)
+
set (qpidclient_SOURCES
${rgen_client_srcs}
${qpidclient_platform_SOURCES}
@@ -1137,9 +1185,15 @@ set (qpidclient_SOURCES
add_msvc_version (qpidclient library dll)
add_library (qpidclient SHARED ${qpidclient_SOURCES})
-target_link_libraries (qpidclient qpidcommon ${qpidclient_platform_LIBS})
-set_target_properties (qpidclient PROPERTIES VERSION ${qpidclient_version}
-SOVERSION ${qpidclient_version_major})
+
+target_link_libraries (qpidclient qpidcommon
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${ssl_LIBS})
+
+set_target_properties (qpidclient PROPERTIES
+ VERSION ${qpidclient_version}
+ SOVERSION ${qpidclient_version_major})
+
install (TARGETS qpidclient
DESTINATION ${QPID_INSTALL_LIBDIR}
COMPONENT ${QPID_COMPONENT_CLIENT})
@@ -1202,27 +1256,25 @@ set (qpidmessaging_SOURCES
qpid/messaging/amqp/EncodedMessage.h
qpid/messaging/amqp/EncodedMessage.cpp
)
+set_source_files_properties(
+ ${qpidmessaging_SOURCES}
+ PROPERTIES
+ COMPILE_FLAGS "${HIDE_SYMBOL_FLAGS}")
+
add_msvc_version (qpidmessaging library dll)
add_library (qpidmessaging SHARED ${qpidmessaging_SOURCES})
-target_link_libraries (qpidmessaging qpidclient)
-set_target_properties (qpidmessaging PROPERTIES
- VERSION ${qpidmessaging_version}
+target_link_libraries (qpidmessaging qpidtypes qpidclient qpidcommon)
+set_target_properties (qpidmessaging PROPERTIES
+ LINK_FLAGS "${HIDE_SYMBOL_FLAGS} ${LINK_VERSION_SCRIPT_FLAG}"
+ VERSION ${qpidmessaging_version}
SOVERSION ${qpidmessaging_version_major})
install (TARGETS qpidmessaging
DESTINATION ${QPID_INSTALL_LIBDIR}
COMPONENT ${QPID_COMPONENT_CLIENT})
install_pdb (qpidmessaging ${QPID_COMPONENT_CLIENT})
-# Released source artifacts from Apache have the generated headers included in
-# the source tree, not the binary tree. So don't attempt to grab them when
-# they're not supposed to be there.
-if (NOT QPID_GENERATED_HEADERS_IN_SOURCE)
- install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../include/qpid
- DESTINATION ${QPID_INSTALL_INCLUDEDIR}
- COMPONENT ${QPID_COMPONENT_CLIENT_INCLUDE})
-endif (NOT QPID_GENERATED_HEADERS_IN_SOURCE)
-
+add_api_test(qpidmessaging)
if (MSVC)
# Install the DtcPlugin project and call it qpidxarm.
@@ -1312,6 +1364,7 @@ set (qpidbroker_SOURCES
qpid/broker/SelectorToken.cpp
qpid/broker/SelectorValue.h
qpid/broker/SelectorValue.cpp
+ qpid/broker/SelfDestructQueue.cpp
qpid/broker/SemanticState.h
qpid/broker/SemanticState.cpp
qpid/broker/SessionAdapter.cpp
@@ -1337,11 +1390,17 @@ set (qpidbroker_SOURCES
)
add_msvc_version (qpidbroker library dll)
add_library (qpidbroker SHARED ${qpidbroker_SOURCES})
-target_link_libraries (qpidbroker qpidcommon ${qpidbroker_platform_LIBS})
-set_target_properties (qpidbroker PROPERTIES
+
+target_link_libraries (qpidbroker qpidcommon qpidtypes
+ "${Boost_PROGRAM_OPTIONS_LIBRARY}"
+ "${sasl_LIB}"
+ ${ssl_server_LIBS})
+
+set_target_properties (qpidbroker PROPERTIES
VERSION ${qpidbroker_version}
- SOVERSION ${qpidbroker_version_major}
+ SOVERSION ${qpidbroker_version_major}
COMPILE_DEFINITIONS _IN_QPID_BROKER)
+
if (MSVC)
set_target_properties (qpidbroker PROPERTIES COMPILE_FLAGS /wd4290)
endif (MSVC)
@@ -1373,30 +1432,6 @@ if (UNIX)
install (CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}/${QPID_LOCALSTATE_DIR}/spool/qpidd)")
endif (UNIX)
-set (qmf_SOURCES
- qpid/agent/ManagementAgentImpl.cpp
- qpid/agent/ManagementAgentImpl.h
- )
-set (qmf_HEADERS
- ../include/qpid/agent/ManagementAgent.h
- ../include/qpid/agent/QmfAgentImportExport.h
- ../include/qmf/BrokerImportExport.h
- )
-
-add_msvc_version (qmf library dll)
-add_library (qmf SHARED ${qmf_SOURCES})
-target_link_libraries (qmf qmfengine)
-set_target_properties (qmf PROPERTIES
- VERSION ${qmf_version}
- SOVERSION ${qmf_version_major})
-install (TARGETS qmf OPTIONAL
- DESTINATION ${QPID_INSTALL_LIBDIR}
- COMPONENT ${QPID_COMPONENT_QMF})
-install (FILES ${qmf_HEADERS}
- DESTINATION ${QPID_INSTALL_INCLUDEDIR}/qpid/agent
- COMPONENT ${QPID_COMPONENT_QMF})
-install_pdb (qmf ${QPID_COMPONENT_QMF})
-
if (NOT WIN32)
set (qmf2_platform_headers
../include/qmf/posix/EventNotifier.h
@@ -1477,7 +1512,7 @@ endif (NOT WIN32)
add_library (qmf2 SHARED ${qmf2_SOURCES})
target_link_libraries (qmf2 qpidmessaging qpidtypes qpidclient qpidcommon)
set_target_properties (qmf2 PROPERTIES
- VERSION ${qmf2_version}
+ VERSION ${qmf2_version}
SOVERSION ${qmf2_version_major})
install (TARGETS qmf2 OPTIONAL
DESTINATION ${QPID_INSTALL_LIBDIR}
@@ -1487,111 +1522,6 @@ endif (NOT WIN32)
COMPONENT ${QPID_COMPONENT_QMF})
install_pdb (qmf2 ${QPID_COMPONENT_QMF})
-set (qmfengine_SOURCES
- qmf/engine/Agent.cpp
- qmf/engine/BrokerProxyImpl.cpp
- qmf/engine/BrokerProxyImpl.h
- qmf/engine/ConnectionSettingsImpl.cpp
- qmf/engine/ConnectionSettingsImpl.h
- qmf/engine/ConsoleImpl.cpp
- qmf/engine/ConsoleImpl.h
- qmf/engine/EventImpl.cpp
- qmf/engine/EventImpl.h
- qmf/engine/MessageImpl.cpp
- qmf/engine/MessageImpl.h
- qmf/engine/ObjectIdImpl.cpp
- qmf/engine/ObjectIdImpl.h
- qmf/engine/ObjectImpl.cpp
- qmf/engine/ObjectImpl.h
- qmf/engine/Protocol.cpp
- qmf/engine/Protocol.h
- qmf/engine/QueryImpl.cpp
- qmf/engine/QueryImpl.h
- qmf/engine/SequenceManager.cpp
- qmf/engine/SequenceManager.h
- qmf/engine/SchemaImpl.cpp
- qmf/engine/SchemaImpl.h
- qmf/engine/ValueImpl.cpp
- qmf/engine/ValueImpl.h
- )
-
-set (qmfengine_HEADERS
- ../include/qmf/engine/Agent.h
- ../include/qmf/engine/ConnectionSettings.h
- ../include/qmf/engine/Console.h
- ../include/qmf/engine/Event.h
- ../include/qmf/engine/Message.h
- ../include/qmf/engine/Object.h
- ../include/qmf/engine/ObjectId.h
- ../include/qmf/engine/QmfEngineImportExport.h
- ../include/qmf/engine/Query.h
- ../include/qmf/engine/ResilientConnection.h
- ../include/qmf/engine/Schema.h
- ../include/qmf/engine/Typecode.h
- ../include/qmf/engine/Value.h
- )
-install (FILES ${qmfengine_HEADERS}
- DESTINATION ${QPID_INSTALL_INCLUDEDIR}/qmf/engine
- COMPONENT ${QPID_COMPONENT_QMF})
-
-if (NOT WIN32)
- list(APPEND qmfengine_SOURCES qmf/engine/ResilientConnection.cpp)
-endif (NOT WIN32)
-add_msvc_version (qmfengine library dll)
-
-add_library (qmfengine SHARED ${qmfengine_SOURCES})
-target_link_libraries (qmfengine qpidclient)
-set_target_properties (qmfengine PROPERTIES
- VERSION ${qmfengine_version}
- SOVERSION ${qmfengine_version_major})
-install (TARGETS qmfengine OPTIONAL
- DESTINATION ${QPID_INSTALL_LIBDIR}
- COMPONENT ${QPID_COMPONENT_QMF})
-install_pdb (qmfengine ${QPID_COMPONENT_QMF})
-
-set (qmfconsole_SOURCES
- qpid/console/Agent.cpp
- qpid/console/Broker.cpp
- qpid/console/ClassKey.cpp
- qpid/console/Event.cpp
- qpid/console/Object.cpp
- qpid/console/ObjectId.cpp
- qpid/console/Package.cpp
- qpid/console/Schema.cpp
- qpid/console/SequenceManager.cpp
- qpid/console/SessionManager.cpp
- qpid/console/Value.cpp
- )
-set (qmfconsole_HEADERS
- ../include/qpid/console/Agent.h
- ../include/qpid/console/Broker.h
- ../include/qpid/console/ClassKey.h
- ../include/qpid/console/ConsoleImportExport.h
- ../include/qpid/console/ConsoleListener.h
- ../include/qpid/console/Event.h
- ../include/qpid/console/Object.h
- ../include/qpid/console/ObjectId.h
- ../include/qpid/console/Package.h
- ../include/qpid/console/Schema.h
- ../include/qpid/console/SequenceManager.h
- ../include/qpid/console/SessionManager.h
- ../include/qpid/console/Value.h
- )
-add_msvc_version (qmfconsole library dll)
-add_library (qmfconsole SHARED ${qmfconsole_SOURCES})
-target_link_libraries (qmfconsole qpidclient)
-set_target_properties (qmfconsole PROPERTIES
- VERSION ${qmfconsole_version}
- SOVERSION ${qmfconsole_version_major})
-install (TARGETS qmfconsole
- DESTINATION ${QPID_INSTALL_LIBDIR}
- COMPONENT ${QPID_COMPONENT_QMF})
-install (FILES ${qmfconsole_HEADERS}
- DESTINATION ${QPID_INSTALL_INCLUDEDIR}/qpid/console
- COMPONENT ${QPID_COMPONENT_QMF})
-install_pdb (qmfconsole ${QPID_COMPONENT_QMF})
-
-
#
# Legacy store
#
diff --git a/qpid/cpp/src/Makefile.am b/qpid/cpp/src/Makefile.am
deleted file mode 100644
index 8a98cea1ee..0000000000
--- a/qpid/cpp/src/Makefile.am
+++ /dev/null
@@ -1,1119 +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.
-#
-
-SUBDIRS = . tests
-
-# The Windows-only sources are not compiled using this Makefile, but
-# are listed here to ensure they're included in releases. They are built
-# using Visual Studio solutions/projects.
-windows_dist = \
- qpid/client/windows/SaslFactory.cpp \
- qpid/client/windows/SslConnector.cpp \
- qpid/client/windows/ClientDllMain.cpp \
- qpid/log/windows/SinkOptions.cpp \
- qpid/log/windows/SinkOptions.h \
- ../include/qpid/sys/windows/check.h \
- qpid/sys/MemStat.cpp \
- qpid/sys/windows/AsynchIO.cpp \
- qpid/sys/windows/AsynchIoResult.h \
- ../include/qpid/sys/windows/Condition.h \
- qpid/sys/windows/FileSysDir.cpp \
- ../include/qpid/sys/windows/IntegerTypes.h \
- qpid/sys/windows/IocpPoller.cpp \
- qpid/sys/windows/IOHandle.cpp \
- qpid/sys/windows/IoHandlePrivate.h \
- qpid/sys/windows/LockFile.cpp \
- qpid/sys/windows/MemoryMappedFile.cpp \
- qpid/sys/windows/mingw32_compat.h \
- qpid/sys/windows/PollableCondition.cpp \
- qpid/sys/windows/PipeHandle.cpp \
- ../include/qpid/sys/windows/Mutex.h \
- qpid/sys/windows/QpidDllMain.h \
- qpid/sys/windows/Shlib.cpp \
- qpid/sys/windows/SocketAddress.cpp \
- qpid/sys/windows/SslAsynchIO.cpp \
- qpid/sys/windows/SslAsynchIO.h \
- qpid/sys/windows/StrError.cpp \
- qpid/sys/windows/SystemInfo.cpp \
- qpid/sys/windows/Thread.cpp \
- qpid/sys/windows/Time.cpp \
- ../include/qpid/sys/windows/Time.h \
- qpid/sys/windows/uuid.cpp \
- qpid/sys/windows/uuid.h \
- qpid/sys/windows/WinSocket.cpp \
- qpid/sys/windows/WinSocket.h \
- windows/QpiddBroker.cpp \
- windows/SCM.h \
- windows/SCM.cpp \
- qpid/broker/windows/BrokerDefaults.cpp \
- qpid/broker/windows/SaslAuthenticator.cpp \
- qpid/broker/windows/SslProtocolFactory.cpp \
- qpid/messaging/HandleInstantiator.cpp \
- windows/resources/template-resource.rc \
- windows/resources/version-resource.h \
- windows/resources/qpid-icon.ico
-
-EXTRA_DIST= $(platform_dist) $(rgen_srcs) $(windows_dist)
-
-# Define variables that are be appended to by this file and included .mk files.
-nobase_include_HEADERS =
-libqpidcommon_la_SOURCES =
-pkgconfig_DATA =
-
-## Generated code
-
-# Note: generated soure and makefiles included in distribution so a
-# distribution can be built without code generation tools and XML
-# sources.
-
-# This phony target is needed by generated makefile fragments:
-force:
-
-if GENERATE
-
-# AMQP_FINAL_XML is defined in ../configure.ac
-amqp_0_10_xml=@AMQP_FINAL_XML@
-specs=$(amqp_0_10_xml)
-
-# Ruby generator.
-rgen_dir=$(top_srcdir)/rubygen
-rgen_cmd=ruby -I $(rgen_dir) $(rgen_dir)/generate . ../include $(specs) all
-
-$(rgen_srcs) $(srcdir)/rubygen.mk: rgen.timestamp
-rgen.timestamp: $(rgen_generator) $(specs)
- $(rgen_cmd) $(srcdir)/rubygen.mk && touch $@
-$(rgen_generator):
-
-# The CMake version is needed for dist
-$(srcdir)/rubygen.cmake: $(rgen_generator) $(specs)
- $(rgen_cmd) $(srcdir)/rubygen.cmake
-
-# Management generator.
-mgen_dir=$(top_srcdir)/managementgen
-mgen_xml=$(top_srcdir)/../specs/management-schema.xml \
- $(srcdir)/qpid/acl/management-schema.xml \
- $(srcdir)/qpid/ha/management-schema.xml \
- $(srcdir)/qpid/legacystore/management-schema.xml
-mgen_cmd=$(mgen_dir)/qmf-gen -m $(srcdir)/managementgen.mk \
- -c $(srcdir)/managementgen.cmake -q -b -l -o qmf \
- $(mgen_xml)
-
-$(srcdir)/managementgen.mk $(mgen_broker_cpp) $(dist_qpid_management_HEADERS): mgen.timestamp
-mgen.timestamp: $(mgen_generator) $(mgen_xml)
- $(mgen_cmd); touch $@
-$(mgen_generator):
-
-endif # GENERATE
-
-include $(srcdir)/rubygen.mk
-include $(srcdir)/managementgen.mk
-
-## Compiler flags
-AM_CXXFLAGS = $(WARNING_CFLAGS)
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(srcdir) -I=$(builddir)
-
-#
-# Destination for intalled programs and tests defined here
-#
-qpidexecdir = $(libexecdir)/qpid
-qpidexec_PROGRAMS =
-qpidexec_SCRIPTS =
-qpidtestdir = $(qpidexecdir)/tests
-qpidtest_PROGRAMS =
-qpidtest_SCRIPTS =
-tmoduleexecdir = $(libdir)/qpid/tests
-tmoduleexec_LTLIBRARIES=
-
-BROKER_CXXFLAGS = -D_IN_QPID_BROKER
-
-## Automake macros to build libraries and executables.
-qpidd_CXXFLAGS = $(AM_CXXFLAGS) $(BROKER_CXXFLAGS) -DQPIDD_MODULE_DIR=\"$(dmoduleexecdir)\" -DQPIDD_CONF_FILE=\"$(sysconfdir)/qpidd.conf\" -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.conf\"
-libqpidcommon_la_CXXFLAGS = $(AM_CXXFLAGS)
-libqpidbroker_la_CXXFLAGS = $(AM_CXXFLAGS) $(BROKER_CXXFLAGS)
-libqpidclient_la_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDC_MODULE_DIR=\"$(cmoduleexecdir)\" -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.conf\"
-
-qpidd_LDADD = \
- libqpidbroker.la \
- libqpidcommon.la \
- -lboost_program_options
-
-posix_qpidd_src = posix/QpiddBroker.cpp
-
-sbin_PROGRAMS = qpidd
-qpidd_SOURCES = qpidd.cpp qpidd.h $(posix_qpidd_src)
-
-## Platform specific code.
-
-# Posix-specific code
-libqpidcommon_la_SOURCES += \
- qpid/log/posix/SinkOptions.cpp \
- qpid/sys/posix/IOHandle.cpp \
- qpid/sys/posix/BSDSocket.cpp \
- qpid/sys/posix/BSDSocket.h \
- qpid/sys/posix/SocketAddress.cpp \
- qpid/sys/posix/AsynchIO.cpp \
- qpid/sys/posix/FileSysDir.cpp \
- qpid/sys/posix/LockFile.cpp \
- qpid/sys/posix/MemoryMappedFile.cpp \
- qpid/sys/posix/Time.cpp \
- qpid/sys/posix/Thread.cpp \
- qpid/sys/posix/Shlib.cpp \
- qpid/sys/posix/MemStat.cpp \
- qpid/sys/posix/Mutex.cpp \
- qpid/sys/posix/Fork.cpp \
- qpid/sys/posix/StrError.cpp \
- qpid/sys/posix/PollableCondition.cpp \
- qpid/sys/posix/PidFile.h \
- qpid/sys/posix/PipeHandle.cpp \
- qpid/log/posix/SinkOptions.h \
- qpid/sys/posix/Fork.h
-
-nobase_include_HEADERS += \
- ../include/qpid/sys/posix/Condition.h \
- ../include/qpid/sys/posix/IntegerTypes.h \
- ../include/qpid/sys/posix/Mutex.h \
- ../include/qpid/sys/posix/PrivatePosix.h \
- ../include/qpid/sys/posix/Time.h \
- ../include/qpid/sys/posix/check.h
-
-if USE_EPOLL
- poller = qpid/sys/epoll/EpollPoller.cpp
-endif
-
-if USE_POLL
- poller = qpid/sys/posix/PosixPoller.cpp
-endif
-
-if USE_ECF
- poller = qpid/sys/solaris/ECFPoller.cpp
-endif
-
-if SUNOS
- systeminfo = qpid/sys/solaris/SystemInfo.cpp
-else
- systeminfo = qpid/sys/posix/SystemInfo.cpp
-endif
-
-libqpidcommon_la_SOURCES += $(poller) $(systeminfo)
-
-posix_broker_src = \
- qpid/broker/posix/BrokerDefaults.cpp \
- qpid/broker/posix/SocketFDPlugin.cpp
-
-
-lib_LTLIBRARIES = libqpidtypes.la libqpidcommon.la libqpidbroker.la libqpidclient.la libqpidmessaging.la
-
-
-# Definitions for client and daemon plugins
-PLUGINLDFLAGS=-no-undefined -module -avoid-version
-confdir=$(sysconfdir)/qpid
-dmoduleexecdir=$(libdir)/qpid/daemon
-cmoduleexecdir=$(libdir)/qpid/client
-dmoduleexec_LTLIBRARIES =
-cmoduleexec_LTLIBRARIES =
-
-include ha.mk
-include qmf.mk
-include qmfc.mk
-if HAVE_XML
-include xml.mk
-endif
-include legacystore.mk
-
-if RDMA
-
-# RDMA (Infiniband) protocol code
-librdmawrap_la_SOURCES = \
- qpid/sys/rdma/rdma_exception.h \
- qpid/sys/rdma/rdma_factories.cpp \
- qpid/sys/rdma/rdma_factories.h \
- qpid/sys/rdma/RdmaIO.cpp \
- qpid/sys/rdma/RdmaIO.h \
- qpid/sys/rdma/rdma_wrap.cpp \
- qpid/sys/rdma/rdma_wrap.h
-librdmawrap_la_LIBADD = \
- libqpidcommon.la \
- -lrdmacm \
- -libverbs
-librdmawrap_la_CXXFLAGS = \
- $(AM_CXXFLAGS) -Wno-missing-field-initializers
-lib_LTLIBRARIES += \
- librdmawrap.la
-RDMAWRAP_VERSION_INFO = 2:0:0
-librdmawrap_la_LDFLAGS = -version-info $(RDMAWRAP_VERSION_INFO) -no-undefined
-
-rdma_la_SOURCES = \
- qpid/sys/RdmaIOPlugin.cpp
-rdma_la_LIBADD = \
- libqpidbroker.la \
- librdmawrap.la \
- -libverbs
-rdma_la_LDFLAGS = $(PLUGINLDFLAGS)
-rdma_la_CXXFLAGS = \
- $(AM_CXXFLAGS) -Wno-missing-field-initializers -D_IN_QPID_BROKER
-dmoduleexec_LTLIBRARIES += \
- rdma.la
-
-rdmaconnector_la_SOURCES = \
- qpid/client/RdmaConnector.cpp
-rdmaconnector_la_LIBADD = \
- libqpidclient.la \
- librdmawrap.la \
- -libverbs
-rdmaconnector_la_LDFLAGS = $(PLUGINLDFLAGS)
-rdmaconnector_la_CXXFLAGS = \
- $(AM_CXXFLAGS) -Wno-missing-field-initializers
-cmoduleexec_LTLIBRARIES += \
- rdmaconnector.la
-
-# RDMA test/sample programs
-noinst_PROGRAMS = RdmaServer RdmaClient
-RdmaServer_SOURCES = qpid/sys/rdma/RdmaServer.cpp
-RdmaServer_LDADD = \
- librdmawrap.la libqpidcommon.la
-RdmaClient_SOURCES = qpid/sys/rdma/RdmaClient.cpp
-RdmaClient_CXXFLAGS = \
- $(AM_CXXFLAGS) -Wno-missing-field-initializers
-RdmaClient_LDADD = \
- librdmawrap.la libqpidcommon.la
-
-endif
-
-EXTRA_DIST +=\
- CMakeLists.txt \
- config.h.cmake \
- amqp.cmake \
- rdma.cmake \
- legacystore.cmake \
- managementgen.cmake \
- rubygen.cmake \
- versions.cmake \
- finddb.cmake \
- $(rgen_amqp_0_10_srcs) \
- qpid/amqp_0_10/apply.h \
- qpid/amqp_0_10/built_in_types.h \
- qpid/amqp_0_10/complex_types.cpp \
- qpid/amqp_0_10/Array.h \
- qpid/amqp_0_10/Array.cpp \
- qpid/amqp_0_10/Body.h \
- qpid/amqp_0_10/Command.h \
- qpid/amqp_0_10/CommmandPacker.h \
- qpid/amqp_0_10/Control.h \
- qpid/amqp_0_10/Header.h \
- qpid/amqp_0_10/Header.cpp \
- qpid/amqp_0_10/FrameHeader.h \
- qpid/amqp_0_10/FrameHeader.cpp \
- qpid/amqp_0_10/Holder.h \
- qpid/amqp_0_10/Codec.h \
- qpid/amqp_0_10/Packer.h \
- qpid/amqp_0_10/Decimal.h \
- qpid/amqp_0_10/SerializableString.h \
- qpid/amqp_0_10/Map.h \
- qpid/amqp_0_10/Map.cpp \
- qpid/amqp_0_10/Struct.h \
- qpid/amqp_0_10/Struct32.h \
- qpid/amqp_0_10/Struct32.cpp \
- qpid/amqp_0_10/Unit.h \
- qpid/amqp_0_10/Unit.cpp \
- qpid/amqp_0_10/UnitHandler.h \
- qpid/amqp_0_10/UnknownType.h \
- qpid/amqp_0_10/UnknownType.cpp \
- qpid/amqp_0_10/UnknownStruct.h \
- qpid/amqp_0_10/UnknownStruct.cpp \
- qpid/store
-
-libqpidcommon_la_LIBADD = \
- libqpidtypes.la \
- -lboost_program_options \
- -luuid \
- -lpthread \
- $(LIB_DLOPEN) \
- $(LIB_CLOCK_GETTIME)
-
-libqpidcommon_la_SOURCES += \
- $(rgen_framing_srcs) \
- $(platform_src) \
- qpid/Address.cpp \
- qpid/DataDir.cpp \
- qpid/DataDir.h \
- qpid/DisableExceptionLogging.h \
- qpid/Exception.cpp \
- qpid/Modules.cpp \
- qpid/Modules.h \
- qpid/Options.cpp \
- qpid/Plugin.cpp \
- qpid/Plugin.h \
- qpid/RefCounted.h \
- qpid/RefCountedBuffer.cpp \
- qpid/RefCountedBuffer.h \
- qpid/BufferRef.h \
- qpid/Sasl.h \
- qpid/SaslFactory.cpp \
- qpid/SaslFactory.h \
- qpid/SaslServer.h \
- qpid/NullSaslServer.h \
- qpid/NullSaslServer.cpp \
- qpid/Serializer.h \
- qpid/SessionId.cpp \
- qpid/SessionState.cpp \
- qpid/SessionState.h \
- qpid/SessionState.h \
- qpid/SharedObject.h \
- qpid/StringUtils.cpp \
- qpid/StringUtils.h \
- qpid/Url.cpp \
- qpid/UrlArray.cpp \
- qpid/UrlArray.h \
- qpid/Version.h \
- qpid/amqp_0_10/Exception.h \
- qpid/amqp_0_10/SessionHandler.cpp \
- qpid/amqp_0_10/SessionHandler.h \
- qpid/amqp_0_10/apply.h \
- qpid/assert.cpp qpid/assert.h \
- qpid/assert.h \
- qpid/framing/AMQBody.cpp \
- qpid/framing/AMQBody.h \
- qpid/framing/AMQContentBody.cpp \
- qpid/framing/AMQContentBody.h \
- qpid/framing/AMQDataBlock.h \
- qpid/framing/AMQFrame.cpp \
- qpid/framing/AMQFrame.h \
- qpid/framing/AMQHeaderBody.cpp \
- qpid/framing/AMQHeaderBody.h \
- qpid/framing/AMQHeartbeatBody.cpp \
- qpid/framing/AMQHeartbeatBody.h \
- qpid/framing/AMQMethodBody.cpp \
- qpid/framing/AMQMethodBody.h \
- qpid/framing/AMQP_HighestVersion.h \
- qpid/framing/AMQP_HighestVersion.h \
- qpid/framing/AccumulatedAck.cpp \
- qpid/framing/AccumulatedAck.h \
- qpid/framing/Array.cpp \
- qpid/framing/BodyFactory.h \
- qpid/framing/Buffer.cpp \
- qpid/framing/ResizableBuffer.h \
- qpid/framing/ChannelHandler.h \
- qpid/framing/Endian.cpp \
- qpid/framing/Endian.h \
- qpid/framing/FieldTable.cpp \
- qpid/framing/FieldValue.cpp \
- qpid/framing/FrameDecoder.cpp \
- qpid/framing/FrameDecoder.h \
- qpid/framing/FrameDefaultVisitor.h \
- qpid/framing/FrameHandler.h \
- qpid/framing/FrameSet.cpp \
- qpid/framing/FrameSet.h \
- qpid/framing/Handler.h \
- qpid/framing/HeaderProperties.h \
- qpid/framing/InitiationHandler.h \
- qpid/framing/InputHandler.h \
- qpid/framing/Invoker.h \
- qpid/framing/IsInSequenceSet.h \
- qpid/framing/List.cpp \
- qpid/framing/MethodBodyFactory.h \
- qpid/framing/MethodContent.h \
- qpid/framing/ModelMethod.h \
- qpid/framing/ProtocolInitiation.cpp \
- qpid/framing/ProtocolInitiation.h \
- qpid/framing/ProtocolVersion.cpp \
- qpid/framing/Proxy.cpp \
- qpid/framing/Proxy.h \
- qpid/framing/SendContent.cpp \
- qpid/framing/SendContent.h \
- qpid/framing/SequenceNumber.cpp \
- qpid/framing/SequenceNumberSet.cpp \
- qpid/framing/SequenceNumberSet.h \
- qpid/framing/SequenceSet.cpp \
- qpid/framing/TransferContent.cpp \
- qpid/framing/TransferContent.h \
- qpid/framing/TypeFilter.h \
- qpid/framing/Uuid.cpp \
- qpid/framing/Visitor.h \
- qpid/framing/amqp_framing.h \
- qpid/framing/frame_functors.h \
- qpid/framing/variant.h \
- qpid/log/Helpers.h \
- qpid/log/Logger.cpp \
- qpid/log/Options.cpp \
- qpid/log/OstreamOutput.cpp \
- qpid/log/OstreamOutput.h \
- qpid/log/Selector.cpp \
- qpid/log/Statement.cpp \
- qpid/management/Buffer.cpp \
- qpid/management/ConnectionSettings.cpp \
- qpid/management/Manageable.cpp \
- qpid/management/ManagementObject.cpp \
- qpid/management/Mutex.cpp \
- qpid/memory.h \
- qpid/pointer_to_other.h \
- qpid/ptr_map.h \
- qpid/sys/AggregateOutput.cpp \
- qpid/sys/AggregateOutput.h \
- qpid/sys/AsynchIO.h \
- qpid/sys/AsynchIOHandler.cpp \
- qpid/sys/AsynchIOHandler.h \
- qpid/sys/AtomicCount.h \
- qpid/sys/AtomicValue.h \
- qpid/sys/AtomicValue_gcc.h \
- qpid/sys/AtomicValue_mutex.h \
- qpid/sys/BlockingQueue.h \
- qpid/sys/Codec.h \
- qpid/sys/ConnectionCodec.h \
- qpid/sys/ConnectionInputHandler.h \
- qpid/sys/ConnectionInputHandlerFactory.h \
- qpid/sys/ConnectionOutputHandler.h \
- qpid/sys/CopyOnWriteArray.h \
- qpid/sys/DeletionManager.h \
- qpid/sys/DispatchHandle.cpp \
- qpid/sys/DispatchHandle.h \
- qpid/sys/Dispatcher.cpp \
- qpid/sys/Dispatcher.h \
- qpid/sys/FileSysDir.h \
- qpid/sys/Fork.h \
- qpid/sys/LockFile.h \
- qpid/sys/LockPtr.h \
- qpid/sys/MemoryMappedFile.h \
- qpid/sys/MemStat.h \
- qpid/sys/OutputControl.h \
- qpid/sys/OutputTask.h \
- qpid/sys/PipeHandle.h \
- qpid/sys/PollableCondition.h \
- qpid/sys/PollableQueue.h \
- qpid/sys/Poller.h \
- qpid/sys/Probes.h \
- qpid/sys/regex.h \
- qpid/sys/Runnable.cpp \
- qpid/sys/ScopedIncrement.h \
- qpid/sys/SecurityLayer.h \
- qpid/sys/SecuritySettings.h \
- qpid/sys/Semaphore.h \
- qpid/sys/Shlib.cpp \
- qpid/sys/Shlib.h \
- qpid/sys/ShutdownHandler.h \
- qpid/sys/Socket.h \
- qpid/sys/SocketAddress.h \
- qpid/sys/StateMonitor.h \
- qpid/sys/Timer.cpp \
- qpid/sys/Timer.h \
- qpid/sys/TimerWarnings.cpp \
- qpid/sys/TimerWarnings.h \
- qpid/sys/Waitable.h \
- qpid/sys/uuid.h \
- qpid/sys/unordered_map.h \
- qpid/amqp_0_10/CodecsInternal.h \
- qpid/amqp_0_10/Codecs.cpp \
- qpid/amqp/CharSequence.h \
- qpid/amqp/CharSequence.cpp \
- qpid/amqp/Codec.h \
- qpid/amqp/Constructor.h \
- qpid/amqp/Decoder.h \
- qpid/amqp/Decoder.cpp \
- qpid/amqp/Descriptor.h \
- qpid/amqp/Descriptor.cpp \
- qpid/amqp/descriptors.h \
- qpid/amqp/Encoder.h \
- qpid/amqp/Encoder.cpp \
- qpid/amqp/ListReader.h \
- qpid/amqp/LoggingReader.h \
- qpid/amqp/MapHandler.h \
- qpid/amqp/MapEncoder.h \
- qpid/amqp/MapEncoder.cpp \
- qpid/amqp/MapSizeCalculator.h \
- qpid/amqp/MapSizeCalculator.cpp \
- qpid/amqp/MapBuilder.h \
- qpid/amqp/MapBuilder.cpp \
- qpid/amqp/MapReader.h \
- qpid/amqp/MapReader.cpp \
- qpid/amqp/MessageEncoder.h \
- qpid/amqp/MessageEncoder.cpp \
- qpid/amqp/MessageId.h \
- qpid/amqp/MessageId.cpp \
- qpid/amqp/MessageReader.h \
- qpid/amqp/MessageReader.cpp \
- qpid/amqp/Reader.h \
- qpid/amqp/Sasl.h \
- qpid/amqp/Sasl.cpp \
- qpid/amqp/SaslClient.h \
- qpid/amqp/SaslClient.cpp \
- qpid/amqp/SaslServer.h \
- qpid/amqp/SaslServer.cpp \
- qpid/amqp/typecodes.h
-
-#libqpidcommon is not really the 'right' place for the Transport
-#interface, which is only used in 1.0 impl of messaging API, but this
-#lets the 1.0 SSL support be included in the existing sslconnector lib
-#which in turn addresses common ssl needs in qpidclient and
-#qpidmessaging:
-libqpidcommon_la_SOURCES += \
- qpid/messaging/amqp/Transport.h \
- qpid/messaging/amqp/Transport.cpp \
- qpid/messaging/amqp/TransportContext.h
-
-if HAVE_SASL
-libqpidcommon_la_SOURCES += qpid/sys/cyrus/CyrusSecurityLayer.h
-libqpidcommon_la_SOURCES += qpid/sys/cyrus/CyrusSecurityLayer.cpp
-libqpidcommon_la_LIBADD += -lsasl2
-endif
-
-QPIDCOMMON_VERSION_INFO = 2:0:0
-libqpidcommon_la_LDFLAGS=-version-info $(QPIDCOMMON_VERSION_INFO)
-
-libqpidbroker_la_LIBADD = libqpidcommon.la
-libqpidbroker_la_SOURCES = \
- $(mgen_broker_cpp) \
- $(posix_broker_src) \
- qpid/acl/Acl.cpp \
- qpid/acl/Acl.h \
- qpid/acl/AclConnectionCounter.cpp \
- qpid/acl/AclConnectionCounter.h \
- qpid/acl/AclData.cpp \
- qpid/acl/AclData.h \
- qpid/acl/AclPlugin.cpp \
- qpid/acl/AclReader.cpp \
- qpid/acl/AclReader.h \
- qpid/acl/AclResourceCounter.cpp \
- qpid/acl/AclResourceCounter.h \
- qpid/acl/AclTopicMatch.h \
- qpid/acl/AclValidator.cpp \
- qpid/acl/AclValidator.h \
- qpid/amqp_0_10/Connection.cpp \
- qpid/amqp_0_10/Connection.h \
- qpid/broker/AclModule.h \
- qpid/broker/Bridge.cpp \
- qpid/broker/Bridge.h \
- qpid/broker/Broker.cpp \
- qpid/broker/Broker.h \
- qpid/broker/BrokerImportExport.h \
- qpid/broker/amqp_0_10/Connection.cpp \
- qpid/broker/amqp_0_10/Connection.h \
- qpid/broker/ConnectionHandler.cpp \
- qpid/broker/ConnectionHandler.h \
- qpid/broker/Consumer.h \
- qpid/broker/Credit.h \
- qpid/broker/Credit.cpp \
- qpid/broker/ConsumerFactory.h \
- qpid/broker/Connection.h \
- qpid/broker/ConnectionObserver.h \
- qpid/broker/ConnectionObservers.h \
- qpid/broker/ConfigurationObserver.h \
- qpid/broker/ConfigurationObservers.h \
- qpid/broker/Daemon.cpp \
- qpid/broker/Daemon.h \
- qpid/broker/Deliverable.h \
- qpid/broker/DeliverableMessage.cpp \
- qpid/broker/DeliverableMessage.h \
- qpid/broker/DeliveryId.h \
- qpid/broker/DeliveryRecord.cpp \
- qpid/broker/DeliveryRecord.h \
- qpid/broker/DirectExchange.cpp \
- qpid/broker/DirectExchange.h \
- qpid/broker/DtxAck.cpp \
- qpid/broker/DtxAck.h \
- qpid/broker/DtxBuffer.cpp \
- qpid/broker/DtxBuffer.h \
- qpid/broker/DtxManager.cpp \
- qpid/broker/DtxManager.h \
- qpid/broker/DtxTimeout.cpp \
- qpid/broker/DtxTimeout.h \
- qpid/broker/DtxWorkRecord.cpp \
- qpid/broker/DtxWorkRecord.h \
- qpid/broker/Exchange.cpp \
- qpid/broker/Exchange.h \
- qpid/broker/ExchangeRegistry.cpp \
- qpid/broker/ExchangeRegistry.h \
- qpid/broker/ExpiryPolicy.cpp \
- qpid/broker/ExpiryPolicy.h \
- qpid/broker/Fairshare.h \
- qpid/broker/Fairshare.cpp \
- qpid/broker/FanOutExchange.cpp \
- qpid/broker/FanOutExchange.h \
- qpid/broker/FedOps.h \
- qpid/broker/HandlerImpl.h \
- qpid/broker/HeadersExchange.cpp \
- qpid/broker/HeadersExchange.h \
- qpid/broker/AsyncCompletion.h \
- qpid/broker/IngressCompletion.h \
- qpid/broker/IngressCompletion.cpp \
- qpid/broker/IndexedDeque.h \
- qpid/broker/Link.cpp \
- qpid/broker/Link.h \
- qpid/broker/LinkRegistry.cpp \
- qpid/broker/LinkRegistry.h \
- qpid/broker/Lvq.h \
- qpid/broker/Lvq.cpp \
- qpid/broker/Message.cpp \
- qpid/broker/Message.h \
- qpid/broker/MessageAdapter.cpp \
- qpid/broker/MessageAdapter.h \
- qpid/broker/MessageBuilder.cpp \
- qpid/broker/MessageBuilder.h \
- qpid/broker/MessageDeque.h \
- qpid/broker/MessageDeque.cpp \
- qpid/broker/MessageInterceptor.h \
- qpid/broker/MessageMap.h \
- qpid/broker/MessageMap.cpp \
- qpid/broker/Messages.h \
- qpid/broker/MessageStore.h \
- qpid/broker/MessageStoreModule.cpp \
- qpid/broker/MessageStoreModule.h \
- qpid/broker/PagedQueue.h \
- qpid/broker/PagedQueue.cpp \
- qpid/broker/PriorityQueue.h \
- qpid/broker/PriorityQueue.cpp \
- qpid/broker/Protocol.h \
- qpid/broker/Protocol.cpp \
- qpid/broker/NameGenerator.cpp \
- qpid/broker/NameGenerator.h \
- qpid/broker/NullMessageStore.cpp \
- qpid/broker/NullMessageStore.h \
- qpid/broker/ObjectFactory.h \
- qpid/broker/ObjectFactory.cpp \
- qpid/broker/Observers.h \
- qpid/broker/OwnershipToken.h \
- qpid/broker/Persistable.h \
- qpid/broker/PersistableConfig.h \
- qpid/broker/PersistableExchange.h \
- qpid/broker/PersistableMessage.cpp \
- qpid/broker/PersistableMessage.h \
- qpid/broker/PersistableObject.h \
- qpid/broker/PersistableObject.cpp \
- qpid/broker/PersistableQueue.h \
- qpid/broker/Queue.cpp \
- qpid/broker/Queue.h \
- qpid/broker/QueueBindings.cpp \
- qpid/broker/QueueBindings.h \
- qpid/broker/QueueCleaner.cpp \
- qpid/broker/QueueCleaner.h \
- qpid/broker/QueueCursor.h \
- qpid/broker/QueueCursor.cpp \
- qpid/broker/QueueDepth.h \
- qpid/broker/QueueDepth.cpp \
- qpid/broker/QueueFactory.h \
- qpid/broker/QueueFactory.cpp \
- qpid/broker/QueueSettings.h \
- qpid/broker/QueueSettings.cpp \
- qpid/broker/QueueListeners.cpp \
- qpid/broker/QueueListeners.h \
- qpid/broker/QueueObserver.h \
- qpid/broker/QueueRegistry.cpp \
- qpid/broker/QueueRegistry.h \
- qpid/broker/QueuedMessage.cpp \
- qpid/broker/QueuedMessage.h \
- qpid/broker/QueueFlowLimit.h \
- qpid/broker/QueueFlowLimit.cpp \
- qpid/broker/LossyQueue.h \
- qpid/broker/LossyQueue.cpp \
- qpid/broker/RecoverableConfig.h \
- qpid/broker/RecoverableExchange.h \
- qpid/broker/RecoverableMessage.h \
- qpid/broker/RecoverableQueue.h \
- qpid/broker/RecoverableTransaction.h \
- qpid/broker/RecoveredDequeue.cpp \
- qpid/broker/RecoveredDequeue.h \
- qpid/broker/RecoveredEnqueue.cpp \
- qpid/broker/RecoveredEnqueue.h \
- qpid/broker/RecoveryManager.h \
- qpid/broker/RecoveryManagerImpl.cpp \
- qpid/broker/RecoveryManagerImpl.h \
- qpid/broker/RecoverableMessageImpl.h \
- qpid/broker/RetryList.cpp \
- qpid/broker/RetryList.h \
- qpid/broker/SaslAuthenticator.cpp \
- qpid/broker/SaslAuthenticator.h \
- qpid/broker/SecureConnection.cpp \
- qpid/broker/SecureConnection.h \
- qpid/broker/SecureConnectionFactory.cpp \
- qpid/broker/SecureConnectionFactory.h \
- qpid/broker/Selector.cpp \
- qpid/broker/Selector.h \
- qpid/broker/SelectorExpression.cpp \
- qpid/broker/SelectorExpression.h \
- qpid/broker/SelectorToken.cpp \
- qpid/broker/SelectorToken.h \
- qpid/broker/SelectorValue.cpp \
- qpid/broker/SelectorValue.h \
- qpid/broker/SemanticState.cpp \
- qpid/broker/SemanticState.h \
- qpid/broker/SessionAdapter.cpp \
- qpid/broker/SessionAdapter.h \
- qpid/broker/SessionAdapter.h \
- qpid/broker/SessionContext.h \
- qpid/broker/SessionHandler.cpp \
- qpid/broker/SessionHandler.h \
- qpid/broker/SessionManager.cpp \
- qpid/broker/SessionManager.h \
- qpid/broker/SessionManager.h \
- qpid/broker/SessionOutputException.h \
- qpid/broker/SessionState.cpp \
- qpid/broker/SessionState.h \
- qpid/broker/SignalHandler.cpp \
- qpid/broker/SignalHandler.h \
- qpid/broker/System.cpp \
- qpid/broker/System.h \
- qpid/broker/ThresholdAlerts.cpp \
- qpid/broker/ThresholdAlerts.h \
- qpid/broker/TopicExchange.cpp \
- qpid/broker/TopicExchange.h \
- qpid/broker/TopicKeyNode.h \
- qpid/broker/TransactionalStore.h \
- qpid/broker/TxAccept.cpp \
- qpid/broker/TxAccept.h \
- qpid/broker/TxBuffer.cpp \
- qpid/broker/TxBuffer.h \
- qpid/broker/TxOp.h \
- qpid/broker/Vhost.cpp \
- qpid/broker/Vhost.h \
- qpid/broker/MessageDistributor.h \
- qpid/broker/FifoDistributor.h \
- qpid/broker/FifoDistributor.cpp \
- qpid/broker/MessageGroupManager.cpp \
- qpid/broker/MessageGroupManager.h \
- qpid/broker/amqp_0_10/MessageTransfer.h \
- qpid/broker/amqp_0_10/MessageTransfer.cpp \
- qpid/management/ManagementAgent.cpp \
- qpid/management/ManagementAgent.h \
- qpid/management/ManagementDirectExchange.cpp \
- qpid/management/ManagementDirectExchange.h \
- qpid/management/ManagementTopicExchange.cpp \
- qpid/management/ManagementTopicExchange.h \
- qpid/sys/TCPIOPlugin.cpp \
- qpid/sys/SocketTransport.cpp \
- qpid/sys/SocketTransport.h \
- qpid/sys/TransportFactory.h
-
-QPIDBROKER_VERSION_INFO = 2:0:0
-libqpidbroker_la_LDFLAGS = -version-info $(QPIDBROKER_VERSION_INFO)
-
-if HAVE_PROTON
-
-dmoduleexec_LTLIBRARIES += amqp.la
-amqp_la_LIBADD = libqpidcommon.la
-amqp_la_SOURCES = \
- qpid/broker/amqp/Authorise.h \
- qpid/broker/amqp/Authorise.cpp \
- qpid/broker/amqp/BrokerContext.h \
- qpid/broker/amqp/BrokerContext.cpp \
- qpid/broker/amqp/Connection.h \
- qpid/broker/amqp/Connection.cpp \
- qpid/broker/amqp/DataReader.h \
- qpid/broker/amqp/DataReader.cpp \
- qpid/broker/amqp/Domain.h \
- qpid/broker/amqp/Domain.cpp \
- qpid/broker/amqp/Exception.h \
- qpid/broker/amqp/Exception.cpp \
- qpid/broker/amqp/Filter.h \
- qpid/broker/amqp/Filter.cpp \
- qpid/broker/amqp/Header.h \
- qpid/broker/amqp/Header.cpp \
- qpid/broker/amqp/Incoming.h \
- qpid/broker/amqp/Incoming.cpp \
- qpid/broker/amqp/Interconnect.h \
- qpid/broker/amqp/Interconnect.cpp \
- qpid/broker/amqp/Interconnects.h \
- qpid/broker/amqp/Interconnects.cpp \
- qpid/broker/amqp/ManagedConnection.h \
- qpid/broker/amqp/ManagedConnection.cpp \
- qpid/broker/amqp/ManagedSession.h \
- qpid/broker/amqp/ManagedSession.cpp \
- qpid/broker/amqp/ManagedIncomingLink.h \
- qpid/broker/amqp/ManagedIncomingLink.cpp \
- qpid/broker/amqp/ManagedOutgoingLink.h \
- qpid/broker/amqp/ManagedOutgoingLink.cpp \
- qpid/broker/amqp/Message.h \
- qpid/broker/amqp/Message.cpp \
- qpid/broker/amqp/NodeProperties.h \
- qpid/broker/amqp/NodeProperties.cpp \
- qpid/broker/amqp/Outgoing.h \
- qpid/broker/amqp/Outgoing.cpp \
- qpid/broker/amqp/ProtocolPlugin.cpp \
- qpid/broker/amqp/Relay.h \
- qpid/broker/amqp/Relay.cpp \
- qpid/broker/amqp/Sasl.h \
- qpid/broker/amqp/Sasl.cpp \
- qpid/broker/amqp/SaslClient.h \
- qpid/broker/amqp/SaslClient.cpp \
- qpid/broker/amqp/Session.h \
- qpid/broker/amqp/Session.cpp \
- qpid/broker/amqp/Topic.h \
- qpid/broker/amqp/Topic.cpp \
- qpid/broker/amqp/Translation.h \
- qpid/broker/amqp/Translation.cpp
-
-amqp_la_CXXFLAGS=$(AM_CXXFLAGS) $(BROKER_CXXFLAGS) $(PROTON_CFLAGS)
-amqp_la_LDFLAGS = $(PLUGINLDFLAGS) $(PROTON_LIBS)
-
-cmoduleexec_LTLIBRARIES += amqpc.la
-amqpc_la_LIBADD = libqpidcommon.la
-amqpc_la_SOURCES = \
- qpid/messaging/amqp/AddressHelper.h \
- qpid/messaging/amqp/AddressHelper.cpp \
- qpid/messaging/amqp/ConnectionContext.h \
- qpid/messaging/amqp/ConnectionContext.cpp \
- qpid/messaging/amqp/ConnectionHandle.h \
- qpid/messaging/amqp/ConnectionHandle.cpp \
- qpid/messaging/amqp/DriverImpl.h \
- qpid/messaging/amqp/DriverImpl.cpp \
- qpid/messaging/amqp/ReceiverContext.h \
- qpid/messaging/amqp/ReceiverContext.cpp \
- qpid/messaging/amqp/ReceiverHandle.h \
- qpid/messaging/amqp/ReceiverHandle.cpp \
- qpid/messaging/amqp/Sasl.h \
- qpid/messaging/amqp/Sasl.cpp \
- qpid/messaging/amqp/SenderContext.h \
- qpid/messaging/amqp/SenderContext.cpp \
- qpid/messaging/amqp/SenderHandle.h \
- qpid/messaging/amqp/SenderHandle.cpp \
- qpid/messaging/amqp/SessionContext.h \
- qpid/messaging/amqp/SessionContext.cpp \
- qpid/messaging/amqp/SessionHandle.h \
- qpid/messaging/amqp/SessionHandle.cpp \
- qpid/messaging/amqp/TcpTransport.h \
- qpid/messaging/amqp/TcpTransport.cpp
-
-amqpc_la_CXXFLAGS=$(AM_CXXFLAGS) $(PROTON_CFLAGS)
-amqpc_la_LDFLAGS = $(PLUGINLDFLAGS) $(PROTON_LIBS)
-
-endif #HAVE_PROTON
-
-libqpidclient_la_LIBADD = libqpidcommon.la -luuid
-
-libqpidclient_la_SOURCES = \
- $(rgen_client_srcs) \
- qpid/client/Bounds.cpp \
- qpid/client/Bounds.h \
- qpid/client/ChainableFrameHandler.h \
- qpid/client/Completion.cpp \
- qpid/client/CompletionImpl.h \
- qpid/client/Connection.cpp \
- qpid/client/ConnectionAccess.h \
- qpid/client/ConnectionHandler.cpp \
- qpid/client/ConnectionHandler.h \
- qpid/client/ConnectionImpl.cpp \
- qpid/client/ConnectionImpl.h \
- qpid/client/ConnectionSettings.cpp \
- qpid/client/Connector.cpp \
- qpid/client/Connector.h \
- qpid/client/Demux.cpp \
- qpid/client/Demux.h \
- qpid/client/Dispatcher.cpp \
- qpid/client/Dispatcher.h \
- qpid/client/Execution.h \
- qpid/client/FailoverListener.cpp \
- qpid/client/FailoverManager.cpp \
- qpid/client/Future.cpp \
- qpid/client/FutureCompletion.cpp \
- qpid/client/FutureResult.cpp \
- qpid/client/LoadPlugins.h \
- qpid/client/LoadPlugins.cpp \
- qpid/client/LocalQueue.cpp \
- qpid/client/LocalQueueImpl.cpp \
- qpid/client/LocalQueueImpl.h \
- qpid/client/Message.cpp \
- qpid/client/MessageImpl.cpp \
- qpid/client/MessageImpl.h \
- qpid/client/MessageListener.cpp \
- qpid/client/MessageReplayTracker.cpp \
- qpid/client/PrivateImplRef.h \
- qpid/client/QueueOptions.cpp \
- qpid/client/Results.cpp \
- qpid/client/Results.h \
- qpid/client/SessionBase_0_10.cpp \
- qpid/client/SessionBase_0_10Access.h \
- qpid/client/SessionImpl.cpp \
- qpid/client/SessionImpl.h \
- qpid/client/StateManager.cpp \
- qpid/client/StateManager.h \
- qpid/client/Subscription.cpp \
- qpid/client/SubscriptionImpl.cpp \
- qpid/client/SubscriptionImpl.h \
- qpid/client/SubscriptionManager.cpp \
- qpid/client/SubscriptionManagerImpl.cpp \
- qpid/client/SubscriptionManagerImpl.h \
- qpid/client/TCPConnector.cpp \
- qpid/client/TCPConnector.h
-
-QPIDCLIENT_VERSION_INFO = 2:0:0
-libqpidclient_la_LDFLAGS = -version-info $(QPIDCLIENT_VERSION_INFO)
-
-if SSL
-include ssl.mk
-endif
-
-libqpidtypes_la_LIBADD= -luuid
-libqpidtypes_la_SOURCES= \
- qpid/types/Exception.cpp \
- qpid/types/Uuid.cpp \
- qpid/types/Variant.cpp \
- ../include/qpid/types/ImportExport.h
-
-QPIDTYPES_VERSION_INFO = 1:0:0
-libqpidtypes_la_LDFLAGS = -version-info $(QPIDTYPES_VERSION_INFO)
-
-libqpidmessaging_la_LIBADD = libqpidclient.la libqpidtypes.la
-libqpidmessaging_la_SOURCES = \
- qpid/messaging/Address.cpp \
- qpid/messaging/AddressImpl.h \
- qpid/messaging/AddressParser.h \
- qpid/messaging/AddressParser.cpp \
- qpid/messaging/Connection.cpp \
- qpid/messaging/ConnectionOptions.h \
- qpid/messaging/ConnectionOptions.cpp \
- qpid/messaging/Duration.cpp \
- qpid/messaging/exceptions.cpp \
- qpid/messaging/Message.cpp \
- qpid/messaging/MessageImpl.h \
- qpid/messaging/MessageImpl.cpp \
- qpid/messaging/PrivateImplRef.h \
- qpid/messaging/ProtocolRegistry.h \
- qpid/messaging/ProtocolRegistry.cpp \
- qpid/messaging/Sender.cpp \
- qpid/messaging/Receiver.cpp \
- qpid/messaging/Session.cpp \
- qpid/messaging/ConnectionImpl.h \
- qpid/messaging/SenderImpl.h \
- qpid/messaging/ReceiverImpl.h \
- qpid/messaging/SessionImpl.h \
- qpid/messaging/FailoverUpdates.cpp \
- qpid/messaging/amqp/EncodedMessage.h \
- qpid/messaging/amqp/EncodedMessage.cpp \
- qpid/client/amqp0_10/AcceptTracker.h \
- qpid/client/amqp0_10/AcceptTracker.cpp \
- qpid/client/amqp0_10/AddressResolution.h \
- qpid/client/amqp0_10/AddressResolution.cpp \
- qpid/client/amqp0_10/ConnectionImpl.h \
- qpid/client/amqp0_10/ConnectionImpl.cpp \
- qpid/client/amqp0_10/IncomingMessages.h \
- qpid/client/amqp0_10/IncomingMessages.cpp \
- qpid/client/amqp0_10/MessageSink.h \
- qpid/client/amqp0_10/MessageSource.h \
- qpid/client/amqp0_10/OutgoingMessage.h \
- qpid/client/amqp0_10/OutgoingMessage.cpp \
- qpid/client/amqp0_10/ReceiverImpl.h \
- qpid/client/amqp0_10/ReceiverImpl.cpp \
- qpid/client/amqp0_10/SessionImpl.h \
- qpid/client/amqp0_10/SessionImpl.cpp \
- qpid/client/amqp0_10/SenderImpl.h \
- qpid/client/amqp0_10/SenderImpl.cpp
-
-QPIDMESSAGING_VERSION_INFO = 2:0:0
-libqpidmessaging_la_LDFLAGS = -version-info $(QPIDMESSAGING_VERSION_INFO)
-
-# NOTE: only public header files (which should be in ../include)
-# should go in this list. Private headers should go in the SOURCES
-# list for one of the libraries or executables that includes it.
-# Also included are the swig descriptor files.
-
-nobase_include_HEADERS += \
- ../include/qpid/Address.h \
- ../include/qpid/CommonImportExport.h \
- ../include/qpid/Exception.h \
- ../include/qpid/ImportExport.h \
- ../include/qpid/InlineAllocator.h \
- ../include/qpid/InlineVector.h \
- ../include/qpid/Msg.h \
- ../include/qpid/Options.h \
- ../include/qpid/RangeSet.h \
- ../include/qpid/SessionId.h \
- ../include/qpid/Url.h \
- ../include/qpid/amqp_0_10/Codecs.h \
- ../include/qpid/client/AsyncSession.h \
- ../include/qpid/client/ClientImportExport.h \
- ../include/qpid/client/Completion.h \
- ../include/qpid/client/Connection.h \
- ../include/qpid/client/ConnectionSettings.h \
- ../include/qpid/client/FailoverListener.h \
- ../include/qpid/client/FailoverManager.h \
- ../include/qpid/client/FlowControl.h \
- ../include/qpid/client/Future.h \
- ../include/qpid/client/FutureCompletion.h \
- ../include/qpid/client/FutureResult.h \
- ../include/qpid/client/Handle.h \
- ../include/qpid/client/LocalQueue.h \
- ../include/qpid/client/Message.h \
- ../include/qpid/client/MessageListener.h \
- ../include/qpid/client/MessageReplayTracker.h \
- ../include/qpid/client/QueueOptions.h \
- ../include/qpid/client/Session.h \
- ../include/qpid/client/SessionBase_0_10.h \
- ../include/qpid/client/Subscription.h \
- ../include/qpid/client/SubscriptionManager.h \
- ../include/qpid/client/SubscriptionSettings.h \
- ../include/qpid/client/TypedResult.h \
- ../include/qpid/framing/Array.h \
- ../include/qpid/framing/Buffer.h \
- ../include/qpid/framing/FieldTable.h \
- ../include/qpid/framing/FieldValue.h \
- ../include/qpid/framing/List.h \
- ../include/qpid/framing/ProtocolVersion.h \
- ../include/qpid/framing/SequenceNumber.h \
- ../include/qpid/framing/SequenceSet.h \
- ../include/qpid/framing/StructHelper.h \
- ../include/qpid/framing/Uuid.h \
- ../include/qpid/framing/amqp_types.h \
- ../include/qpid/framing/amqp_types_full.h \
- ../include/qpid/log/Logger.h \
- ../include/qpid/log/Options.h \
- ../include/qpid/log/Selector.h \
- ../include/qpid/log/SinkOptions.h \
- ../include/qpid/log/Statement.h \
- ../include/qpid/management/Args.h \
- ../include/qpid/management/Buffer.h \
- ../include/qpid/management/ConnectionSettings.h \
- ../include/qpid/management/Manageable.h \
- ../include/qpid/management/ManagementEvent.h \
- ../include/qpid/management/ManagementObject.h \
- ../include/qpid/management/Mutex.h \
- ../include/qpid/sys/Condition.h \
- ../include/qpid/sys/ExceptionHolder.h \
- ../include/qpid/sys/IOHandle.h \
- ../include/qpid/sys/IntegerTypes.h \
- ../include/qpid/sys/Monitor.h \
- ../include/qpid/sys/Mutex.h \
- ../include/qpid/sys/Runnable.h \
- ../include/qpid/sys/StrError.h \
- ../include/qpid/sys/SystemInfo.h \
- ../include/qpid/sys/Thread.h \
- ../include/qpid/sys/Time.h \
- ../include/qpid/messaging/Address.h \
- ../include/qpid/messaging/Connection.h \
- ../include/qpid/messaging/Duration.h \
- ../include/qpid/messaging/exceptions.h \
- ../include/qpid/messaging/Handle.h \
- ../include/qpid/messaging/ImportExport.h \
- ../include/qpid/messaging/Message.h \
- ../include/qpid/messaging/Receiver.h \
- ../include/qpid/messaging/Sender.h \
- ../include/qpid/messaging/Session.h \
- ../include/qpid/messaging/FailoverUpdates.h \
- ../include/qpid/types/Exception.h \
- ../include/qpid/types/Uuid.h \
- ../include/qpid/types/Variant.h \
- ../include/qpid/types/ImportExport.h \
- ../include/qpid/qpid.i \
- ../include/qmf/qmfengine.i \
- ../include/qmf/qmf2.i
-
-# Create the default data directory
-install-data-local:
- $(mkinstalldirs) $(DESTDIR)/$(localstatedir)/lib/qpidd
-
-# Support for pkg-config
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA += qpid.pc
-
diff --git a/qpid/cpp/src/amqp.cmake b/qpid/cpp/src/amqp.cmake
index 2d0ca06250..38b7d01315 100644
--- a/qpid/cpp/src/amqp.cmake
+++ b/qpid/cpp/src/amqp.cmake
@@ -23,15 +23,43 @@ include(FindPkgConfig)
pkg_check_modules(PROTON libqpid-proton)
+if (NOT PROTON_FOUND)
+ # if pkg-config is absent or fails to find proton then use
+ # PROTON_ROOT command line option or environment variable to locate
+ # local installed proton build.
+ if (NOT PROTON_ROOT)
+ set (PROTON_ROOT "$ENV{PROTON_ROOT}")
+ endif()
+ if (PROTON_ROOT)
+ find_package(proton PATHS ${PROTON_ROOT} NO_DEFAULT_PATH)
+
+ if (proton_FOUND EQUAL 1)
+ set(iFile "${PROTON_ROOT}/lib/proton.cmake/libqpid-proton.cmake")
+ if(EXISTS ${iFile})
+ include("${iFile}")
+ else()
+ message(FATAL_ERROR "PROTON_ROOT defined but file ${iFile} is missing")
+ endif()
+ else()
+ message(FATAL_ERROR "Proton package files not found in ${PROTON_ROOT}")
+ endif()
+ endif()
+endif()
+
set (amqp_default ${amqp_force})
-set (required_version 0.3)
+set (minimum_version 0.5)
+set (maximum_version 0.5)
if (PROTON_FOUND)
- if (PROTON_VERSION LESS ${required_version})
- message(STATUS "Qpid proton is too old, amqp 1.0 support not enabled")
- else (PROTON_VERSION LESS ${required_version})
- message(STATUS "Qpid proton found, amqp 1.0 support enabled")
- set (amqp_default ON)
- endif (PROTON_VERSION LESS ${required_version})
+ if (PROTON_VERSION LESS ${minimum_version})
+ message(STATUS "Qpid proton ${PROTON_VERSION} is too old, require ${minimum_version} - ${maximum_version}; amqp 1.0 support not enabled")
+ else (PROTON_VERSION LESS ${minimum_version})
+ if (PROTON_VERSION GREATER ${maximum_version})
+ message(STATUS "Qpid proton ${PROTON_VERSION} is too new, require ${minimum_version} - ${maximum_version}; amqp 1.0 support not enabled")
+ else (PROTON_VERSION GREATER ${maximum_version})
+ message(STATUS "Qpid proton found, amqp 1.0 support enabled")
+ set (amqp_default ON)
+ endif (PROTON_VERSION GREATER ${maximum_version})
+ endif (PROTON_VERSION LESS ${minimum_version})
else (PROTON_FOUND)
message(STATUS "Qpid proton not found, amqp 1.0 support not enabled")
endif (PROTON_FOUND)
@@ -43,15 +71,6 @@ if (BUILD_AMQP)
message(FATAL_ERROR "Qpid proton not found, required for amqp 1.0 support")
endif (NOT PROTON_FOUND)
- foreach(f ${PROTON_CFLAGS})
- set (PROTON_COMPILE_FLAGS "${PROTON_COMPILE_FLAGS} ${f}")
- endforeach(f)
-
- foreach(f ${PROTON_LDFLAGS})
- set (PROTON_LINK_FLAGS "${PROTON_LINK_FLAGS} ${f}")
- endforeach(f)
-
-
set (amqp_SOURCES
qpid/broker/amqp/Authorise.h
qpid/broker/amqp/Authorise.cpp
@@ -103,18 +122,21 @@ if (BUILD_AMQP)
qpid/broker/amqp/Translation.h
qpid/broker/amqp/Translation.cpp
)
+
+ include_directories(${PROTON_INCLUDE_DIRS})
+ link_directories(${PROTON_LIBRARY_DIRS})
+
add_library (amqp MODULE ${amqp_SOURCES})
- target_link_libraries (amqp qpidbroker qpidcommon)
+ target_link_libraries (amqp qpidtypes qpidbroker qpidcommon ${PROTON_LIBRARIES} ${Boost_PROGRAM_OPTIONS_LIBRARY})
set_target_properties (amqp PROPERTIES
PREFIX ""
- COMPILE_FLAGS "${PROTON_COMPILE_FLAGS}"
- LINK_FLAGS "${PROTON_LINK_FLAGS}")
- set_target_properties (amqp PROPERTIES COMPILE_DEFINITIONS _IN_QPID_BROKER)
+ LINK_FLAGS "${CATCH_UNDEFINED}"
+ COMPILE_DEFINITIONS _IN_QPID_BROKER)
+
install (TARGETS amqp
DESTINATION ${QPIDD_MODULE_DIR}
COMPONENT ${QPID_COMPONENT_BROKER})
-
set (amqpc_SOURCES
qpid/messaging/amqp/AddressHelper.h
qpid/messaging/amqp/AddressHelper.cpp
@@ -142,11 +164,11 @@ if (BUILD_AMQP)
qpid/messaging/amqp/TcpTransport.cpp
)
add_library (amqpc MODULE ${amqpc_SOURCES})
- target_link_libraries (amqpc qpidclient qpidcommon)
+ target_link_libraries (amqpc qpidmessaging qpidtypes qpidclient qpidcommon ${PROTON_LIBRARIES})
set_target_properties (amqpc PROPERTIES
PREFIX ""
- COMPILE_FLAGS "${PROTON_COMPILE_FLAGS}"
- LINK_FLAGS "${PROTON_LINK_FLAGS}")
+ LINK_FLAGS "${CATCH_UNDEFINED}")
+
install (TARGETS amqpc
DESTINATION ${QPIDC_MODULE_DIR}
COMPONENT ${QPID_COMPONENT_CLIENT})
diff --git a/qpid/cpp/src/check-abi b/qpid/cpp/src/check-abi
new file mode 100755
index 0000000000..2b5d4eda68
--- /dev/null
+++ b/qpid/cpp/src/check-abi
@@ -0,0 +1,81 @@
+#! /bin/bash
+
+# Ask the compiler the implementation specific type for a standard typedeffed type
+# (int64_t, size_t etc.). Operates by test compiling and using the demangling ABI call.
+#
+# This works for gcc and clang on Unix.
+full_type_of () {
+ prog=$(mktemp)
+ trap "rm $prog" EXIT
+
+ ${CXX:-g++} -x c++ -o $prog - <<END-FILE
+#include <stdint.h>
+#include <stdlib.h>
+#include <cxxabi.h>
+#include <iostream>
+#include <typeinfo>
+
+int main() {
+ int status;
+ char* printable_type =
+ __cxxabiv1::__cxa_demangle(typeid($1).name(), 0, 0, &status);
+ if (printable_type) {
+ std::cout << printable_type;
+ } else {
+ std::cout << "$1";
+ }
+ ::free(printable_type);
+}
+END-FILE
+$prog
+}
+
+rc=0
+syms_desired=$(mktemp)
+syms_library=$(mktemp)
+syms_missing=$(mktemp)
+syms_extra=$(mktemp)
+
+trap 'rm $syms_desired $syms_library $syms_missing $syms_extra' EXIT
+
+CXX=$1
+export CXX
+
+# Extract exported symbols from library
+nm -DC --defined-only -f s $2 | cut -f1 -d'|' -s | sort -u > $syms_library
+
+# Process API syms (substitute in some typedefs etc.)
+sed $3 -e "
+ s/uint64_t/$(full_type_of uint64_t)/
+ s/uint32_t/unsigned int/
+ s/uint16_t/unsigned short/
+ s/uint8_t/unsigned char/
+ s/size_t/$(full_type_of size_t)/
+ s/int64_t/$(full_type_of int64_t)/
+ s/int32_t/int/
+ s/int16_t/short/
+ s/int8_t/signed char/
+ s/qpid::types::Variant::Map/std::map<std::string, qpid::types::Variant, std::less<std::string>, std::allocator<std::pair<std::string const, qpid::types::Variant> > >/
+ s/qpid::types::Variant::List/std::list<qpid::types::Variant, std::allocator<qpid::types::Variant> >/
+ /^\$/d
+ /^#.*\$/d
+" | sort -u > $syms_desired
+
+comm -23 $syms_desired $syms_library > $syms_missing
+comm -13 $syms_desired $syms_library > $syms_extra
+
+if [ -n "$(cat $syms_missing)" ] ; then
+ (echo "Not exported from library (should be)"
+ echo "====================================="
+ cat $syms_missing ) 1>&2
+ rc=1
+fi
+
+
+if [ -n "$(cat $syms_extra)" ]; then
+ (echo "Exported by library but not in spec"
+ echo "==================================="
+ cat $syms_extra ) 1>&2
+fi
+
+exit $rc
diff --git a/qpid/cpp/src/finddb.cmake b/qpid/cpp/src/finddb.cmake
index fad827cffe..2f2f94f469 100644
--- a/qpid/cpp/src/finddb.cmake
+++ b/qpid/cpp/src/finddb.cmake
@@ -22,31 +22,33 @@ if(UNIX)
# - Find BerkeleyDB
# Find the BerkeleyDB includes and library
# This module defines
-# DB_INCLUDE_DIR, where to find db.h, etc.
+# DB_CXX_INCLUDE_DIR, where to find db_cxx.h, etc.
# DB_LIBRARIES, the libraries needed to use BerkeleyDB.
# DB_FOUND, If false, do not try to use BerkeleyDB.
# also defined, but not for general use are
# DB_LIBRARY, where to find the BerkeleyDB library.
-FIND_PATH(DB_INCLUDE_DIR db.h
+FIND_PATH(DB_CXX_INCLUDE_DIR db_cxx.h
/usr/local/include/db4
+ /usr/local/include/libdb4
/usr/local/include
/usr/include/db4
+ /usr/include/libdb4
/usr/include
)
-SET(DB_NAMES ${DB_NAMES} db_cxx)
+SET(DB_NAMES ${DB_NAMES} db_cxx db_cxx-4)
FIND_LIBRARY(DB_LIBRARY
NAMES ${DB_NAMES}
PATHS /usr/lib /usr/local/lib
)
-IF (DB_LIBRARY AND DB_INCLUDE_DIR)
+IF (DB_LIBRARY AND DB_CXX_INCLUDE_DIR)
SET(DB_LIBRARIES ${DB_LIBRARY})
SET(DB_FOUND "YES")
-ELSE (DB_LIBRARY AND DB_INCLUDE_DIR)
+ELSE (DB_LIBRARY AND DB_CXX_INCLUDE_DIR)
UNSET( DB_FOUND )
-ENDIF (DB_LIBRARY AND DB_INCLUDE_DIR)
+ENDIF (DB_LIBRARY AND DB_CXX_INCLUDE_DIR)
IF (DB_FOUND)
@@ -60,15 +62,15 @@ ELSE (DB_FOUND)
ENDIF (DB_FOUND)
# Deprecated declarations.
-SET (NATIVE_DB_INCLUDE_PATH ${DB_INCLUDE_DIR} )
+SET (NATIVE_DB_INCLUDE_PATH ${DB_CXX_INCLUDE_DIR} )
GET_FILENAME_COMPONENT (NATIVE_DB_LIB_PATH ${DB_LIBRARY} PATH)
MARK_AS_ADVANCED(
DB_LIBRARY
- DB_INCLUDE_DIR
+ DB_CXX_INCLUDE_DIR
)
else(UNIX)
MESSAGE(STATUS "BerkeleyDB is ignored on non-Unix platforms")
UNSET( DB_FOUND )
-endif(UNIX) \ No newline at end of file
+endif(UNIX)
diff --git a/qpid/cpp/src/ha.mk b/qpid/cpp/src/ha.mk
deleted file mode 100644
index aa3a572286..0000000000
--- a/qpid/cpp/src/ha.mk
+++ /dev/null
@@ -1,72 +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.
-#
-#
-# HA plugin makefile fragment, to be included in Makefile.am
-#
-
-dmoduleexec_LTLIBRARIES += ha.la
-
-ha_la_SOURCES = \
- qpid/ha/AlternateExchangeSetter.h \
- qpid/ha/Backup.cpp \
- qpid/ha/Backup.h \
- qpid/ha/BackupConnectionExcluder.h \
- qpid/ha/BrokerInfo.cpp \
- qpid/ha/BrokerInfo.h \
- qpid/ha/BrokerReplicator.cpp \
- qpid/ha/BrokerReplicator.h \
- qpid/ha/ConnectionObserver.cpp \
- qpid/ha/ConnectionObserver.h \
- qpid/ha/FailoverExchange.cpp \
- qpid/ha/FailoverExchange.h \
- qpid/ha/HaBroker.cpp \
- qpid/ha/HaBroker.h \
- qpid/ha/HaPlugin.cpp \
- qpid/ha/hash.h \
- qpid/ha/IdSetter.h \
- qpid/ha/QueueSnapshot.h \
- qpid/ha/makeMessage.cpp \
- qpid/ha/makeMessage.h \
- qpid/ha/Membership.cpp \
- qpid/ha/Membership.h \
- qpid/ha/Primary.cpp \
- qpid/ha/Primary.h \
- qpid/ha/QueueGuard.cpp \
- qpid/ha/QueueGuard.h \
- qpid/ha/QueueReplicator.cpp \
- qpid/ha/QueueReplicator.h \
- qpid/ha/QueueSnapshot.h \
- qpid/ha/QueueSnapshots.h \
- qpid/ha/RemoteBackup.cpp \
- qpid/ha/RemoteBackup.h \
- qpid/ha/ReplicatingSubscription.cpp \
- qpid/ha/ReplicatingSubscription.h \
- qpid/ha/ReplicationTest.cpp \
- qpid/ha/ReplicationTest.h \
- qpid/ha/Role.h \
- qpid/ha/Settings.h \
- qpid/ha/StandAlone.h \
- qpid/ha/StatusCheck.cpp \
- qpid/ha/StatusCheck.h \
- qpid/ha/types.cpp \
- qpid/ha/types.h
-
-ha_la_LIBADD = libqpidbroker.la libqpidmessaging.la
-ha_la_LDFLAGS = $(PLUGINLDFLAGS)
-ha_la_CXXFLAGS = $(AM_CXXFLAGS) -D_IN_QPID_BROKER
diff --git a/qpid/cpp/src/legacystore.cmake b/qpid/cpp/src/legacystore.cmake
index 9d6876b8d6..1fdb51aa32 100644
--- a/qpid/cpp/src/legacystore.cmake
+++ b/qpid/cpp/src/legacystore.cmake
@@ -126,10 +126,10 @@ if (BUILD_LEGACYSTORE)
)
if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/db-inc.h)
- message(STATUS "Including BDB from ${DB_INCLUDE_DIR}/db_cxx.h")
+ message(STATUS "Including BDB from ${DB_CXX_INCLUDE_DIR}/db_cxx.h")
file(WRITE
${CMAKE_CURRENT_BINARY_DIR}/db-inc.h
- "#include <${DB_INCLUDE_DIR}/db_cxx.h>\n")
+ "#include <${DB_CXX_INCLUDE_DIR}/db_cxx.h>\n")
endif()
add_library (legacystore MODULE
diff --git a/qpid/cpp/src/legacystore.mk b/qpid/cpp/src/legacystore.mk
deleted file mode 100644
index 7dbfac8a28..0000000000
--- a/qpid/cpp/src/legacystore.mk
+++ /dev/null
@@ -1,110 +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.
-#
-#
-# Legacy store plugin makefile fragment, to be included in Makefile.am
-# NOTE: this fragment only includes legacystore sources in
-# the distribution, it does not build the store.
-#
-# To build the store use the cmake build system, see ../INSTALL
-#
-
-EXTRA_DIST += \
- qpid/legacystore/BindingDbt.cpp \
- qpid/legacystore/BindingDbt.h \
- qpid/legacystore/BufferValue.cpp \
- qpid/legacystore/BufferValue.h \
- qpid/legacystore/Cursor.h \
- qpid/legacystore/DataTokenImpl.cpp \
- qpid/legacystore/DataTokenImpl.h \
- qpid/legacystore/IdDbt.cpp \
- qpid/legacystore/IdDbt.h \
- qpid/legacystore/IdSequence.cpp \
- qpid/legacystore/IdSequence.h \
- qpid/legacystore/JournalImpl.cpp \
- qpid/legacystore/JournalImpl.h \
- qpid/legacystore/MessageStoreImpl.cpp \
- qpid/legacystore/MessageStoreImpl.h \
- qpid/legacystore/PreparedTransaction.cpp \
- qpid/legacystore/PreparedTransaction.h \
- qpid/legacystore/StoreException.h \
- qpid/legacystore/StorePlugin.cpp \
- qpid/legacystore/TxnCtxt.cpp \
- qpid/legacystore/TxnCtxt.h \
- qpid/legacystore/jrnl/aio.cpp \
- qpid/legacystore/jrnl/aio.h \
- qpid/legacystore/jrnl/aio_callback.h \
- qpid/legacystore/jrnl/cvar.cpp \
- qpid/legacystore/jrnl/cvar.h \
- qpid/legacystore/jrnl/data_tok.cpp \
- qpid/legacystore/jrnl/data_tok.h \
- qpid/legacystore/jrnl/deq_hdr.h \
- qpid/legacystore/jrnl/deq_rec.cpp \
- qpid/legacystore/jrnl/deq_rec.h \
- qpid/legacystore/jrnl/enq_hdr.h \
- qpid/legacystore/jrnl/enq_map.cpp \
- qpid/legacystore/jrnl/enq_map.h \
- qpid/legacystore/jrnl/enq_rec.cpp \
- qpid/legacystore/jrnl/enq_rec.h \
- qpid/legacystore/jrnl/enums.h \
- qpid/legacystore/jrnl/fcntl.cpp \
- qpid/legacystore/jrnl/fcntl.h \
- qpid/legacystore/jrnl/file_hdr.h \
- qpid/legacystore/jrnl/jcfg.h \
- qpid/legacystore/jrnl/jcntl.cpp \
- qpid/legacystore/jrnl/jcntl.h \
- qpid/legacystore/jrnl/jdir.cpp \
- qpid/legacystore/jrnl/jdir.h \
- qpid/legacystore/jrnl/jerrno.cpp \
- qpid/legacystore/jrnl/jerrno.h \
- qpid/legacystore/jrnl/jexception.cpp \
- qpid/legacystore/jrnl/jexception.h \
- qpid/legacystore/jrnl/jinf.cpp \
- qpid/legacystore/jrnl/jinf.h \
- qpid/legacystore/jrnl/jrec.cpp \
- qpid/legacystore/jrnl/jrec.h \
- qpid/legacystore/jrnl/lp_map.cpp \
- qpid/legacystore/jrnl/lp_map.h \
- qpid/legacystore/jrnl/lpmgr.cpp \
- qpid/legacystore/jrnl/lpmgr.h \
- qpid/legacystore/jrnl/pmgr.cpp \
- qpid/legacystore/jrnl/pmgr.h \
- qpid/legacystore/jrnl/rcvdat.h \
- qpid/legacystore/jrnl/rec_hdr.h \
- qpid/legacystore/jrnl/rec_tail.h \
- qpid/legacystore/jrnl/rfc.cpp \
- qpid/legacystore/jrnl/rfc.h \
- qpid/legacystore/jrnl/rmgr.cpp \
- qpid/legacystore/jrnl/rmgr.h \
- qpid/legacystore/jrnl/rrfc.cpp \
- qpid/legacystore/jrnl/rrfc.h \
- qpid/legacystore/jrnl/slock.cpp \
- qpid/legacystore/jrnl/slock.h \
- qpid/legacystore/jrnl/smutex.cpp \
- qpid/legacystore/jrnl/smutex.h \
- qpid/legacystore/jrnl/time_ns.cpp \
- qpid/legacystore/jrnl/time_ns.h \
- qpid/legacystore/jrnl/txn_hdr.h \
- qpid/legacystore/jrnl/txn_map.cpp \
- qpid/legacystore/jrnl/txn_map.h \
- qpid/legacystore/jrnl/txn_rec.cpp \
- qpid/legacystore/jrnl/txn_rec.h \
- qpid/legacystore/jrnl/wmgr.cpp \
- qpid/legacystore/jrnl/wmgr.h \
- qpid/legacystore/jrnl/wrfc.cpp \
- qpid/legacystore/jrnl/wrfc.h
diff --git a/qpid/cpp/src/libqpidmessaging-api-symbols.txt b/qpid/cpp/src/libqpidmessaging-api-symbols.txt
new file mode 100644
index 0000000000..dc889afaed
--- /dev/null
+++ b/qpid/cpp/src/libqpidmessaging-api-symbols.txt
@@ -0,0 +1,214 @@
+# Address
+qpid::messaging::Address::Address()
+qpid::messaging::Address::Address(std::string const&)
+qpid::messaging::Address::Address(std::string const&, std::string const&, qpid::types::Variant::Map const&, std::string const&)
+qpid::messaging::Address::Address(qpid::messaging::Address const&)
+qpid::messaging::Address::~Address()
+qpid::messaging::Address::operator=(qpid::messaging::Address const&)
+qpid::messaging::Address::getName() const
+qpid::messaging::Address::setName(std::string const&)
+qpid::messaging::Address::getSubject() const
+qpid::messaging::Address::setSubject(std::string const&)
+qpid::messaging::Address::getOptions() const
+qpid::messaging::Address::getOptions()
+qpid::messaging::Address::setOptions(qpid::types::Variant::Map const&)
+qpid::messaging::Address::getType() const
+qpid::messaging::Address::setType(std::string const&)
+qpid::messaging::Address::str() const
+qpid::messaging::Address::operator bool() const
+qpid::messaging::Address::operator!() const
+
+qpid::messaging::operator<<(std::ostream&, qpid::messaging::Address const&)
+
+# Connection
+qpid::messaging::Connection::Connection(qpid::messaging::ConnectionImpl*)
+qpid::messaging::Connection::Connection(qpid::messaging::Connection const&)
+qpid::messaging::Connection::Connection()
+qpid::messaging::Connection::Connection(std::string const&, qpid::types::Variant::Map const&)
+qpid::messaging::Connection::Connection(std::string const&, std::string const&)
+qpid::messaging::Connection::~Connection()
+qpid::messaging::Connection::operator=(qpid::messaging::Connection const&)
+qpid::messaging::Connection::setOption(std::string const&, qpid::types::Variant const&)
+qpid::messaging::Connection::open()
+qpid::messaging::Connection::isOpen()
+qpid::messaging::Connection::isOpen() const
+qpid::messaging::Connection::close()
+qpid::messaging::Connection::createTransactionalSession(std::string const&)
+qpid::messaging::Connection::createSession(std::string const&)
+qpid::messaging::Connection::getSession(std::string const&) const
+qpid::messaging::Connection::getAuthenticatedUsername()
+
+# Duration
+qpid::messaging::Duration::Duration(uint64_t)
+qpid::messaging::Duration::getMilliseconds() const
+qpid::messaging::Duration::FOREVER
+qpid::messaging::Duration::IMMEDIATE
+qpid::messaging::Duration::SECOND
+qpid::messaging::Duration::MINUTE
+
+qpid::messaging::operator*(qpid::messaging::Duration const&, uint64_t)
+qpid::messaging::operator*(uint64_t, qpid::messaging::Duration const&)
+qpid::messaging::operator==(qpid::messaging::Duration const&, qpid::messaging::Duration const&)
+qpid::messaging::operator!=(qpid::messaging::Duration const&, qpid::messaging::Duration const&)
+
+# FailoverUpdates (this is a very strange class - more like a property of a Connection)
+qpid::messaging::FailoverUpdates::FailoverUpdates(qpid::messaging::Connection&)
+qpid::messaging::FailoverUpdates::~FailoverUpdates()
+
+# Message
+qpid::messaging::Message::Message(std::string const&)
+qpid::messaging::Message::Message(char const*, size_t)
+qpid::messaging::Message::Message(qpid::messaging::Message const&)
+qpid::messaging::Message::Message(qpid::types::Variant&)
+qpid::messaging::Message::~Message()
+qpid::messaging::Message::operator=(qpid::messaging::Message const&)
+qpid::messaging::Message::setReplyTo(qpid::messaging::Address const&)
+qpid::messaging::Message::getReplyTo() const
+qpid::messaging::Message::setSubject(std::string const&)
+qpid::messaging::Message::getSubject() const
+qpid::messaging::Message::setContentType(std::string const&)
+qpid::messaging::Message::getContentType() const
+qpid::messaging::Message::setMessageId(std::string const&)
+qpid::messaging::Message::getMessageId() const
+qpid::messaging::Message::setUserId(std::string const&)
+qpid::messaging::Message::getUserId() const
+qpid::messaging::Message::setCorrelationId(std::string const&)
+qpid::messaging::Message::getCorrelationId() const
+qpid::messaging::Message::setPriority(uint8_t)
+qpid::messaging::Message::getPriority() const
+qpid::messaging::Message::setTtl(qpid::messaging::Duration)
+qpid::messaging::Message::getTtl() const
+qpid::messaging::Message::setDurable(bool)
+qpid::messaging::Message::getDurable() const
+qpid::messaging::Message::getRedelivered() const
+qpid::messaging::Message::setRedelivered(bool)
+qpid::messaging::Message::getProperties() const
+qpid::messaging::Message::getProperties()
+qpid::messaging::Message::setContent(std::string const&)
+qpid::messaging::Message::setContent(char const*, size_t)
+qpid::messaging::Message::getContent() const
+qpid::messaging::Message::setContentBytes(std::string const&)
+qpid::messaging::Message::getContentBytes() const
+qpid::messaging::Message::setContentObject(qpid::types::Variant const&)
+qpid::messaging::Message::getContentObject()
+qpid::messaging::Message::getContentObject() const
+qpid::messaging::Message::getContentPtr() const
+qpid::messaging::Message::getContentSize() const
+qpid::messaging::Message::setProperty(std::string const&, qpid::types::Variant const&)
+
+# Receiver
+qpid::messaging::Receiver::Receiver(qpid::messaging::ReceiverImpl*)
+qpid::messaging::Receiver::Receiver(qpid::messaging::Receiver const&)
+qpid::messaging::Receiver::~Receiver()
+qpid::messaging::Receiver::operator=(qpid::messaging::Receiver const&)
+qpid::messaging::Receiver::get(qpid::messaging::Message&, qpid::messaging::Duration)
+qpid::messaging::Receiver::get(qpid::messaging::Duration)
+qpid::messaging::Receiver::fetch(qpid::messaging::Message&, qpid::messaging::Duration)
+qpid::messaging::Receiver::fetch(qpid::messaging::Duration)
+qpid::messaging::Receiver::setCapacity(uint32_t)
+qpid::messaging::Receiver::getCapacity()
+qpid::messaging::Receiver::getAvailable()
+qpid::messaging::Receiver::getUnsettled()
+qpid::messaging::Receiver::close()
+qpid::messaging::Receiver::isClosed() const
+qpid::messaging::Receiver::getName() const
+qpid::messaging::Receiver::getSession() const
+qpid::messaging::Receiver::getAddress() const
+
+# Sender
+qpid::messaging::Sender::Sender(qpid::messaging::SenderImpl*)
+qpid::messaging::Sender::Sender(qpid::messaging::Sender const&)
+qpid::messaging::Sender::~Sender()
+qpid::messaging::Sender::operator=(qpid::messaging::Sender const&)
+qpid::messaging::Sender::send(qpid::messaging::Message const&, bool)
+qpid::messaging::Sender::close()
+qpid::messaging::Sender::setCapacity(uint32_t)
+qpid::messaging::Sender::getCapacity()
+qpid::messaging::Sender::getUnsettled()
+qpid::messaging::Sender::getAvailable()
+qpid::messaging::Sender::getName() const
+qpid::messaging::Sender::getSession() const
+qpid::messaging::Sender::getAddress() const
+
+# Session
+qpid::messaging::Session::Session(qpid::messaging::SessionImpl*)
+qpid::messaging::Session::Session(qpid::messaging::Session const&)
+qpid::messaging::Session::~Session()
+qpid::messaging::Session::operator=(qpid::messaging::Session const&)
+qpid::messaging::Session::close()
+qpid::messaging::Session::commit()
+qpid::messaging::Session::rollback()
+qpid::messaging::Session::acknowledge(bool)
+qpid::messaging::Session::acknowledge(qpid::messaging::Message&, bool)
+qpid::messaging::Session::acknowledgeUpTo(qpid::messaging::Message&, bool)
+qpid::messaging::Session::reject(qpid::messaging::Message&)
+qpid::messaging::Session::release(qpid::messaging::Message&)
+qpid::messaging::Session::sync(bool)
+qpid::messaging::Session::getReceivable()
+qpid::messaging::Session::getUnsettledAcks()
+qpid::messaging::Session::nextReceiver(qpid::messaging::Receiver&, qpid::messaging::Duration)
+qpid::messaging::Session::nextReceiver(qpid::messaging::Duration)
+qpid::messaging::Session::createSender(qpid::messaging::Address const&)
+qpid::messaging::Session::createSender(std::string const&)
+qpid::messaging::Session::createReceiver(qpid::messaging::Address const&)
+qpid::messaging::Session::createReceiver(std::string const&)
+qpid::messaging::Session::getSender(std::string const&) const
+qpid::messaging::Session::getReceiver(std::string const&) const
+qpid::messaging::Session::getConnection() const
+qpid::messaging::Session::hasError()
+qpid::messaging::Session::checkError()
+
+# Codec routines (properly superceded now by Messsage::setContentObject()
+qpid::messaging::decode(qpid::messaging::Message const&, qpid::types::Variant::Map&, std::string const&)
+qpid::messaging::decode(qpid::messaging::Message const&, qpid::types::Variant::List&, std::string const&)
+qpid::messaging::encode(qpid::types::Variant::Map const&, qpid::messaging::Message&, std::string const&)
+qpid::messaging::encode(qpid::types::Variant::List const&, qpid::messaging::Message&, std::string const&)
+
+# Exceptions
+qpid::messaging::EncodingException::EncodingException(std::string const&)
+qpid::messaging::EncodingException::~EncodingException()
+
+qpid::messaging::MessagingException::MessagingException(std::string const&)
+qpid::messaging::MessagingException::~MessagingException()
+
+qpid::messaging::InvalidOptionString::InvalidOptionString(std::string const&)
+qpid::messaging::InvalidOptionString::~InvalidOptionString()
+qpid::messaging::KeyError::KeyError(std::string const&)
+qpid::messaging::KeyError::~KeyError()
+qpid::messaging::LinkError::LinkError(std::string const&)
+qpid::messaging::LinkError::~LinkError()
+qpid::messaging::AddressError::AddressError(std::string const&)
+qpid::messaging::AddressError::~AddressError()
+qpid::messaging::ResolutionError::ResolutionError(std::string const&)
+qpid::messaging::ResolutionError::~ResolutionError()
+qpid::messaging::AssertionFailed::AssertionFailed(std::string const&)
+qpid::messaging::AssertionFailed::~AssertionFailed()
+qpid::messaging::NotFound::NotFound(std::string const&)
+qpid::messaging::NotFound::~NotFound()
+qpid::messaging::MalformedAddress::MalformedAddress(std::string const&)
+qpid::messaging::MalformedAddress::~MalformedAddress()
+qpid::messaging::ReceiverError::ReceiverError(std::string const&)
+qpid::messaging::ReceiverError::~ReceiverError()
+qpid::messaging::FetchError::FetchError(std::string const&)
+qpid::messaging::FetchError::~FetchError()
+qpid::messaging::NoMessageAvailable::NoMessageAvailable()
+qpid::messaging::NoMessageAvailable::~NoMessageAvailable()
+qpid::messaging::SenderError::SenderError(std::string const&)
+qpid::messaging::SenderError::~SenderError()
+qpid::messaging::SendError::SendError(std::string const&)
+qpid::messaging::SendError::~SendError()
+qpid::messaging::TargetCapacityExceeded::TargetCapacityExceeded(std::string const&)
+qpid::messaging::TargetCapacityExceeded::~TargetCapacityExceeded()
+qpid::messaging::SessionError::SessionError(std::string const&)
+qpid::messaging::SessionError::~SessionError()
+qpid::messaging::TransactionError::TransactionError(std::string const&)
+qpid::messaging::TransactionError::~TransactionError()
+qpid::messaging::TransactionAborted::TransactionAborted(std::string const&)
+qpid::messaging::TransactionAborted::~TransactionAborted()
+qpid::messaging::UnauthorizedAccess::UnauthorizedAccess(std::string const&)
+qpid::messaging::UnauthorizedAccess::~UnauthorizedAccess()
+qpid::messaging::ConnectionError::ConnectionError(std::string const&)
+qpid::messaging::ConnectionError::~ConnectionError()
+qpid::messaging::TransportFailure::TransportFailure(std::string const&)
+qpid::messaging::TransportFailure::~TransportFailure()
+
diff --git a/qpid/cpp/src/libqpidtypes-api-symbols.txt b/qpid/cpp/src/libqpidtypes-api-symbols.txt
new file mode 100644
index 0000000000..5703ed7fb8
--- /dev/null
+++ b/qpid/cpp/src/libqpidtypes-api-symbols.txt
@@ -0,0 +1,122 @@
+# Uuid
+qpid::types::Uuid::SIZE
+qpid::types::Uuid::Uuid(bool)
+qpid::types::Uuid::Uuid(qpid::types::Uuid const&)
+qpid::types::Uuid::operator=(qpid::types::Uuid const&)
+qpid::types::Uuid::Uuid(unsigned char const*)
+qpid::types::Uuid::Uuid(char const*)
+qpid::types::Uuid::generate()
+qpid::types::Uuid::clear()
+qpid::types::Uuid::isNull() const
+qpid::types::Uuid::operator bool() const
+qpid::types::Uuid::operator!() const
+qpid::types::Uuid::str() const
+qpid::types::Uuid::size() const
+qpid::types::Uuid::data() const
+qpid::types::Uuid::hash() const
+
+qpid::types::operator==(qpid::types::Uuid const&, qpid::types::Uuid const&)
+qpid::types::operator!=(qpid::types::Uuid const&, qpid::types::Uuid const&)
+qpid::types::operator<(qpid::types::Uuid const&, qpid::types::Uuid const&)
+qpid::types::operator>(qpid::types::Uuid const&, qpid::types::Uuid const&)
+qpid::types::operator<=(qpid::types::Uuid const&, qpid::types::Uuid const&)
+qpid::types::operator>=(qpid::types::Uuid const&, qpid::types::Uuid const&)
+qpid::types::operator<<(std::ostream&, qpid::types::Uuid)
+qpid::types::operator>>(std::istream&, qpid::types::Uuid&)
+
+# VariantType
+qpid::types::getTypeName(qpid::types::VariantType)
+qpid::types::isIntegerType(qpid::types::VariantType)
+
+# Variant
+qpid::types::Variant::Variant()
+qpid::types::Variant::Variant(bool)
+qpid::types::Variant::Variant(uint8_t)
+qpid::types::Variant::Variant(uint16_t)
+qpid::types::Variant::Variant(uint32_t)
+qpid::types::Variant::Variant(uint64_t)
+qpid::types::Variant::Variant(int8_t)
+qpid::types::Variant::Variant(int16_t)
+qpid::types::Variant::Variant(int32_t)
+qpid::types::Variant::Variant(int64_t)
+qpid::types::Variant::Variant(float)
+qpid::types::Variant::Variant(double)
+qpid::types::Variant::Variant(std::string const&)
+qpid::types::Variant::Variant(char const*)
+qpid::types::Variant::Variant(qpid::types::Variant::Map const&)
+qpid::types::Variant::Variant(qpid::types::Variant::List const&)
+qpid::types::Variant::Variant(qpid::types::Variant const&)
+qpid::types::Variant::Variant(qpid::types::Uuid const&)
+qpid::types::Variant::~Variant()
+qpid::types::Variant::getType() const
+qpid::types::Variant::isVoid() const
+qpid::types::Variant::operator=(bool)
+qpid::types::Variant::operator=(uint8_t)
+qpid::types::Variant::operator=(uint16_t)
+qpid::types::Variant::operator=(uint32_t)
+qpid::types::Variant::operator=(uint64_t)
+qpid::types::Variant::operator=(int8_t)
+qpid::types::Variant::operator=(int16_t)
+qpid::types::Variant::operator=(int32_t)
+qpid::types::Variant::operator=(int64_t)
+qpid::types::Variant::operator=(float)
+qpid::types::Variant::operator=(double)
+qpid::types::Variant::operator=(std::string const&)
+qpid::types::Variant::operator=(char const*)
+qpid::types::Variant::operator=(qpid::types::Variant::Map const&)
+qpid::types::Variant::operator=(qpid::types::Variant::List const&)
+qpid::types::Variant::operator=(qpid::types::Variant const&)
+qpid::types::Variant::operator=(qpid::types::Uuid const&)
+qpid::types::Variant::parse(std::string const&)
+qpid::types::Variant::asBool() const
+qpid::types::Variant::asUint8() const
+qpid::types::Variant::asUint16() const
+qpid::types::Variant::asUint32() const
+qpid::types::Variant::asUint64() const
+qpid::types::Variant::asInt8() const
+qpid::types::Variant::asInt16() const
+qpid::types::Variant::asInt32() const
+qpid::types::Variant::asInt64() const
+qpid::types::Variant::asFloat() const
+qpid::types::Variant::asDouble() const
+qpid::types::Variant::asString() const
+qpid::types::Variant::asUuid() const
+qpid::types::Variant::asMap() const
+qpid::types::Variant::asMap()
+qpid::types::Variant::asList() const
+qpid::types::Variant::asList()
+qpid::types::Variant::getString() const
+qpid::types::Variant::getString()
+qpid::types::Variant::setEncoding(std::string const&)
+qpid::types::Variant::getEncoding() const
+qpid::types::Variant::operator bool() const
+qpid::types::Variant::operator uint8_t() const
+qpid::types::Variant::operator uint16_t() const
+qpid::types::Variant::operator uint32_t() const
+qpid::types::Variant::operator uint64_t() const
+qpid::types::Variant::operator int8_t() const
+qpid::types::Variant::operator int16_t() const
+qpid::types::Variant::operator int32_t() const
+qpid::types::Variant::operator int64_t() const
+qpid::types::Variant::operator float() const
+qpid::types::Variant::operator double() const
+qpid::types::Variant::operator std::string() const
+qpid::types::Variant::operator qpid::types::Uuid() const
+qpid::types::Variant::isEqualTo(qpid::types::Variant const&) const
+qpid::types::Variant::reset()
+
+qpid::types::operator<<(std::ostream&, qpid::types::Variant const&)
+qpid::types::operator<<(std::ostream&, qpid::types::Variant::Map const&)
+qpid::types::operator<<(std::ostream&, qpid::types::Variant::List const&)
+qpid::types::operator==(qpid::types::Variant const&, qpid::types::Variant const&)
+qpid::types::operator!=(qpid::types::Variant const&, qpid::types::Variant const&)
+
+# Root of qpid::types Exception hierarchy
+qpid::types::Exception::Exception(std::string const&)
+qpid::types::Exception::~Exception()
+qpid::types::Exception::what() const
+
+qpid::types::InvalidConversion::InvalidConversion(std::string const&)
+qpid::types::InvalidConversion::~InvalidConversion()
+
+
diff --git a/qpid/cpp/src/prof b/qpid/cpp/src/prof
index acfbaff2d4..6276ff620a 100755
--- a/qpid/cpp/src/prof
+++ b/qpid/cpp/src/prof
@@ -32,8 +32,8 @@ opcontrol --start
opcontrol --stop
opcontrol --dump
opcontrol --shutdown
-opreport -l ./.libs/lt-qpidd > stats.txt
-opannotate --source --output-dir=qpidd-prof ./.libs/lt-qpidd
+opreport -l ./qpidd > stats.txt
+opannotate --source --output-dir=qpidd-prof ./qpidd
# clear the relusts
#opcontrol --reset
diff --git a/qpid/cpp/src/qmf.mk b/qpid/cpp/src/qmf.mk
deleted file mode 100644
index 6a4bce4087..0000000000
--- a/qpid/cpp/src/qmf.mk
+++ /dev/null
@@ -1,177 +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.
-#
-
-#
-# qmf library makefile fragment, to be included in Makefile.am
-#
-lib_LTLIBRARIES += \
- libqmf.la \
- libqmfengine.la \
- libqmf2.la
-
-#
-# Public headers for the QMF API
-#
-QMF_API = \
- ../include/qpid/agent/ManagementAgent.h \
- ../include/qpid/agent/QmfAgentImportExport.h \
- ../include/qmf/BrokerImportExport.h
-
-#
-# Public headers for the QMF2 API
-#
-QMF2_API = \
- ../include/qmf/AgentEvent.h \
- ../include/qmf/Agent.h \
- ../include/qmf/AgentSession.h \
- ../include/qmf/ConsoleEvent.h \
- ../include/qmf/ConsoleSession.h \
- ../include/qmf/DataAddr.h \
- ../include/qmf/Data.h \
- ../include/qmf/posix/EventNotifier.h \
- ../include/qmf/exceptions.h \
- ../include/qmf/Handle.h \
- ../include/qmf/ImportExport.h \
- ../include/qmf/Query.h \
- ../include/qmf/Schema.h \
- ../include/qmf/SchemaId.h \
- ../include/qmf/SchemaMethod.h \
- ../include/qmf/SchemaProperty.h \
- ../include/qmf/SchemaTypes.h \
- ../include/qmf/Subscription.h
-
-
-#
-# Public headers for the QMF Engine API
-#
-QMF_ENGINE_API = \
- ../include/qmf/engine/Agent.h \
- ../include/qmf/engine/ConnectionSettings.h \
- ../include/qmf/engine/Console.h \
- ../include/qmf/engine/Event.h \
- ../include/qmf/engine/Message.h \
- ../include/qmf/engine/Object.h \
- ../include/qmf/engine/ObjectId.h \
- ../include/qmf/engine/QmfEngineImportExport.h \
- ../include/qmf/engine/Query.h \
- ../include/qmf/engine/ResilientConnection.h \
- ../include/qmf/engine/Schema.h \
- ../include/qmf/engine/Typecode.h \
- ../include/qmf/engine/Value.h
-
-# Public header files
-nobase_include_HEADERS += \
- $(QMF_API) \
- $(QMF_ENGINE_API) \
- $(QMF2_API)
-
-libqmf_la_SOURCES = \
- $(QMF_API) \
- qpid/agent/ManagementAgentImpl.cpp \
- qpid/agent/ManagementAgentImpl.h
-
-libqmf2_la_SOURCES = \
- $(QMF2_API) \
- qmf/agentCapability.h \
- qmf/Agent.cpp \
- qmf/AgentEvent.cpp \
- qmf/AgentEventImpl.h \
- qmf/AgentImpl.h \
- qmf/AgentSession.cpp \
- qmf/AgentSessionImpl.h \
- qmf/AgentSubscription.cpp \
- qmf/AgentSubscription.h \
- qmf/ConsoleEvent.cpp \
- qmf/ConsoleEventImpl.h \
- qmf/ConsoleSession.cpp \
- qmf/ConsoleSessionImpl.h \
- qmf/constants.cpp \
- qmf/constants.h \
- qmf/DataAddr.cpp \
- qmf/DataAddrImpl.h \
- qmf/Data.cpp \
- qmf/DataImpl.h \
- qmf/EventNotifierImpl.cpp \
- qmf/EventNotifierImpl.h \
- qmf/exceptions.cpp \
- qmf/Expression.cpp \
- qmf/Expression.h \
- qmf/Hash.cpp \
- qmf/Hash.h \
- qmf/PosixEventNotifier.cpp \
- qmf/PosixEventNotifierImpl.cpp \
- qmf/PosixEventNotifierImpl.h \
- qmf/PrivateImplRef.h \
- qmf/Query.cpp \
- qmf/QueryImpl.h \
- qmf/SchemaCache.cpp \
- qmf/SchemaCache.h \
- qmf/Schema.cpp \
- qmf/SchemaId.cpp \
- qmf/SchemaIdImpl.h \
- qmf/SchemaImpl.h \
- qmf/SchemaMethod.cpp \
- qmf/SchemaMethodImpl.h \
- qmf/SchemaProperty.cpp \
- qmf/SchemaPropertyImpl.h \
- qmf/Subscription.cpp \
- qmf/SubscriptionImpl.h
-
-libqmfengine_la_SOURCES = \
- $(QMF_ENGINE_API) \
- qmf/engine/Agent.cpp \
- qmf/engine/BrokerProxyImpl.cpp \
- qmf/engine/BrokerProxyImpl.h \
- qmf/engine/ConnectionSettingsImpl.cpp \
- qmf/engine/ConnectionSettingsImpl.h \
- qmf/engine/ConsoleImpl.cpp \
- qmf/engine/ConsoleImpl.h \
- qmf/engine/EventImpl.cpp \
- qmf/engine/EventImpl.h \
- qmf/engine/MessageImpl.cpp \
- qmf/engine/MessageImpl.h \
- qmf/engine/ObjectIdImpl.cpp \
- qmf/engine/ObjectIdImpl.h \
- qmf/engine/ObjectImpl.cpp \
- qmf/engine/ObjectImpl.h \
- qmf/engine/Protocol.cpp \
- qmf/engine/Protocol.h \
- qmf/engine/QueryImpl.cpp \
- qmf/engine/QueryImpl.h \
- qmf/engine/ResilientConnection.cpp \
- qmf/engine/SequenceManager.cpp \
- qmf/engine/SequenceManager.h \
- qmf/engine/SchemaImpl.cpp \
- qmf/engine/SchemaImpl.h \
- qmf/engine/ValueImpl.cpp \
- qmf/engine/ValueImpl.h
-
-libqmf_la_LIBADD = libqmfengine.la
-libqmf2_la_LIBADD = libqpidmessaging.la libqpidtypes.la
-libqmfengine_la_LIBADD = libqpidclient.la
-
-QMF_VERSION_INFO = 1:0:0
-QMF2_VERSION_INFO = 1:0:0
-QMFENGINE_VERSION_INFO = 1:1:0
-
-libqmf_la_LDFLAGS = -version-info $(QMF_VERSION_INFO)
-libqmf2_la_LDFLAGS = -version-info $(QMF2_VERSION_INFO)
-libqmfengine_la_LDFLAGS = -version-info $(QMFENGINE_VERSION_INFO)
-
-pkgconfig_DATA += qmf2.pc
diff --git a/qpid/cpp/src/qmf/engine/Agent.cpp b/qpid/cpp/src/qmf/engine/Agent.cpp
deleted file mode 100644
index 1f08dded94..0000000000
--- a/qpid/cpp/src/qmf/engine/Agent.cpp
+++ /dev/null
@@ -1,915 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/Agent.h"
-#include "qmf/engine/MessageImpl.h"
-#include "qmf/engine/SchemaImpl.h"
-#include "qmf/engine/Typecode.h"
-#include "qmf/engine/EventImpl.h"
-#include "qmf/engine/ObjectImpl.h"
-#include "qmf/engine/ObjectIdImpl.h"
-#include "qmf/engine/QueryImpl.h"
-#include "qmf/engine/ValueImpl.h"
-#include "qmf/engine/Protocol.h"
-#include <qpid/framing/Buffer.h>
-#include <qpid/framing/Uuid.h>
-#include <qpid/framing/FieldTable.h>
-#include <qpid/framing/FieldValue.h>
-#include <qpid/sys/Mutex.h>
-#include <qpid/log/Statement.h>
-#include <qpid/sys/Time.h>
-#include <string.h>
-#include <string>
-#include <deque>
-#include <map>
-#include <iostream>
-#include <fstream>
-#include <boost/shared_ptr.hpp>
-#include <boost/noncopyable.hpp>
-
-using namespace std;
-using namespace qmf::engine;
-using namespace qpid::framing;
-using namespace qpid::sys;
-
-namespace qmf {
-namespace engine {
-
- struct AgentEventImpl {
- typedef boost::shared_ptr<AgentEventImpl> Ptr;
- AgentEvent::EventKind kind;
- uint32_t sequence;
- string authUserId;
- string authToken;
- string name;
- Object* object;
- boost::shared_ptr<ObjectId> objectId;
- boost::shared_ptr<Query> query;
- boost::shared_ptr<Value> arguments;
- string exchange;
- string bindingKey;
- const SchemaObjectClass* objectClass;
-
- AgentEventImpl(AgentEvent::EventKind k) :
- kind(k), sequence(0), object(0), objectClass(0) {}
- ~AgentEventImpl() {}
- AgentEvent copy();
- };
-
- struct AgentQueryContext {
- typedef boost::shared_ptr<AgentQueryContext> Ptr;
- uint32_t sequence;
- string exchange;
- string key;
- const SchemaMethod* schemaMethod;
- AgentQueryContext() : schemaMethod(0) {}
- };
-
- class AgentImpl : public boost::noncopyable {
- public:
- AgentImpl(char* label, bool internalStore);
- ~AgentImpl();
-
- void setStoreDir(const char* path);
- void setTransferDir(const char* path);
- void handleRcvMessage(Message& message);
- bool getXmtMessage(Message& item) const;
- void popXmt();
- bool getEvent(AgentEvent& event) const;
- void popEvent();
- void newSession();
- void startProtocol();
- void heartbeat();
- void methodResponse(uint32_t sequence, uint32_t status, char* text, const Value& arguments);
- void queryResponse(uint32_t sequence, Object& object, bool prop, bool stat);
- void queryComplete(uint32_t sequence);
- void registerClass(SchemaObjectClass* cls);
- void registerClass(SchemaEventClass* cls);
- const ObjectId* addObject(Object& obj, uint64_t persistId);
- const ObjectId* allocObjectId(uint64_t persistId);
- const ObjectId* allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi);
- void raiseEvent(Event& event);
-
- private:
- mutable Mutex lock;
- Mutex addLock;
- string label;
- string queueName;
- string storeDir;
- string transferDir;
- bool internalStore;
- uint64_t nextTransientId;
- Uuid systemId;
- uint32_t requestedBrokerBank;
- uint32_t requestedAgentBank;
- uint32_t assignedBrokerBank;
- uint32_t assignedAgentBank;
- AgentAttachment attachment;
- uint16_t bootSequence;
- uint64_t nextObjectId;
- uint32_t nextContextNum;
- deque<AgentEventImpl::Ptr> eventQueue;
- deque<MessageImpl::Ptr> xmtQueue;
- map<uint32_t, AgentQueryContext::Ptr> contextMap;
- bool attachComplete;
-
- static const char* QMF_EXCHANGE;
- static const char* DIR_EXCHANGE;
- static const char* BROKER_KEY;
- static const uint32_t MERR_UNKNOWN_METHOD = 2;
- static const uint32_t MERR_UNKNOWN_PACKAGE = 8;
- static const uint32_t MERR_UNKNOWN_CLASS = 9;
- static const uint32_t MERR_INTERNAL_ERROR = 10;
-# define MA_BUFFER_SIZE 65536
- char outputBuffer[MA_BUFFER_SIZE];
-
- struct AgentClassKey {
- string name;
- uint8_t hash[16];
- AgentClassKey(const string& n, const uint8_t* h) : name(n) {
- memcpy(hash, h, 16);
- }
- AgentClassKey(Buffer& buffer) {
- buffer.getShortString(name);
- buffer.getBin128(hash);
- }
- string repr() {
- return name;
- }
- };
-
- struct AgentClassKeyComp {
- bool operator() (const AgentClassKey& lhs, const AgentClassKey& rhs) const
- {
- if (lhs.name != rhs.name)
- return lhs.name < rhs.name;
- else
- for (int i = 0; i < 16; i++)
- if (lhs.hash[i] != rhs.hash[i])
- return lhs.hash[i] < rhs.hash[i];
- return false;
- }
- };
-
- typedef map<AgentClassKey, SchemaObjectClass*, AgentClassKeyComp> ObjectClassMap;
- typedef map<AgentClassKey, SchemaEventClass*, AgentClassKeyComp> EventClassMap;
-
- struct ClassMaps {
- ObjectClassMap objectClasses;
- EventClassMap eventClasses;
- };
-
- map<string, ClassMaps> packages;
-
- AgentEventImpl::Ptr eventDeclareQueue(const string& queueName);
- AgentEventImpl::Ptr eventBind(const string& exchange, const string& queue, const string& key);
- AgentEventImpl::Ptr eventSetupComplete();
- AgentEventImpl::Ptr eventQuery(uint32_t num, const string& userId, const string& package, const string& cls,
- boost::shared_ptr<ObjectId> oid);
- AgentEventImpl::Ptr eventMethod(uint32_t num, const string& userId, const string& method,
- boost::shared_ptr<ObjectId> oid, boost::shared_ptr<Value> argMap,
- const SchemaObjectClass* objectClass);
- void sendBufferLH(Buffer& buf, const string& destination, const string& routingKey);
-
- void sendPackageIndicationLH(const string& packageName);
- void sendClassIndicationLH(ClassKind kind, const string& packageName, const AgentClassKey& key);
- void sendCommandCompleteLH(const string& exchange, const string& key, uint32_t seq,
- uint32_t code = 0, const string& text = "OK");
- void sendMethodErrorLH(uint32_t sequence, const string& key, uint32_t code, const string& text="");
- void handleAttachResponse(Buffer& inBuffer);
- void handlePackageRequest(Buffer& inBuffer);
- void handleClassQuery(Buffer& inBuffer);
- void handleSchemaRequest(Buffer& inBuffer, uint32_t sequence,
- const string& replyToExchange, const string& replyToKey);
- void handleGetQuery(Buffer& inBuffer, uint32_t sequence, const string& replyTo, const string& userId);
- void handleMethodRequest(Buffer& inBuffer, uint32_t sequence, const string& replyTo, const string& userId);
- void handleConsoleAddedIndication();
- };
-}
-}
-
-const char* AgentImpl::QMF_EXCHANGE = "qpid.management";
-const char* AgentImpl::DIR_EXCHANGE = "amq.direct";
-const char* AgentImpl::BROKER_KEY = "broker";
-
-#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());}
-
-AgentEvent AgentEventImpl::copy()
-{
- AgentEvent item;
-
- ::memset(&item, 0, sizeof(AgentEvent));
- item.kind = kind;
- item.sequence = sequence;
- item.object = object;
- item.objectId = objectId.get();
- item.query = query.get();
- item.arguments = arguments.get();
- item.objectClass = objectClass;
-
- STRING_REF(authUserId);
- STRING_REF(authToken);
- STRING_REF(name);
- STRING_REF(exchange);
- STRING_REF(bindingKey);
-
- return item;
-}
-
-AgentImpl::AgentImpl(char* _label, bool i) :
- label(_label), queueName("qmfa-"), internalStore(i), nextTransientId(1),
- requestedBrokerBank(0), requestedAgentBank(0),
- assignedBrokerBank(0), assignedAgentBank(0),
- bootSequence(1), nextObjectId(1), nextContextNum(1), attachComplete(false)
-{
- queueName += Uuid(true).str();
-}
-
-AgentImpl::~AgentImpl()
-{
-}
-
-void AgentImpl::setStoreDir(const char* path)
-{
- Mutex::ScopedLock _lock(lock);
- if (path)
- storeDir = path;
- else
- storeDir.clear();
-}
-
-void AgentImpl::setTransferDir(const char* path)
-{
- Mutex::ScopedLock _lock(lock);
- if (path)
- transferDir = path;
- else
- transferDir.clear();
-}
-
-void AgentImpl::handleRcvMessage(Message& message)
-{
- Buffer inBuffer(message.body, message.length);
- uint8_t opcode;
- uint32_t sequence;
- string replyToExchange(message.replyExchange ? message.replyExchange : "");
- string replyToKey(message.replyKey ? message.replyKey : "");
- string userId(message.userId ? message.userId : "");
-
- while (Protocol::checkHeader(inBuffer, &opcode, &sequence)) {
- if (opcode == Protocol::OP_ATTACH_RESPONSE) handleAttachResponse(inBuffer);
- else if (opcode == Protocol::OP_SCHEMA_REQUEST) handleSchemaRequest(inBuffer, sequence, replyToExchange, replyToKey);
- else if (opcode == Protocol::OP_CONSOLE_ADDED_INDICATION) handleConsoleAddedIndication();
- else if (opcode == Protocol::OP_GET_QUERY) handleGetQuery(inBuffer, sequence, replyToKey, userId);
- else if (opcode == Protocol::OP_METHOD_REQUEST) handleMethodRequest(inBuffer, sequence, replyToKey, userId);
- else {
- QPID_LOG(error, "AgentImpl::handleRcvMessage invalid opcode=" << opcode);
- break;
- }
- }
-}
-
-bool AgentImpl::getXmtMessage(Message& item) const
-{
- Mutex::ScopedLock _lock(lock);
- if (xmtQueue.empty())
- return false;
- item = xmtQueue.front()->copy();
- return true;
-}
-
-void AgentImpl::popXmt()
-{
- Mutex::ScopedLock _lock(lock);
- if (!xmtQueue.empty())
- xmtQueue.pop_front();
-}
-
-bool AgentImpl::getEvent(AgentEvent& event) const
-{
- Mutex::ScopedLock _lock(lock);
- if (eventQueue.empty())
- return false;
- event = eventQueue.front()->copy();
- return true;
-}
-
-void AgentImpl::popEvent()
-{
- Mutex::ScopedLock _lock(lock);
- if (!eventQueue.empty())
- eventQueue.pop_front();
-}
-
-void AgentImpl::newSession()
-{
- Mutex::ScopedLock _lock(lock);
- eventQueue.clear();
- xmtQueue.clear();
- eventQueue.push_back(eventDeclareQueue(queueName));
- eventQueue.push_back(eventBind("amq.direct", queueName, queueName));
- eventQueue.push_back(eventSetupComplete());
-}
-
-void AgentImpl::startProtocol()
-{
- Mutex::ScopedLock _lock(lock);
- char rawbuffer[512];
- Buffer buffer(rawbuffer, 512);
-
- Protocol::encodeHeader(buffer, Protocol::OP_ATTACH_REQUEST);
- buffer.putShortString(label);
- systemId.encode(buffer);
- buffer.putLong(requestedBrokerBank);
- buffer.putLong(requestedAgentBank);
- sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT AttachRequest: reqBroker=" << requestedBrokerBank <<
- " reqAgent=" << requestedAgentBank);
-}
-
-void AgentImpl::heartbeat()
-{
- Mutex::ScopedLock _lock(lock);
- Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
-
- Protocol::encodeHeader(buffer, Protocol::OP_HEARTBEAT_INDICATION);
- buffer.putLongLong(uint64_t(Duration(EPOCH, now())));
- stringstream key;
- key << "console.heartbeat." << assignedBrokerBank << "." << assignedAgentBank;
- sendBufferLH(buffer, QMF_EXCHANGE, key.str());
- QPID_LOG(trace, "SENT HeartbeatIndication");
-}
-
-void AgentImpl::methodResponse(uint32_t sequence, uint32_t status, char* text, const Value& argMap)
-{
- Mutex::ScopedLock _lock(lock);
- map<uint32_t, AgentQueryContext::Ptr>::iterator iter = contextMap.find(sequence);
- if (iter == contextMap.end())
- return;
- AgentQueryContext::Ptr context = iter->second;
- contextMap.erase(iter);
-
- char* buf(outputBuffer);
- uint32_t bufLen(114 + strlen(text)); // header(8) + status(4) + mstring(2 + size) + margin(100)
- bool allocated(false);
-
- if (status == 0) {
- for (vector<const SchemaArgument*>::const_iterator aIter = context->schemaMethod->impl->arguments.begin();
- aIter != context->schemaMethod->impl->arguments.end(); aIter++) {
- const SchemaArgument* schemaArg = *aIter;
- if (schemaArg->getDirection() == DIR_OUT || schemaArg->getDirection() == DIR_IN_OUT) {
- if (argMap.keyInMap(schemaArg->getName())) {
- const Value* val = argMap.byKey(schemaArg->getName());
- bufLen += val->impl->encodedSize();
- } else {
- Value val(schemaArg->getType());
- bufLen += val.impl->encodedSize();
- }
- }
- }
- }
-
- if (bufLen > MA_BUFFER_SIZE) {
- buf = (char*) malloc(bufLen);
- allocated = true;
- }
-
- Buffer buffer(buf, bufLen);
- Protocol::encodeHeader(buffer, Protocol::OP_METHOD_RESPONSE, context->sequence);
- buffer.putLong(status);
- buffer.putMediumString(text);
- if (status == 0) {
- for (vector<const SchemaArgument*>::const_iterator aIter = context->schemaMethod->impl->arguments.begin();
- aIter != context->schemaMethod->impl->arguments.end(); aIter++) {
- const SchemaArgument* schemaArg = *aIter;
- if (schemaArg->getDirection() == DIR_OUT || schemaArg->getDirection() == DIR_IN_OUT) {
- if (argMap.keyInMap(schemaArg->getName())) {
- const Value* val = argMap.byKey(schemaArg->getName());
- val->impl->encode(buffer);
- } else {
- Value val(schemaArg->getType());
- val.impl->encode(buffer);
- }
- }
- }
- }
- sendBufferLH(buffer, context->exchange, context->key);
- if (allocated)
- free(buf);
- QPID_LOG(trace, "SENT MethodResponse seq=" << context->sequence << " status=" << status << " text=" << text);
-}
-
-void AgentImpl::queryResponse(uint32_t sequence, Object& object, bool prop, bool stat)
-{
- Mutex::ScopedLock _lock(lock);
- map<uint32_t, AgentQueryContext::Ptr>::iterator iter = contextMap.find(sequence);
- if (iter == contextMap.end())
- return;
- AgentQueryContext::Ptr context = iter->second;
-
- Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
- Protocol::encodeHeader(buffer, Protocol::OP_OBJECT_INDICATION, context->sequence);
-
- object.impl->encodeSchemaKey(buffer);
- object.impl->encodeManagedObjectData(buffer);
- if (prop)
- object.impl->encodeProperties(buffer);
- if (stat)
- object.impl->encodeStatistics(buffer);
-
- sendBufferLH(buffer, context->exchange, context->key);
- QPID_LOG(trace, "SENT ContentIndication seq=" << context->sequence);
-}
-
-void AgentImpl::queryComplete(uint32_t sequence)
-{
- Mutex::ScopedLock _lock(lock);
- map<uint32_t, AgentQueryContext::Ptr>::iterator iter = contextMap.find(sequence);
- if (iter == contextMap.end())
- return;
-
- AgentQueryContext::Ptr context = iter->second;
- contextMap.erase(iter);
- sendCommandCompleteLH(context->exchange, context->key, context->sequence, 0, "OK");
-}
-
-void AgentImpl::registerClass(SchemaObjectClass* cls)
-{
- Mutex::ScopedLock _lock(lock);
- bool newPackage = false;
-
- map<string, ClassMaps>::iterator iter = packages.find(cls->getClassKey()->getPackageName());
- if (iter == packages.end()) {
- packages[cls->getClassKey()->getPackageName()] = ClassMaps();
- iter = packages.find(cls->getClassKey()->getPackageName());
- newPackage = true;
- }
-
- AgentClassKey key(cls->getClassKey()->getClassName(), cls->getClassKey()->getHash());
- iter->second.objectClasses[key] = cls;
-
- // Indicate this new schema if connected.
-
- if (attachComplete) {
-
- if (newPackage) {
- sendPackageIndicationLH(iter->first);
- }
- sendClassIndicationLH(CLASS_OBJECT, iter->first, key);
- }
-}
-
-void AgentImpl::registerClass(SchemaEventClass* cls)
-{
- Mutex::ScopedLock _lock(lock);
- bool newPackage = false;
-
- map<string, ClassMaps>::iterator iter = packages.find(cls->getClassKey()->getPackageName());
- if (iter == packages.end()) {
- packages[cls->getClassKey()->getPackageName()] = ClassMaps();
- iter = packages.find(cls->getClassKey()->getPackageName());
- newPackage = true;
- }
-
- AgentClassKey key(cls->getClassKey()->getClassName(), cls->getClassKey()->getHash());
- iter->second.eventClasses[key] = cls;
-
- // Indicate this new schema if connected.
-
- if (attachComplete) {
-
- if (newPackage) {
- sendPackageIndicationLH(iter->first);
- }
- sendClassIndicationLH(CLASS_EVENT, iter->first, key);
- }
-}
-
-const ObjectId* AgentImpl::addObject(Object&, uint64_t)
-{
- Mutex::ScopedLock _lock(lock);
- return 0;
-}
-
-const ObjectId* AgentImpl::allocObjectId(uint64_t persistId)
-{
- Mutex::ScopedLock _lock(lock);
- uint16_t sequence = persistId ? 0 : bootSequence;
- uint64_t objectNum = persistId ? persistId : nextObjectId++;
-
- ObjectId* oid = ObjectIdImpl::factory(&attachment, 0, sequence, objectNum);
- return oid;
-}
-
-const ObjectId* AgentImpl::allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi)
-{
- return allocObjectId(((uint64_t) persistIdHi) << 32 | (uint64_t) persistIdLo);
-}
-
-void AgentImpl::raiseEvent(Event& event)
-{
- Mutex::ScopedLock _lock(lock);
- Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
- Protocol::encodeHeader(buffer, Protocol::OP_EVENT_INDICATION);
-
- event.impl->encodeSchemaKey(buffer);
- buffer.putLongLong(uint64_t(Duration(EPOCH, now())));
- event.impl->encode(buffer);
- string key(event.impl->getRoutingKey(assignedBrokerBank, assignedAgentBank));
-
- sendBufferLH(buffer, QMF_EXCHANGE, key);
- QPID_LOG(trace, "SENT EventIndication");
-}
-
-AgentEventImpl::Ptr AgentImpl::eventDeclareQueue(const string& name)
-{
- AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::DECLARE_QUEUE));
- event->name = name;
-
- return event;
-}
-
-AgentEventImpl::Ptr AgentImpl::eventBind(const string& exchange, const string& queue,
- const string& key)
-{
- AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::BIND));
- event->name = queue;
- event->exchange = exchange;
- event->bindingKey = key;
-
- return event;
-}
-
-AgentEventImpl::Ptr AgentImpl::eventSetupComplete()
-{
- AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::SETUP_COMPLETE));
- return event;
-}
-
-AgentEventImpl::Ptr AgentImpl::eventQuery(uint32_t num, const string& userId, const string& package,
- const string& cls, boost::shared_ptr<ObjectId> oid)
-{
- AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::GET_QUERY));
- event->sequence = num;
- event->authUserId = userId;
- if (oid.get())
- event->query.reset(new Query(oid.get()));
- else
- event->query.reset(new Query(cls.c_str(), package.c_str()));
- return event;
-}
-
-AgentEventImpl::Ptr AgentImpl::eventMethod(uint32_t num, const string& userId, const string& method,
- boost::shared_ptr<ObjectId> oid, boost::shared_ptr<Value> argMap,
- const SchemaObjectClass* objectClass)
-{
- AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::METHOD_CALL));
- event->sequence = num;
- event->authUserId = userId;
- event->name = method;
- event->objectId = oid;
- event->arguments = argMap;
- event->objectClass = objectClass;
- return event;
-}
-
-void AgentImpl::sendBufferLH(Buffer& buf, const string& destination, const string& routingKey)
-{
- uint32_t length = buf.getPosition();
- MessageImpl::Ptr message(new MessageImpl);
-
- buf.reset();
- buf.getRawData(message->body, length);
- message->destination = destination;
- message->routingKey = routingKey;
- message->replyExchange = "amq.direct";
- message->replyKey = queueName;
-
- xmtQueue.push_back(message);
-}
-
-void AgentImpl::sendPackageIndicationLH(const string& packageName)
-{
- Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
- Protocol::encodeHeader(buffer, Protocol::OP_PACKAGE_INDICATION);
- buffer.putShortString(packageName);
- sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT PackageIndication: package_name=" << packageName);
-}
-
-void AgentImpl::sendClassIndicationLH(ClassKind kind, const string& packageName, const AgentClassKey& key)
-{
- Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
- Protocol::encodeHeader(buffer, Protocol::OP_CLASS_INDICATION);
- buffer.putOctet((int) kind);
- buffer.putShortString(packageName);
- buffer.putShortString(key.name);
- buffer.putBin128(const_cast<uint8_t*>(key.hash)); // const_cast needed for older Qpid libraries
- sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT ClassIndication: package_name=" << packageName << " class_name=" << key.name);
-}
-
-void AgentImpl::sendCommandCompleteLH(const string& exchange, const string& replyToKey,
- uint32_t sequence, uint32_t code, const string& text)
-{
- Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
- Protocol::encodeHeader(buffer, Protocol::OP_COMMAND_COMPLETE, sequence);
- buffer.putLong(code);
- buffer.putShortString(text);
- sendBufferLH(buffer, exchange, replyToKey);
- QPID_LOG(trace, "SENT CommandComplete: seq=" << sequence << " code=" << code << " text=" << text);
-}
-
-void AgentImpl::sendMethodErrorLH(uint32_t sequence, const string& key, uint32_t code, const string& text)
-{
- Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
- Protocol::encodeHeader(buffer, Protocol::OP_METHOD_RESPONSE, sequence);
- buffer.putLong(code);
-
- string fulltext;
- switch (code) {
- case MERR_UNKNOWN_PACKAGE: fulltext = "Unknown Package"; break;
- case MERR_UNKNOWN_CLASS: fulltext = "Unknown Class"; break;
- case MERR_UNKNOWN_METHOD: fulltext = "Unknown Method"; break;
- case MERR_INTERNAL_ERROR: fulltext = "Internal Error"; break;
- default: fulltext = "Unspecified Error"; break;
- }
-
- if (!text.empty()) {
- fulltext += " (";
- fulltext += text;
- fulltext += ")";
- }
-
- buffer.putMediumString(fulltext);
- sendBufferLH(buffer, DIR_EXCHANGE, key);
- QPID_LOG(trace, "SENT MethodResponse: errorCode=" << code << " text=" << fulltext);
-}
-
-void AgentImpl::handleAttachResponse(Buffer& inBuffer)
-{
- Mutex::ScopedLock _lock(lock);
-
- assignedBrokerBank = inBuffer.getLong();
- assignedAgentBank = inBuffer.getLong();
-
- QPID_LOG(trace, "RCVD AttachResponse: broker=" << assignedBrokerBank << " agent=" << assignedAgentBank);
-
- if ((assignedBrokerBank != requestedBrokerBank) ||
- (assignedAgentBank != requestedAgentBank)) {
- if (requestedAgentBank == 0) {
- QPID_LOG(notice, "Initial object-id bank assigned: " << assignedBrokerBank << "." <<
- assignedAgentBank);
- } else {
- QPID_LOG(warning, "Collision in object-id! New bank assigned: " << assignedBrokerBank <<
- "." << assignedAgentBank);
- }
- //storeData(); // TODO
- requestedBrokerBank = assignedBrokerBank;
- requestedAgentBank = assignedAgentBank;
- }
-
- attachment.setBanks(assignedBrokerBank, assignedAgentBank);
-
- // Bind to qpid.management to receive commands
- stringstream key;
- key << "agent." << assignedBrokerBank << "." << assignedAgentBank;
- eventQueue.push_back(eventBind(QMF_EXCHANGE, queueName, key.str()));
-
- // Send package indications for all local packages
- for (map<string, ClassMaps>::iterator pIter = packages.begin();
- pIter != packages.end();
- pIter++) {
- sendPackageIndicationLH(pIter->first);
-
- // Send class indications for all local classes
- ClassMaps cMap = pIter->second;
- for (ObjectClassMap::iterator cIter = cMap.objectClasses.begin();
- cIter != cMap.objectClasses.end(); cIter++)
- sendClassIndicationLH(CLASS_OBJECT, pIter->first, cIter->first);
- for (EventClassMap::iterator cIter = cMap.eventClasses.begin();
- cIter != cMap.eventClasses.end(); cIter++)
- sendClassIndicationLH(CLASS_EVENT, pIter->first, cIter->first);
- }
-
- attachComplete = true;
-}
-
-void AgentImpl::handlePackageRequest(Buffer&)
-{
- Mutex::ScopedLock _lock(lock);
-}
-
-void AgentImpl::handleClassQuery(Buffer&)
-{
- Mutex::ScopedLock _lock(lock);
-}
-
-void AgentImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence,
- const string& replyExchange, const string& replyKey)
-{
- Mutex::ScopedLock _lock(lock);
- string rExchange(replyExchange);
- string rKey(replyKey);
- string packageName;
- inBuffer.getShortString(packageName);
- AgentClassKey key(inBuffer);
-
- if (rExchange.empty())
- rExchange = QMF_EXCHANGE;
- if (rKey.empty())
- rKey = BROKER_KEY;
-
- QPID_LOG(trace, "RCVD SchemaRequest: package=" << packageName << " class=" << key.name);
-
- map<string, ClassMaps>::iterator pIter = packages.find(packageName);
- if (pIter == packages.end()) {
- sendCommandCompleteLH(rExchange, rKey, sequence, 1, "package not found");
- return;
- }
-
- ClassMaps cMap = pIter->second;
- ObjectClassMap::iterator ocIter = cMap.objectClasses.find(key);
- if (ocIter != cMap.objectClasses.end()) {
- SchemaObjectClass* oImpl = ocIter->second;
- Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
- Protocol::encodeHeader(buffer, Protocol::OP_SCHEMA_RESPONSE, sequence);
- oImpl->impl->encode(buffer);
- sendBufferLH(buffer, rExchange, rKey);
- QPID_LOG(trace, "SENT SchemaResponse: (object) package=" << packageName << " class=" << key.name);
- return;
- }
-
- EventClassMap::iterator ecIter = cMap.eventClasses.find(key);
- if (ecIter != cMap.eventClasses.end()) {
- SchemaEventClass* eImpl = ecIter->second;
- Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
- Protocol::encodeHeader(buffer, Protocol::OP_SCHEMA_RESPONSE, sequence);
- eImpl->impl->encode(buffer);
- sendBufferLH(buffer, rExchange, rKey);
- QPID_LOG(trace, "SENT SchemaResponse: (event) package=" << packageName << " class=" << key.name);
- return;
- }
-
- sendCommandCompleteLH(rExchange, rKey, sequence, 1, "class not found");
-}
-
-void AgentImpl::handleGetQuery(Buffer& inBuffer, uint32_t sequence, const string& replyTo, const string& userId)
-{
- Mutex::ScopedLock _lock(lock);
- FieldTable ft;
- FieldTable::ValuePtr value;
- map<string, ClassMaps>::const_iterator pIter = packages.end();
- string pname;
- string cname;
- string oidRepr;
- boost::shared_ptr<ObjectId> oid;
-
- ft.decode(inBuffer);
-
- QPID_LOG(trace, "RCVD GetQuery: seq=" << sequence << " map=" << ft);
-
- value = ft.get("_package");
- if (value.get() && value->convertsTo<string>()) {
- pname = value->get<string>();
- pIter = packages.find(pname);
- if (pIter == packages.end()) {
- sendCommandCompleteLH(DIR_EXCHANGE, replyTo, sequence);
- return;
- }
- }
-
- value = ft.get("_class");
- if (value.get() && value->convertsTo<string>()) {
- cname = value->get<string>();
- // TODO - check for validity of class (in package or any package)
- if (pIter == packages.end()) {
- } else {
-
- }
- }
-
- value = ft.get("_objectid");
- if (value.get() && value->convertsTo<string>()) {
- oidRepr = value->get<string>();
- oid.reset(new ObjectId());
- oid->impl->fromString(oidRepr);
- }
-
- AgentQueryContext::Ptr context(new AgentQueryContext);
- uint32_t contextNum = nextContextNum++;
- context->sequence = sequence;
- context->exchange = DIR_EXCHANGE;
- context->key = replyTo;
- contextMap[contextNum] = context;
-
- eventQueue.push_back(eventQuery(contextNum, userId, pname, cname, oid));
-}
-
-void AgentImpl::handleMethodRequest(Buffer& buffer, uint32_t sequence, const string& replyTo, const string& userId)
-{
- Mutex::ScopedLock _lock(lock);
- string pname;
- string method;
- boost::shared_ptr<ObjectId> oid(ObjectIdImpl::factory(buffer));
- buffer.getShortString(pname);
- AgentClassKey classKey(buffer);
- buffer.getShortString(method);
-
- QPID_LOG(trace, "RCVD MethodRequest seq=" << sequence << " method=" << method);
-
- map<string, ClassMaps>::const_iterator pIter = packages.find(pname);
- if (pIter == packages.end()) {
- sendMethodErrorLH(sequence, replyTo, MERR_UNKNOWN_PACKAGE, pname);
- return;
- }
-
- ObjectClassMap::const_iterator cIter = pIter->second.objectClasses.find(classKey);
- if (cIter == pIter->second.objectClasses.end()) {
- sendMethodErrorLH(sequence, replyTo, MERR_UNKNOWN_CLASS, classKey.repr());
- return;
- }
-
- const SchemaObjectClass* schema = cIter->second;
- vector<const SchemaMethod*>::const_iterator mIter = schema->impl->methods.begin();
- for (; mIter != schema->impl->methods.end(); mIter++) {
- if ((*mIter)->getName() == method)
- break;
- }
-
- if (mIter == schema->impl->methods.end()) {
- sendMethodErrorLH(sequence, replyTo, MERR_UNKNOWN_METHOD, method);
- return;
- }
-
- const SchemaMethod* schemaMethod = *mIter;
- boost::shared_ptr<Value> argMap(new Value(TYPE_MAP));
- Value* value;
- for (vector<const SchemaArgument*>::const_iterator aIter = schemaMethod->impl->arguments.begin();
- aIter != schemaMethod->impl->arguments.end(); aIter++) {
- const SchemaArgument* schemaArg = *aIter;
- if (schemaArg->getDirection() == DIR_IN || schemaArg->getDirection() == DIR_IN_OUT)
- value = ValueImpl::factory(schemaArg->getType(), buffer);
- else
- value = ValueImpl::factory(schemaArg->getType());
- argMap->insert(schemaArg->getName(), value);
- }
-
- AgentQueryContext::Ptr context(new AgentQueryContext);
- uint32_t contextNum = nextContextNum++;
- context->sequence = sequence;
- context->exchange = DIR_EXCHANGE;
- context->key = replyTo;
- context->schemaMethod = schemaMethod;
- contextMap[contextNum] = context;
-
- eventQueue.push_back(eventMethod(contextNum, userId, method, oid, argMap, schema));
-}
-
-void AgentImpl::handleConsoleAddedIndication()
-{
- Mutex::ScopedLock _lock(lock);
-}
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-Agent::Agent(char* label, bool internalStore) { impl = new AgentImpl(label, internalStore); }
-Agent::~Agent() { delete impl; }
-void Agent::setStoreDir(const char* path) { impl->setStoreDir(path); }
-void Agent::setTransferDir(const char* path) { impl->setTransferDir(path); }
-void Agent::handleRcvMessage(Message& message) { impl->handleRcvMessage(message); }
-bool Agent::getXmtMessage(Message& item) const { return impl->getXmtMessage(item); }
-void Agent::popXmt() { impl->popXmt(); }
-bool Agent::getEvent(AgentEvent& event) const { return impl->getEvent(event); }
-void Agent::popEvent() { impl->popEvent(); }
-void Agent::newSession() { impl->newSession(); }
-void Agent::startProtocol() { impl->startProtocol(); }
-void Agent::heartbeat() { impl->heartbeat(); }
-void Agent::methodResponse(uint32_t sequence, uint32_t status, char* text, const Value& arguments) { impl->methodResponse(sequence, status, text, arguments); }
-void Agent::queryResponse(uint32_t sequence, Object& object, bool prop, bool stat) { impl->queryResponse(sequence, object, prop, stat); }
-void Agent::queryComplete(uint32_t sequence) { impl->queryComplete(sequence); }
-void Agent::registerClass(SchemaObjectClass* cls) { impl->registerClass(cls); }
-void Agent::registerClass(SchemaEventClass* cls) { impl->registerClass(cls); }
-const ObjectId* Agent::addObject(Object& obj, uint64_t persistId) { return impl->addObject(obj, persistId); }
-const ObjectId* Agent::allocObjectId(uint64_t persistId) { return impl->allocObjectId(persistId); }
-const ObjectId* Agent::allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi) { return impl->allocObjectId(persistIdLo, persistIdHi); }
-void Agent::raiseEvent(Event& event) { impl->raiseEvent(event); }
-
diff --git a/qpid/cpp/src/qmf/engine/BrokerProxyImpl.cpp b/qpid/cpp/src/qmf/engine/BrokerProxyImpl.cpp
deleted file mode 100644
index 5fc71979fd..0000000000
--- a/qpid/cpp/src/qmf/engine/BrokerProxyImpl.cpp
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/BrokerProxyImpl.h"
-#include "qmf/engine/ConsoleImpl.h"
-#include "qmf/engine/Protocol.h"
-#include "qpid/Address.h"
-#include "qpid/sys/SystemInfo.h"
-#include <qpid/log/Statement.h>
-#include <qpid/StringUtils.h>
-#include <string.h>
-#include <iostream>
-#include <fstream>
-
-using namespace std;
-using namespace qmf::engine;
-using namespace qpid::framing;
-using namespace qpid::sys;
-
-namespace {
- const char* QMF_EXCHANGE = "qpid.management";
- const char* DIR_EXCHANGE = "amq.direct";
- const char* BROKER_KEY = "broker";
- const char* BROKER_PACKAGE = "org.apache.qpid.broker";
- const char* AGENT_CLASS = "agent";
- const char* BROKER_AGENT_KEY = "agent.1.0";
-}
-
-const Object* QueryResponseImpl::getObject(uint32_t idx) const
-{
- vector<ObjectPtr>::const_iterator iter = results.begin();
-
- while (idx > 0) {
- if (iter == results.end())
- return 0;
- iter++;
- idx--;
- }
-
- return iter->get();
-}
-
-#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());}
-
-BrokerEvent BrokerEventImpl::copy()
-{
- BrokerEvent item;
-
- ::memset(&item, 0, sizeof(BrokerEvent));
- item.kind = kind;
-
- STRING_REF(name);
- STRING_REF(exchange);
- STRING_REF(bindingKey);
- item.context = context;
- item.queryResponse = queryResponse.get();
- item.methodResponse = methodResponse.get();
-
- return item;
-}
-
-BrokerProxyImpl::BrokerProxyImpl(BrokerProxy& pub, Console& _console) : publicObject(pub), console(_console)
-{
- stringstream qn;
- qpid::Address addr;
-
- SystemInfo::getLocalHostname(addr);
- qn << "qmfc-" << SystemInfo::getProcessName() << "-" << addr << "-" << SystemInfo::getProcessId();
- queueName = qn.str();
-
- seqMgr.setUnsolicitedContext(SequenceContext::Ptr(new StaticContext(*this)));
-}
-
-void BrokerProxyImpl::sessionOpened(SessionHandle& /*sh*/)
-{
- Mutex::ScopedLock _lock(lock);
- agentList.clear();
- eventQueue.clear();
- xmtQueue.clear();
- eventQueue.push_back(eventDeclareQueue(queueName));
- eventQueue.push_back(eventBind(DIR_EXCHANGE, queueName, queueName));
- eventQueue.push_back(eventSetupComplete());
-
- // TODO: Store session handle
-}
-
-void BrokerProxyImpl::sessionClosed()
-{
- Mutex::ScopedLock _lock(lock);
- agentList.clear();
- eventQueue.clear();
- xmtQueue.clear();
-}
-
-void BrokerProxyImpl::startProtocol()
-{
- AgentProxyPtr agent(AgentProxyImpl::factory(console, publicObject, 0, "Agent embedded in broker"));
- {
- Mutex::ScopedLock _lock(lock);
- char rawbuffer[512];
- Buffer buffer(rawbuffer, 512);
-
- agentList[0] = agent;
-
- requestsOutstanding = 1;
- topicBound = false;
- uint32_t sequence(seqMgr.reserve());
- Protocol::encodeHeader(buffer, Protocol::OP_BROKER_REQUEST, sequence);
- sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT BrokerRequest seq=" << sequence);
- }
-
- console.impl->eventAgentAdded(agent);
-}
-
-void BrokerProxyImpl::sendBufferLH(Buffer& buf, const string& destination, const string& routingKey)
-{
- uint32_t length = buf.getPosition();
- MessageImpl::Ptr message(new MessageImpl);
-
- buf.reset();
- buf.getRawData(message->body, length);
- message->destination = destination;
- message->routingKey = routingKey;
- message->replyExchange = DIR_EXCHANGE;
- message->replyKey = queueName;
-
- xmtQueue.push_back(message);
-}
-
-void BrokerProxyImpl::handleRcvMessage(Message& message)
-{
- Buffer inBuffer(message.body, message.length);
- uint8_t opcode;
- uint32_t sequence;
-
- while (Protocol::checkHeader(inBuffer, &opcode, &sequence))
- seqMgr.dispatch(opcode, sequence, message.routingKey ? string(message.routingKey) : string(), inBuffer);
-}
-
-bool BrokerProxyImpl::getXmtMessage(Message& item) const
-{
- Mutex::ScopedLock _lock(lock);
- if (xmtQueue.empty())
- return false;
- item = xmtQueue.front()->copy();
- return true;
-}
-
-void BrokerProxyImpl::popXmt()
-{
- Mutex::ScopedLock _lock(lock);
- if (!xmtQueue.empty())
- xmtQueue.pop_front();
-}
-
-bool BrokerProxyImpl::getEvent(BrokerEvent& event) const
-{
- Mutex::ScopedLock _lock(lock);
- if (eventQueue.empty())
- return false;
- event = eventQueue.front()->copy();
- return true;
-}
-
-void BrokerProxyImpl::popEvent()
-{
- Mutex::ScopedLock _lock(lock);
- if (!eventQueue.empty())
- eventQueue.pop_front();
-}
-
-uint32_t BrokerProxyImpl::agentCount() const
-{
- Mutex::ScopedLock _lock(lock);
- return agentList.size();
-}
-
-const AgentProxy* BrokerProxyImpl::getAgent(uint32_t idx) const
-{
- Mutex::ScopedLock _lock(lock);
- for (map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.begin();
- iter != agentList.end(); iter++)
- if (idx-- == 0)
- return iter->second.get();
- return 0;
-}
-
-void BrokerProxyImpl::sendQuery(const Query& query, void* context, const AgentProxy* agent)
-{
- SequenceContext::Ptr queryContext(new QueryContext(*this, context));
- Mutex::ScopedLock _lock(lock);
- bool sent = false;
- if (agent != 0) {
- if (sendGetRequestLH(queryContext, query, agent))
- sent = true;
- } else {
- // TODO (optimization) only send queries to agents that have the requested class+package
- for (map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.begin();
- iter != agentList.end(); iter++) {
- if (sendGetRequestLH(queryContext, query, iter->second.get()))
- sent = true;
- }
- }
-
- if (!sent) {
- queryContext->reserve();
- queryContext->release();
- }
-}
-
-bool BrokerProxyImpl::sendGetRequestLH(SequenceContext::Ptr queryContext, const Query& query, const AgentProxy* agent)
-{
- if (query.impl->singleAgent()) {
- if (query.impl->agentBank() != agent->getAgentBank())
- return false;
- }
- stringstream key;
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve(queryContext));
- agent->impl->addSequence(sequence);
-
- Protocol::encodeHeader(outBuffer, Protocol::OP_GET_QUERY, sequence);
- query.impl->encode(outBuffer);
- key << "agent.1." << agent->impl->agentBank;
- sendBufferLH(outBuffer, QMF_EXCHANGE, key.str());
- QPID_LOG(trace, "SENT GetQuery seq=" << sequence << " key=" << key.str());
- return true;
-}
-
-string BrokerProxyImpl::encodeMethodArguments(const SchemaMethod* schema, const Value* argmap, Buffer& buffer)
-{
- int argCount = schema->getArgumentCount();
-
- if (argmap == 0 || !argmap->isMap())
- return string("Arguments must be in a map value");
-
- for (int aIdx = 0; aIdx < argCount; aIdx++) {
- const SchemaArgument* arg(schema->getArgument(aIdx));
- if (arg->getDirection() == DIR_IN || arg->getDirection() == DIR_IN_OUT) {
- if (argmap->keyInMap(arg->getName())) {
- const Value* argVal(argmap->byKey(arg->getName()));
- if (argVal->getType() != arg->getType())
- return string("Argument is the wrong type: ") + arg->getName();
- argVal->impl->encode(buffer);
- } else {
- Value defaultValue(arg->getType());
- defaultValue.impl->encode(buffer);
- }
- }
- }
-
- return string();
-}
-
-string BrokerProxyImpl::encodedSizeMethodArguments(const SchemaMethod* schema, const Value* argmap, uint32_t& size)
-{
- int argCount = schema->getArgumentCount();
-
- if (argmap == 0 || !argmap->isMap())
- return string("Arguments must be in a map value");
-
- for (int aIdx = 0; aIdx < argCount; aIdx++) {
- const SchemaArgument* arg(schema->getArgument(aIdx));
- if (arg->getDirection() == DIR_IN || arg->getDirection() == DIR_IN_OUT) {
- if (argmap->keyInMap(arg->getName())) {
- const Value* argVal(argmap->byKey(arg->getName()));
- if (argVal->getType() != arg->getType())
- return string("Argument is the wrong type: ") + arg->getName();
- size += argVal->impl->encodedSize();
- } else {
- Value defaultValue(arg->getType());
- size += defaultValue.impl->encodedSize();
- }
- }
- }
-
- return string();
-}
-
-void BrokerProxyImpl::sendMethodRequest(ObjectId* oid, const SchemaObjectClass* cls,
- const string& methodName, const Value* args, void* userContext)
-{
- int methodCount = cls->getMethodCount();
- int idx;
- for (idx = 0; idx < methodCount; idx++) {
- const SchemaMethod* method = cls->getMethod(idx);
- if (string(method->getName()) == methodName) {
- Mutex::ScopedLock _lock(lock);
- SequenceContext::Ptr methodContext(new MethodContext(*this, userContext, method));
- stringstream key;
- char* buf(outputBuffer);
- uint32_t bufLen(1024);
- bool allocated(false);
-
- string argErrorString = encodedSizeMethodArguments(method, args, bufLen);
- if (!argErrorString.empty()) {
- MethodResponsePtr argError(MethodResponseImpl::factory(1, argErrorString));
- eventQueue.push_back(eventMethodResponse(userContext, argError));
- return;
- }
-
- if (bufLen > MA_BUFFER_SIZE) {
- buf = (char*) malloc(bufLen);
- allocated = true;
- }
-
- Buffer outBuffer(buf, bufLen);
- uint32_t sequence(seqMgr.reserve(methodContext));
-
- Protocol::encodeHeader(outBuffer, Protocol::OP_METHOD_REQUEST, sequence);
- oid->impl->encode(outBuffer);
- cls->getClassKey()->impl->encode(outBuffer);
- outBuffer.putShortString(methodName);
-
- encodeMethodArguments(method, args, outBuffer);
- key << "agent.1." << oid->impl->getAgentBank();
- sendBufferLH(outBuffer, QMF_EXCHANGE, key.str());
- QPID_LOG(trace, "SENT MethodRequest seq=" << sequence << " method=" << methodName << " key=" << key.str());
-
- if (allocated)
- free(buf);
-
- return;
- }
- }
-
- MethodResponsePtr error(MethodResponseImpl::factory(1, string("Unknown method: ") + methodName));
- Mutex::ScopedLock _lock(lock);
- eventQueue.push_back(eventMethodResponse(userContext, error));
-}
-
-void BrokerProxyImpl::addBinding(const string& exchange, const string& key)
-{
- Mutex::ScopedLock _lock(lock);
- eventQueue.push_back(eventBind(exchange, queueName, key));
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventDeclareQueue(const string& queueName)
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::DECLARE_QUEUE));
- event->name = queueName;
- return event;
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventBind(const string& exchange, const string& queue, const string& key)
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::BIND));
- event->name = queue;
- event->exchange = exchange;
- event->bindingKey = key;
-
- return event;
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventSetupComplete()
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::SETUP_COMPLETE));
- return event;
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventStable()
-{
- QPID_LOG(trace, "Console Link to Broker Stable");
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::STABLE));
- return event;
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventQueryComplete(void* context, QueryResponsePtr response)
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::QUERY_COMPLETE));
- event->context = context;
- event->queryResponse = response;
- return event;
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventMethodResponse(void* context, MethodResponsePtr response)
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::METHOD_RESPONSE));
- event->context = context;
- event->methodResponse = response;
- return event;
-}
-
-void BrokerProxyImpl::handleBrokerResponse(Buffer& inBuffer, uint32_t seq)
-{
- brokerId.decode(inBuffer);
- QPID_LOG(trace, "RCVD BrokerResponse seq=" << seq << " brokerId=" << brokerId);
- Mutex::ScopedLock _lock(lock);
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve());
- incOutstandingLH();
- Protocol::encodeHeader(outBuffer, Protocol::OP_PACKAGE_REQUEST, sequence);
- sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT PackageRequest seq=" << sequence);
-}
-
-void BrokerProxyImpl::handlePackageIndication(Buffer& inBuffer, uint32_t seq)
-{
- string package;
-
- inBuffer.getShortString(package);
- QPID_LOG(trace, "RCVD PackageIndication seq=" << seq << " package=" << package);
- console.impl->learnPackage(package);
-
- Mutex::ScopedLock _lock(lock);
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve());
- incOutstandingLH();
- Protocol::encodeHeader(outBuffer, Protocol::OP_CLASS_QUERY, sequence);
- outBuffer.putShortString(package);
- sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT ClassQuery seq=" << sequence << " package=" << package);
-}
-
-void BrokerProxyImpl::handleCommandComplete(Buffer& inBuffer, uint32_t seq)
-{
- string text;
- uint32_t code = inBuffer.getLong();
- inBuffer.getShortString(text);
- QPID_LOG(trace, "RCVD CommandComplete seq=" << seq << " code=" << code << " text=" << text);
-}
-
-void BrokerProxyImpl::handleClassIndication(Buffer& inBuffer, uint32_t seq)
-{
- uint8_t kind = inBuffer.getOctet();
- auto_ptr<SchemaClassKey> classKey(SchemaClassKeyImpl::factory(inBuffer));
-
- QPID_LOG(trace, "RCVD ClassIndication seq=" << seq << " kind=" << (int) kind << " key=" << classKey->impl->str());
-
- if (!console.impl->haveClass(classKey.get())) {
- Mutex::ScopedLock _lock(lock);
- incOutstandingLH();
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve());
- Protocol::encodeHeader(outBuffer, Protocol::OP_SCHEMA_REQUEST, sequence);
- classKey->impl->encode(outBuffer);
- sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT SchemaRequest seq=" << sequence <<" key=" << classKey->impl->str());
- }
-}
-
-MethodResponsePtr BrokerProxyImpl::handleMethodResponse(Buffer& inBuffer, uint32_t seq, const SchemaMethod* schema)
-{
- MethodResponsePtr response(MethodResponseImpl::factory(inBuffer, schema));
-
- QPID_LOG(trace, "RCVD MethodResponse seq=" << seq << " status=" << response->getStatus() << " text=" <<
- response->getException()->asString());
-
- return response;
-}
-
-void BrokerProxyImpl::handleHeartbeatIndication(Buffer& inBuffer, uint32_t seq, const string& routingKey)
-{
- vector<string> tokens = qpid::split(routingKey, ".");
- uint32_t agentBank;
- uint64_t timestamp;
-
- if (routingKey.empty() || tokens.size() != 4)
- agentBank = 0;
- else
- agentBank = ::atoi(tokens[3].c_str());
-
- timestamp = inBuffer.getLongLong();
- map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.find(agentBank);
- if (iter != agentList.end()) {
- console.impl->eventAgentHeartbeat(iter->second, timestamp);
- }
- QPID_LOG(trace, "RCVD HeartbeatIndication seq=" << seq << " agentBank=" << agentBank);
-}
-
-void BrokerProxyImpl::handleEventIndication(Buffer& inBuffer, uint32_t seq)
-{
- auto_ptr<SchemaClassKey> classKey(SchemaClassKeyImpl::factory(inBuffer));
- const SchemaEventClass *schema = console.impl->getEventClass(classKey.get());
- if (schema == 0) {
- QPID_LOG(trace, "No Schema Found for EventIndication. seq=" << seq << " key=" << classKey->impl->str());
- return;
- }
-
- EventPtr eptr(EventImpl::factory(schema, inBuffer));
-
- console.impl->eventEventReceived(eptr);
- QPID_LOG(trace, "RCVD EventIndication seq=" << seq << " key=" << classKey->impl->str());
-}
-
-void BrokerProxyImpl::handleSchemaResponse(Buffer& inBuffer, uint32_t seq)
-{
- SchemaObjectClass* oClassPtr;
- SchemaEventClass* eClassPtr;
- uint8_t kind = inBuffer.getOctet();
- const SchemaClassKey* key;
- if (kind == CLASS_OBJECT) {
- oClassPtr = SchemaObjectClassImpl::factory(inBuffer);
- console.impl->learnClass(oClassPtr);
- key = oClassPtr->getClassKey();
- QPID_LOG(trace, "RCVD SchemaResponse seq=" << seq << " kind=object key=" << key->impl->str());
-
- //
- // If we have just learned about the org.apache.qpid.broker:agent class, send a get
- // request for the current list of agents so we can have it on-hand before we declare
- // this session "stable".
- //
- if (key->impl->getClassName() == AGENT_CLASS && key->impl->getPackageName() == BROKER_PACKAGE) {
- Mutex::ScopedLock _lock(lock);
- incOutstandingLH();
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve());
- Protocol::encodeHeader(outBuffer, Protocol::OP_GET_QUERY, sequence);
- FieldTable ft;
- ft.setString("_class", AGENT_CLASS);
- ft.setString("_package", BROKER_PACKAGE);
- ft.encode(outBuffer);
- sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_AGENT_KEY);
- QPID_LOG(trace, "SENT GetQuery seq=" << sequence << " key=" << BROKER_AGENT_KEY);
- }
- } else if (kind == CLASS_EVENT) {
- eClassPtr = SchemaEventClassImpl::factory(inBuffer);
- console.impl->learnClass(eClassPtr);
- key = eClassPtr->getClassKey();
- QPID_LOG(trace, "RCVD SchemaResponse seq=" << seq << " kind=event key=" << key->impl->str());
- }
- else {
- QPID_LOG(error, "BrokerProxyImpl::handleSchemaResponse received unknown class kind: " << (int) kind);
- }
-}
-
-ObjectPtr BrokerProxyImpl::handleObjectIndication(Buffer& inBuffer, uint32_t seq, bool prop, bool stat)
-{
- auto_ptr<SchemaClassKey> classKey(SchemaClassKeyImpl::factory(inBuffer));
- QPID_LOG(trace, "RCVD ObjectIndication seq=" << seq << " key=" << classKey->impl->str());
-
- SchemaObjectClass* schema = console.impl->getSchema(classKey.get());
- if (schema == 0) {
- QPID_LOG(trace, "No Schema Found for ObjectIndication. seq=" << seq << " key=" << classKey->impl->str());
- return ObjectPtr();
- }
-
- ObjectPtr optr(ObjectImpl::factory(schema, this, inBuffer, prop, stat, true));
- if (prop && classKey->impl->getPackageName() == BROKER_PACKAGE && classKey->impl->getClassName() == AGENT_CLASS) {
- //
- // We've intercepted information about a remote agent... update the agent list accordingly
- //
- updateAgentList(optr);
- }
- return optr;
-}
-
-void BrokerProxyImpl::updateAgentList(ObjectPtr obj)
-{
- Value* value = obj->getValue("agentBank");
- Mutex::ScopedLock _lock(lock);
- if (value != 0 && value->isUint()) {
- uint32_t agentBank = value->asUint();
- if (obj->isDeleted()) {
- map<uint32_t, AgentProxyPtr>::iterator iter = agentList.find(agentBank);
- if (iter != agentList.end()) {
- AgentProxyPtr agent(iter->second);
- console.impl->eventAgentDeleted(agent);
- agentList.erase(agentBank);
- QPID_LOG(trace, "Agent at bank " << agentBank << " removed from agent list");
-
- //
- // Release all sequence numbers for requests in-flight to this agent.
- // Since the agent is no longer connected, these requests would not
- // otherwise complete.
- //
- agent->impl->releaseInFlight(seqMgr);
- }
- } else {
- Value* str = obj->getValue("label");
- string label;
- if (str != 0 && str->isString())
- label = str->asString();
- map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.find(agentBank);
- if (iter == agentList.end()) {
- AgentProxyPtr agent(AgentProxyImpl::factory(console, publicObject, agentBank, label));
- agentList[agentBank] = agent;
- console.impl->eventAgentAdded(agent);
- QPID_LOG(trace, "Agent '" << label << "' found at bank " << agentBank);
- }
- }
- }
-}
-
-void BrokerProxyImpl::incOutstandingLH()
-{
- requestsOutstanding++;
-}
-
-void BrokerProxyImpl::decOutstanding()
-{
- Mutex::ScopedLock _lock(lock);
- requestsOutstanding--;
- if (requestsOutstanding == 0 && !topicBound) {
- topicBound = true;
- for (vector<pair<string, string> >::const_iterator iter = console.impl->bindingList.begin();
- iter != console.impl->bindingList.end(); iter++) {
- string exchange(iter->first.empty() ? QMF_EXCHANGE : iter->first);
- string key(iter->second);
- eventQueue.push_back(eventBind(exchange, queueName, key));
- }
- eventQueue.push_back(eventStable());
- }
-}
-
-MethodResponseImpl::MethodResponseImpl(const MethodResponseImpl& from) :
- status(from.status), schema(from.schema)
-{
- if (from.exception.get())
- exception.reset(new Value(*(from.exception)));
- if (from.arguments.get())
- arguments.reset(new Value(*(from.arguments)));
-}
-
-MethodResponseImpl::MethodResponseImpl(Buffer& buf, const SchemaMethod* s) : schema(s)
-{
- string text;
-
- status = buf.getLong();
- buf.getMediumString(text);
- exception.reset(new Value(TYPE_LSTR));
- exception->setString(text.c_str());
-
- if (status != 0)
- return;
-
- arguments.reset(new Value(TYPE_MAP));
- int argCount(schema->getArgumentCount());
- for (int idx = 0; idx < argCount; idx++) {
- const SchemaArgument* arg = schema->getArgument(idx);
- if (arg->getDirection() == DIR_OUT || arg->getDirection() == DIR_IN_OUT) {
- Value* value(ValueImpl::factory(arg->getType(), buf));
- arguments->insert(arg->getName(), value);
- }
- }
-}
-
-MethodResponseImpl::MethodResponseImpl(uint32_t s, const string& text) : schema(0)
-{
- status = s;
- exception.reset(new Value(TYPE_LSTR));
- exception->setString(text.c_str());
-}
-
-MethodResponse* MethodResponseImpl::factory(Buffer& buf, const SchemaMethod* schema)
-{
- MethodResponseImpl* impl(new MethodResponseImpl(buf, schema));
- return new MethodResponse(impl);
-}
-
-MethodResponse* MethodResponseImpl::factory(uint32_t status, const std::string& text)
-{
- MethodResponseImpl* impl(new MethodResponseImpl(status, text));
- return new MethodResponse(impl);
-}
-
-bool StaticContext::handleMessage(uint8_t opcode, uint32_t sequence, const string& routingKey, Buffer& buffer)
-{
- ObjectPtr object;
- bool completeContext = false;
-
- if (opcode == Protocol::OP_BROKER_RESPONSE) {
- broker.handleBrokerResponse(buffer, sequence);
- completeContext = true;
- }
- else if (opcode == Protocol::OP_COMMAND_COMPLETE) {
- broker.handleCommandComplete(buffer, sequence);
- completeContext = true;
- }
- else if (opcode == Protocol::OP_SCHEMA_RESPONSE) {
- broker.handleSchemaResponse(buffer, sequence);
- completeContext = true;
- }
- else if (opcode == Protocol::OP_PACKAGE_INDICATION)
- broker.handlePackageIndication(buffer, sequence);
- else if (opcode == Protocol::OP_CLASS_INDICATION)
- broker.handleClassIndication(buffer, sequence);
- else if (opcode == Protocol::OP_HEARTBEAT_INDICATION)
- broker.handleHeartbeatIndication(buffer, sequence, routingKey);
- else if (opcode == Protocol::OP_EVENT_INDICATION)
- broker.handleEventIndication(buffer, sequence);
- else if (opcode == Protocol::OP_PROPERTY_INDICATION) {
- object = broker.handleObjectIndication(buffer, sequence, true, false);
- broker.console.impl->eventObjectUpdate(object, true, false);
- }
- else if (opcode == Protocol::OP_STATISTIC_INDICATION) {
- object = broker.handleObjectIndication(buffer, sequence, false, true);
- broker.console.impl->eventObjectUpdate(object, false, true);
- }
- else if (opcode == Protocol::OP_OBJECT_INDICATION) {
- object = broker.handleObjectIndication(buffer, sequence, true, true);
- broker.console.impl->eventObjectUpdate(object, true, true);
- }
- else {
- QPID_LOG(trace, "StaticContext::handleMessage invalid opcode: " << opcode);
- completeContext = true;
- }
-
- return completeContext;
-}
-
-void QueryContext::reserve()
-{
- Mutex::ScopedLock _lock(lock);
- requestsOutstanding++;
-}
-
-void QueryContext::release()
-{
- {
- Mutex::ScopedLock _lock(lock);
- if (--requestsOutstanding > 0)
- return;
- }
-
- Mutex::ScopedLock _block(broker.lock);
- broker.eventQueue.push_back(broker.eventQueryComplete(userContext, queryResponse));
-}
-
-bool QueryContext::handleMessage(uint8_t opcode, uint32_t sequence, const string& /*routingKey*/, Buffer& buffer)
-{
- bool completeContext = false;
- ObjectPtr object;
-
- if (opcode == Protocol::OP_COMMAND_COMPLETE) {
- broker.handleCommandComplete(buffer, sequence);
- completeContext = true;
-
- //
- // Visit each agent and remove the sequence from that agent's in-flight list.
- // This could be made more efficient because only one agent will have this sequence
- // in its list.
- //
- map<uint32_t, AgentProxyPtr> copy;
- {
- Mutex::ScopedLock _block(broker.lock);
- copy = broker.agentList;
- }
- for (map<uint32_t, AgentProxyPtr>::iterator iter = copy.begin(); iter != copy.end(); iter++)
- iter->second->impl->delSequence(sequence);
- }
- else if (opcode == Protocol::OP_OBJECT_INDICATION) {
- object = broker.handleObjectIndication(buffer, sequence, true, true);
- if (object.get() != 0)
- queryResponse->impl->results.push_back(object);
- }
- else {
- QPID_LOG(trace, "QueryContext::handleMessage invalid opcode: " << opcode);
- completeContext = true;
- }
-
- return completeContext;
-}
-
-void MethodContext::release()
-{
- Mutex::ScopedLock _block(broker.lock);
- broker.eventQueue.push_back(broker.eventMethodResponse(userContext, methodResponse));
-}
-
-bool MethodContext::handleMessage(uint8_t opcode, uint32_t sequence, const string& /*routingKey*/, Buffer& buffer)
-{
- if (opcode == Protocol::OP_METHOD_RESPONSE)
- methodResponse = broker.handleMethodResponse(buffer, sequence, schema);
- else
- QPID_LOG(trace, "QueryContext::handleMessage invalid opcode: " << opcode);
-
- return true;
-}
-
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-AgentProxy::AgentProxy(AgentProxyImpl* i) : impl(i) {}
-AgentProxy::AgentProxy(const AgentProxy& from) : impl(new AgentProxyImpl(*(from.impl))) {}
-AgentProxy::~AgentProxy() { delete impl; }
-const char* AgentProxy::getLabel() const { return impl->getLabel().c_str(); }
-uint32_t AgentProxy::getBrokerBank() const { return impl->getBrokerBank(); }
-uint32_t AgentProxy::getAgentBank() const { return impl->getAgentBank(); }
-
-BrokerProxy::BrokerProxy(Console& console) : impl(new BrokerProxyImpl(*this, console)) {}
-BrokerProxy::~BrokerProxy() { delete impl; }
-void BrokerProxy::sessionOpened(SessionHandle& sh) { impl->sessionOpened(sh); }
-void BrokerProxy::sessionClosed() { impl->sessionClosed(); }
-void BrokerProxy::startProtocol() { impl->startProtocol(); }
-void BrokerProxy::handleRcvMessage(Message& message) { impl->handleRcvMessage(message); }
-bool BrokerProxy::getXmtMessage(Message& item) const { return impl->getXmtMessage(item); }
-void BrokerProxy::popXmt() { impl->popXmt(); }
-bool BrokerProxy::getEvent(BrokerEvent& event) const { return impl->getEvent(event); }
-void BrokerProxy::popEvent() { impl->popEvent(); }
-uint32_t BrokerProxy::agentCount() const { return impl->agentCount(); }
-const AgentProxy* BrokerProxy::getAgent(uint32_t idx) const { return impl->getAgent(idx); }
-void BrokerProxy::sendQuery(const Query& query, void* context, const AgentProxy* agent) { impl->sendQuery(query, context, agent); }
-
-MethodResponse::MethodResponse(const MethodResponse& from) : impl(new MethodResponseImpl(*(from.impl))) {}
-MethodResponse::MethodResponse(MethodResponseImpl* i) : impl(i) {}
-MethodResponse::~MethodResponse() {}
-uint32_t MethodResponse::getStatus() const { return impl->getStatus(); }
-const Value* MethodResponse::getException() const { return impl->getException(); }
-const Value* MethodResponse::getArgs() const { return impl->getArgs(); }
-
-QueryResponse::QueryResponse(QueryResponseImpl* i) : impl(i) {}
-QueryResponse::~QueryResponse() {}
-uint32_t QueryResponse::getStatus() const { return impl->getStatus(); }
-const Value* QueryResponse::getException() const { return impl->getException(); }
-uint32_t QueryResponse::getObjectCount() const { return impl->getObjectCount(); }
-const Object* QueryResponse::getObject(uint32_t idx) const { return impl->getObject(idx); }
-
diff --git a/qpid/cpp/src/qmf/engine/BrokerProxyImpl.h b/qpid/cpp/src/qmf/engine/BrokerProxyImpl.h
deleted file mode 100644
index 0542b67dbb..0000000000
--- a/qpid/cpp/src/qmf/engine/BrokerProxyImpl.h
+++ /dev/null
@@ -1,241 +0,0 @@
-#ifndef _QmfEngineBrokerProxyImpl_
-#define _QmfEngineBrokerProxyImpl_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/Console.h"
-#include "qmf/engine/ObjectImpl.h"
-#include "qmf/engine/EventImpl.h"
-#include "qmf/engine/SchemaImpl.h"
-#include "qmf/engine/ValueImpl.h"
-#include "qmf/engine/QueryImpl.h"
-#include "qmf/engine/SequenceManager.h"
-#include "qmf/engine/MessageImpl.h"
-#include "qpid/framing/Buffer.h"
-#include "qpid/framing/Uuid.h"
-#include "qpid/sys/Mutex.h"
-#include "boost/shared_ptr.hpp"
-#include "boost/noncopyable.hpp"
-#include <memory>
-#include <string>
-#include <deque>
-#include <map>
-#include <set>
-#include <vector>
-
-namespace qmf {
-namespace engine {
-
- typedef boost::shared_ptr<MethodResponse> MethodResponsePtr;
- struct MethodResponseImpl {
- uint32_t status;
- const SchemaMethod* schema;
- std::auto_ptr<Value> exception;
- std::auto_ptr<Value> arguments;
-
- MethodResponseImpl(const MethodResponseImpl& from);
- MethodResponseImpl(qpid::framing::Buffer& buf, const SchemaMethod* schema);
- MethodResponseImpl(uint32_t status, const std::string& text);
- static MethodResponse* factory(qpid::framing::Buffer& buf, const SchemaMethod* schema);
- static MethodResponse* factory(uint32_t status, const std::string& text);
- ~MethodResponseImpl() {}
- uint32_t getStatus() const { return status; }
- const Value* getException() const { return exception.get(); }
- const Value* getArgs() const { return arguments.get(); }
- };
-
- typedef boost::shared_ptr<QueryResponse> QueryResponsePtr;
- struct QueryResponseImpl {
- uint32_t status;
- std::auto_ptr<Value> exception;
- std::vector<ObjectPtr> results;
-
- QueryResponseImpl() : status(0) {}
- static QueryResponse* factory() {
- QueryResponseImpl* impl(new QueryResponseImpl());
- return new QueryResponse(impl);
- }
- ~QueryResponseImpl() {}
- uint32_t getStatus() const { return status; }
- const Value* getException() const { return exception.get(); }
- uint32_t getObjectCount() const { return results.size(); }
- const Object* getObject(uint32_t idx) const;
- };
-
- struct BrokerEventImpl {
- typedef boost::shared_ptr<BrokerEventImpl> Ptr;
- BrokerEvent::EventKind kind;
- std::string name;
- std::string exchange;
- std::string bindingKey;
- void* context;
- QueryResponsePtr queryResponse;
- MethodResponsePtr methodResponse;
-
- BrokerEventImpl(BrokerEvent::EventKind k) : kind(k), context(0) {}
- ~BrokerEventImpl() {}
- BrokerEvent copy();
- };
-
- typedef boost::shared_ptr<AgentProxy> AgentProxyPtr;
- struct AgentProxyImpl {
- Console& console;
- BrokerProxy& broker;
- uint32_t agentBank;
- std::string label;
- std::set<uint32_t> inFlightSequences;
-
- AgentProxyImpl(Console& c, BrokerProxy& b, uint32_t ab, const std::string& l) : console(c), broker(b), agentBank(ab), label(l) {}
- static AgentProxy* factory(Console& c, BrokerProxy& b, uint32_t ab, const std::string& l) {
- AgentProxyImpl* impl(new AgentProxyImpl(c, b, ab, l));
- return new AgentProxy(impl);
- }
- ~AgentProxyImpl() {}
- const std::string& getLabel() const { return label; }
- uint32_t getBrokerBank() const { return 1; }
- uint32_t getAgentBank() const { return agentBank; }
- void addSequence(uint32_t seq) { inFlightSequences.insert(seq); }
- void delSequence(uint32_t seq) { inFlightSequences.erase(seq); }
- void releaseInFlight(SequenceManager& seqMgr) {
- for (std::set<uint32_t>::iterator iter = inFlightSequences.begin(); iter != inFlightSequences.end(); iter++)
- seqMgr.release(*iter);
- inFlightSequences.clear();
- }
- };
-
- class BrokerProxyImpl : public boost::noncopyable {
- public:
- BrokerProxyImpl(BrokerProxy& pub, Console& _console);
- ~BrokerProxyImpl() {}
-
- void sessionOpened(SessionHandle& sh);
- void sessionClosed();
- void startProtocol();
-
- void sendBufferLH(qpid::framing::Buffer& buf, const std::string& destination, const std::string& routingKey);
- void handleRcvMessage(Message& message);
- bool getXmtMessage(Message& item) const;
- void popXmt();
-
- bool getEvent(BrokerEvent& event) const;
- void popEvent();
-
- uint32_t agentCount() const;
- const AgentProxy* getAgent(uint32_t idx) const;
- void sendQuery(const Query& query, void* context, const AgentProxy* agent);
- bool sendGetRequestLH(SequenceContext::Ptr queryContext, const Query& query, const AgentProxy* agent);
- std::string encodeMethodArguments(const SchemaMethod* schema, const Value* args, qpid::framing::Buffer& buffer);
- std::string encodedSizeMethodArguments(const SchemaMethod* schema, const Value* args, uint32_t& size);
- void sendMethodRequest(ObjectId* oid, const SchemaObjectClass* cls, const std::string& method, const Value* args, void* context);
-
- void addBinding(const std::string& exchange, const std::string& key);
- void staticRelease() { decOutstanding(); }
-
- private:
- friend struct StaticContext;
- friend struct QueryContext;
- friend struct MethodContext;
- BrokerProxy& publicObject;
- mutable qpid::sys::Mutex lock;
- Console& console;
- std::string queueName;
- qpid::framing::Uuid brokerId;
- SequenceManager seqMgr;
- uint32_t requestsOutstanding;
- bool topicBound;
- std::map<uint32_t, AgentProxyPtr> agentList;
- std::deque<MessageImpl::Ptr> xmtQueue;
- std::deque<BrokerEventImpl::Ptr> eventQueue;
-
-# define MA_BUFFER_SIZE 65536
- char outputBuffer[MA_BUFFER_SIZE];
-
- BrokerEventImpl::Ptr eventDeclareQueue(const std::string& queueName);
- BrokerEventImpl::Ptr eventBind(const std::string& exchange, const std::string& queue, const std::string& key);
- BrokerEventImpl::Ptr eventSetupComplete();
- BrokerEventImpl::Ptr eventStable();
- BrokerEventImpl::Ptr eventQueryComplete(void* context, QueryResponsePtr response);
- BrokerEventImpl::Ptr eventMethodResponse(void* context, MethodResponsePtr response);
-
- void handleBrokerResponse(qpid::framing::Buffer& inBuffer, uint32_t seq);
- void handlePackageIndication(qpid::framing::Buffer& inBuffer, uint32_t seq);
- void handleCommandComplete(qpid::framing::Buffer& inBuffer, uint32_t seq);
- void handleClassIndication(qpid::framing::Buffer& inBuffer, uint32_t seq);
- MethodResponsePtr handleMethodResponse(qpid::framing::Buffer& inBuffer, uint32_t seq, const SchemaMethod* schema);
- void handleHeartbeatIndication(qpid::framing::Buffer& inBuffer, uint32_t seq, const std::string& routingKey);
- void handleEventIndication(qpid::framing::Buffer& inBuffer, uint32_t seq);
- void handleSchemaResponse(qpid::framing::Buffer& inBuffer, uint32_t seq);
- ObjectPtr handleObjectIndication(qpid::framing::Buffer& inBuffer, uint32_t seq, bool prop, bool stat);
- void updateAgentList(ObjectPtr obj);
- void incOutstandingLH();
- void decOutstanding();
- };
-
- //
- // StaticContext is used to handle:
- //
- // 1) Responses to console-level requests (for schema info, etc.)
- // 2) Unsolicited messages from agents (events, published updates, etc.)
- //
- struct StaticContext : public SequenceContext {
- StaticContext(BrokerProxyImpl& b) : broker(b) {}
- virtual ~StaticContext() {}
- void reserve() {}
- void release() { broker.staticRelease(); }
- bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer);
- BrokerProxyImpl& broker;
- };
-
- //
- // QueryContext is used to track and handle responses associated with a single Get Query
- //
- struct QueryContext : public SequenceContext {
- QueryContext(BrokerProxyImpl& b, void* u) :
- broker(b), userContext(u), requestsOutstanding(0), queryResponse(QueryResponseImpl::factory()) {}
- virtual ~QueryContext() {}
- void reserve();
- void release();
- bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer);
-
- mutable qpid::sys::Mutex lock;
- BrokerProxyImpl& broker;
- void* userContext;
- uint32_t requestsOutstanding;
- QueryResponsePtr queryResponse;
- };
-
- struct MethodContext : public SequenceContext {
- MethodContext(BrokerProxyImpl& b, void* u, const SchemaMethod* s) : broker(b), userContext(u), schema(s) {}
- virtual ~MethodContext() {}
- void reserve() {}
- void release();
- bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer);
-
- BrokerProxyImpl& broker;
- void* userContext;
- const SchemaMethod* schema;
- MethodResponsePtr methodResponse;
- };
-
-}
-}
-
-#endif
-
diff --git a/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp b/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp
deleted file mode 100644
index 22a65f28ca..0000000000
--- a/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/ConnectionSettingsImpl.h"
-#include "qmf/engine/Typecode.h"
-
-using namespace std;
-using namespace qmf::engine;
-using namespace qpid;
-
-const string attrProtocol("protocol");
-const string attrHost("host");
-const string attrPort("port");
-const string attrVirtualhost("virtualhost");
-const string attrUsername("username");
-const string attrPassword("password");
-const string attrMechanism("mechanism");
-const string attrLocale("locale");
-const string attrHeartbeat("heartbeat");
-const string attrMaxChannels("maxChannels");
-const string attrMaxFrameSize("maxFrameSize");
-const string attrBounds("bounds");
-const string attrTcpNoDelay("tcpNoDelay");
-const string attrService("service");
-const string attrMinSsf("minSsf");
-const string attrMaxSsf("maxSsf");
-const string attrRetryDelayMin("retryDelayMin");
-const string attrRetryDelayMax("retryDelayMax");
-const string attrRetryDelayFactor("retryDelayFactor");
-const string attrSendUserId("sendUserId");
-
-ConnectionSettingsImpl::ConnectionSettingsImpl() :
- retryDelayMin(1), retryDelayMax(64), retryDelayFactor(2), sendUserId(true)
-{
-}
-
-ConnectionSettingsImpl::ConnectionSettingsImpl(const string& /*url*/) :
- retryDelayMin(1), retryDelayMax(64), retryDelayFactor(2), sendUserId(true)
-{
- // TODO: Parse the URL
-}
-
-bool ConnectionSettingsImpl::setAttr(const string& key, const Value& value)
-{
- if (key == attrProtocol) clientSettings.protocol = value.asString();
- else if (key == attrHost) clientSettings.host = value.asString();
- else if (key == attrPort) clientSettings.port = value.asUint();
- else if (key == attrVirtualhost) clientSettings.virtualhost = value.asString();
- else if (key == attrUsername) clientSettings.username = value.asString();
- else if (key == attrPassword) clientSettings.password = value.asString();
- else if (key == attrMechanism) clientSettings.mechanism = value.asString();
- else if (key == attrLocale) clientSettings.locale = value.asString();
- else if (key == attrHeartbeat) clientSettings.heartbeat = value.asUint();
- else if (key == attrMaxChannels) clientSettings.maxChannels = value.asUint();
- else if (key == attrMaxFrameSize) clientSettings.maxFrameSize = value.asUint();
- else if (key == attrBounds) clientSettings.bounds = value.asUint();
- else if (key == attrTcpNoDelay) clientSettings.tcpNoDelay = value.asBool();
- else if (key == attrService) clientSettings.service = value.asString();
- else if (key == attrMinSsf) clientSettings.minSsf = value.asUint();
- else if (key == attrMaxSsf) clientSettings.maxSsf = value.asUint();
-
- else if (key == attrRetryDelayMin) retryDelayMin = value.asUint();
- else if (key == attrRetryDelayMax) retryDelayMax = value.asUint();
- else if (key == attrRetryDelayFactor) retryDelayFactor = value.asUint();
- else if (key == attrSendUserId) sendUserId = value.asBool();
- else
- return false;
- return true;
-}
-
-Value ConnectionSettingsImpl::getAttr(const string& key) const
-{
- Value strval(TYPE_LSTR);
- Value intval(TYPE_UINT32);
- Value boolval(TYPE_BOOL);
-
- if (key == attrProtocol) {
- strval.setString(clientSettings.protocol.c_str());
- return strval;
- }
-
- if (key == attrHost) {
- strval.setString(clientSettings.host.c_str());
- return strval;
- }
-
- if (key == attrPort) {
- intval.setUint(clientSettings.port);
- return intval;
- }
-
- if (key == attrVirtualhost) {
- strval.setString(clientSettings.virtualhost.c_str());
- return strval;
- }
-
- if (key == attrUsername) {
- strval.setString(clientSettings.username.c_str());
- return strval;
- }
-
- if (key == attrPassword) {
- strval.setString(clientSettings.password.c_str());
- return strval;
- }
-
- if (key == attrMechanism) {
- strval.setString(clientSettings.mechanism.c_str());
- return strval;
- }
-
- if (key == attrLocale) {
- strval.setString(clientSettings.locale.c_str());
- return strval;
- }
-
- if (key == attrHeartbeat) {
- intval.setUint(clientSettings.heartbeat);
- return intval;
- }
-
- if (key == attrMaxChannels) {
- intval.setUint(clientSettings.maxChannels);
- return intval;
- }
-
- if (key == attrMaxFrameSize) {
- intval.setUint(clientSettings.maxFrameSize);
- return intval;
- }
-
- if (key == attrBounds) {
- intval.setUint(clientSettings.bounds);
- return intval;
- }
-
- if (key == attrTcpNoDelay) {
- boolval.setBool(clientSettings.tcpNoDelay);
- return boolval;
- }
-
- if (key == attrService) {
- strval.setString(clientSettings.service.c_str());
- return strval;
- }
-
- if (key == attrMinSsf) {
- intval.setUint(clientSettings.minSsf);
- return intval;
- }
-
- if (key == attrMaxSsf) {
- intval.setUint(clientSettings.maxSsf);
- return intval;
- }
-
- if (key == attrRetryDelayMin) {
- intval.setUint(retryDelayMin);
- return intval;
- }
-
- if (key == attrRetryDelayMax) {
- intval.setUint(retryDelayMax);
- return intval;
- }
-
- if (key == attrRetryDelayFactor) {
- intval.setUint(retryDelayFactor);
- return intval;
- }
-
- if (key == attrSendUserId) {
- boolval.setBool(sendUserId);
- return boolval;
- }
-
- return strval;
-}
-
-const string& ConnectionSettingsImpl::getAttrString() const
-{
- // TODO: build and return attribute string
- return attrString;
-}
-
-void ConnectionSettingsImpl::transportTcp(uint16_t port)
-{
- clientSettings.protocol = "tcp";
- clientSettings.port = port;
-}
-
-void ConnectionSettingsImpl::transportSsl(uint16_t port)
-{
- clientSettings.protocol = "ssl";
- clientSettings.port = port;
-}
-
-void ConnectionSettingsImpl::transportRdma(uint16_t port)
-{
- clientSettings.protocol = "rdma";
- clientSettings.port = port;
-}
-
-void ConnectionSettingsImpl::authAnonymous(const string& username)
-{
- clientSettings.mechanism = "ANONYMOUS";
- clientSettings.username = username;
-}
-
-void ConnectionSettingsImpl::authPlain(const string& username, const string& password)
-{
- clientSettings.mechanism = "PLAIN";
- clientSettings.username = username;
- clientSettings.password = password;
-}
-
-void ConnectionSettingsImpl::authGssapi(const string& serviceName, uint32_t minSsf, uint32_t maxSsf)
-{
- clientSettings.mechanism = "GSSAPI";
- clientSettings.service = serviceName;
- clientSettings.minSsf = minSsf;
- clientSettings.maxSsf = maxSsf;
-}
-
-void ConnectionSettingsImpl::setRetry(int delayMin, int delayMax, int delayFactor)
-{
- retryDelayMin = delayMin;
- retryDelayMax = delayMax;
- retryDelayFactor = delayFactor;
-}
-
-const client::ConnectionSettings& ConnectionSettingsImpl::getClientSettings() const
-{
- return clientSettings;
-}
-
-void ConnectionSettingsImpl::getRetrySettings(int* min, int* max, int* factor) const
-{
- *min = retryDelayMin;
- *max = retryDelayMax;
- *factor = retryDelayFactor;
-}
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-ConnectionSettings::ConnectionSettings(const ConnectionSettings& from) { impl = new ConnectionSettingsImpl(*from.impl); }
-ConnectionSettings::ConnectionSettings() { impl = new ConnectionSettingsImpl(); }
-ConnectionSettings::ConnectionSettings(const char* url) { impl = new ConnectionSettingsImpl(url); }
-ConnectionSettings::~ConnectionSettings() { delete impl; }
-bool ConnectionSettings::setAttr(const char* key, const Value& value) { return impl->setAttr(key, value); }
-Value ConnectionSettings::getAttr(const char* key) const { return impl->getAttr(key); }
-const char* ConnectionSettings::getAttrString() const { return impl->getAttrString().c_str(); }
-void ConnectionSettings::transportTcp(uint16_t port) { impl->transportTcp(port); }
-void ConnectionSettings::transportSsl(uint16_t port) { impl->transportSsl(port); }
-void ConnectionSettings::transportRdma(uint16_t port) { impl->transportRdma(port); }
-void ConnectionSettings::authAnonymous(const char* username) { impl->authAnonymous(username); }
-void ConnectionSettings::authPlain(const char* username, const char* password) { impl->authPlain(username, password); }
-void ConnectionSettings::authGssapi(const char* serviceName, uint32_t minSsf, uint32_t maxSsf) { impl->authGssapi(serviceName, minSsf, maxSsf); }
-void ConnectionSettings::setRetry(int delayMin, int delayMax, int delayFactor) { impl->setRetry(delayMin, delayMax, delayFactor); }
-
diff --git a/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.h b/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.h
deleted file mode 100644
index 98bf87868b..0000000000
--- a/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef _QmfEngineConnectionSettingsImpl_
-#define _QmfEngineConnectionSettingsImpl_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/ConnectionSettings.h"
-#include "qmf/engine/Value.h"
-#include "qpid/client/ConnectionSettings.h"
-#include <string>
-#include <map>
-
-namespace qmf {
-namespace engine {
-
- class ConnectionSettingsImpl {
- qpid::client::ConnectionSettings clientSettings;
- mutable std::string attrString;
- int retryDelayMin;
- int retryDelayMax;
- int retryDelayFactor;
- bool sendUserId;
-
- public:
- ConnectionSettingsImpl();
- ConnectionSettingsImpl(const std::string& url);
- ~ConnectionSettingsImpl() {}
- bool setAttr(const std::string& key, const Value& value);
- Value getAttr(const std::string& key) const;
- const std::string& getAttrString() const;
- void transportTcp(uint16_t port);
- void transportSsl(uint16_t port);
- void transportRdma(uint16_t port);
- void authAnonymous(const std::string& username);
- void authPlain(const std::string& username, const std::string& password);
- void authGssapi(const std::string& serviceName, uint32_t minSsf, uint32_t maxSsf);
- void setRetry(int delayMin, int delayMax, int delayFactor);
-
- const qpid::client::ConnectionSettings& getClientSettings() const;
- void getRetrySettings(int* delayMin, int* delayMax, int* delayFactor) const;
- bool getSendUserId() const { return sendUserId; }
- };
-
-}
-}
-
-#endif
diff --git a/qpid/cpp/src/qmf/engine/ConsoleImpl.cpp b/qpid/cpp/src/qmf/engine/ConsoleImpl.cpp
deleted file mode 100644
index 4a5da31bdc..0000000000
--- a/qpid/cpp/src/qmf/engine/ConsoleImpl.cpp
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/ConsoleImpl.h"
-#include "qmf/engine/MessageImpl.h"
-#include "qmf/engine/SchemaImpl.h"
-#include "qmf/engine/Typecode.h"
-#include "qmf/engine/ObjectImpl.h"
-#include "qmf/engine/ObjectIdImpl.h"
-#include "qmf/engine/QueryImpl.h"
-#include "qmf/engine/ValueImpl.h"
-#include "qmf/engine/Protocol.h"
-#include "qmf/engine/SequenceManager.h"
-#include "qmf/engine/BrokerProxyImpl.h"
-#include <qpid/framing/Buffer.h>
-#include <qpid/framing/Uuid.h>
-#include <qpid/framing/FieldTable.h>
-#include <qpid/framing/FieldValue.h>
-#include <qpid/log/Statement.h>
-#include <qpid/sys/Time.h>
-#include <qpid/sys/SystemInfo.h>
-#include <string.h>
-#include <iostream>
-#include <fstream>
-
-using namespace std;
-using namespace qmf::engine;
-using namespace qpid::framing;
-using namespace qpid::sys;
-
-namespace {
- const char* QMF_EXCHANGE = "qpid.management";
-}
-
-#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());}
-
-ConsoleEvent ConsoleEventImpl::copy()
-{
- ConsoleEvent item;
-
- ::memset(&item, 0, sizeof(ConsoleEvent));
- item.kind = kind;
- item.agent = agent.get();
- item.classKey = classKey;
- item.object = object.get();
- item.context = context;
- item.event = event.get();
- item.timestamp = timestamp;
- item.hasProps = hasProps;
- item.hasStats = hasStats;
-
- STRING_REF(name);
-
- return item;
-}
-
-ConsoleImpl::ConsoleImpl(const ConsoleSettings& s) : settings(s)
-{
- bindingList.push_back(pair<string, string>(string(), "schema.#"));
- if (settings.rcvObjects && settings.rcvEvents && settings.rcvHeartbeats && !settings.userBindings) {
- bindingList.push_back(pair<string, string>(string(), "console.#"));
- } else {
- if (settings.rcvObjects && !settings.userBindings)
- bindingList.push_back(pair<string, string>(string(), "console.obj.#"));
- else
- bindingList.push_back(pair<string, string>(string(), "console.obj.*.*.org.apache.qpid.broker.agent"));
- if (settings.rcvEvents)
- bindingList.push_back(pair<string, string>(string(), "console.event.#"));
- if (settings.rcvHeartbeats)
- bindingList.push_back(pair<string, string>(string(), "console.heartbeat.#"));
- }
-}
-
-ConsoleImpl::~ConsoleImpl()
-{
- // This function intentionally left blank.
-}
-
-bool ConsoleImpl::getEvent(ConsoleEvent& event) const
-{
- Mutex::ScopedLock _lock(lock);
- if (eventQueue.empty())
- return false;
- event = eventQueue.front()->copy();
- return true;
-}
-
-void ConsoleImpl::popEvent()
-{
- Mutex::ScopedLock _lock(lock);
- if (!eventQueue.empty())
- eventQueue.pop_front();
-}
-
-void ConsoleImpl::addConnection(BrokerProxy& broker, void* /*context*/)
-{
- Mutex::ScopedLock _lock(lock);
- brokerList.push_back(broker.impl);
-}
-
-void ConsoleImpl::delConnection(BrokerProxy& broker)
-{
- Mutex::ScopedLock _lock(lock);
- for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
- iter != brokerList.end(); iter++)
- if (*iter == broker.impl) {
- brokerList.erase(iter);
- break;
- }
-}
-
-uint32_t ConsoleImpl::packageCount() const
-{
- Mutex::ScopedLock _lock(lock);
- return packages.size();
-}
-
-const string& ConsoleImpl::getPackageName(uint32_t idx) const
-{
- const static string empty;
-
- Mutex::ScopedLock _lock(lock);
- if (idx >= packages.size())
- return empty;
-
- PackageList::const_iterator iter = packages.begin();
- for (uint32_t i = 0; i < idx; i++) iter++;
- return iter->first;
-}
-
-uint32_t ConsoleImpl::classCount(const char* packageName) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(packageName);
- if (pIter == packages.end())
- return 0;
-
- const ObjectClassList& oList = pIter->second.first;
- const EventClassList& eList = pIter->second.second;
-
- return oList.size() + eList.size();
-}
-
-const SchemaClassKey* ConsoleImpl::getClass(const char* packageName, uint32_t idx) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(packageName);
- if (pIter == packages.end())
- return 0;
-
- const ObjectClassList& oList = pIter->second.first;
- const EventClassList& eList = pIter->second.second;
- uint32_t count = 0;
-
- for (ObjectClassList::const_iterator oIter = oList.begin();
- oIter != oList.end(); oIter++) {
- if (count == idx)
- return oIter->second->getClassKey();
- count++;
- }
-
- for (EventClassList::const_iterator eIter = eList.begin();
- eIter != eList.end(); eIter++) {
- if (count == idx)
- return eIter->second->getClassKey();
- count++;
- }
-
- return 0;
-}
-
-ClassKind ConsoleImpl::getClassKind(const SchemaClassKey* key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return CLASS_OBJECT;
-
- const EventClassList& eList = pIter->second.second;
- if (eList.find(key) != eList.end())
- return CLASS_EVENT;
- return CLASS_OBJECT;
-}
-
-const SchemaObjectClass* ConsoleImpl::getObjectClass(const SchemaClassKey* key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return 0;
-
- const ObjectClassList& oList = pIter->second.first;
- ObjectClassList::const_iterator iter = oList.find(key);
- if (iter == oList.end())
- return 0;
- return iter->second;
-}
-
-const SchemaEventClass* ConsoleImpl::getEventClass(const SchemaClassKey* key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return 0;
-
- const EventClassList& eList = pIter->second.second;
- EventClassList::const_iterator iter = eList.find(key);
- if (iter == eList.end())
- return 0;
- return iter->second;
-}
-
-void ConsoleImpl::bindPackage(const char* packageName)
-{
- stringstream key;
- key << "console.obj.*.*." << packageName << ".#";
- Mutex::ScopedLock _lock(lock);
- bindingList.push_back(pair<string, string>(string(), key.str()));
- for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
- iter != brokerList.end(); iter++)
- (*iter)->addBinding(QMF_EXCHANGE, key.str());
-}
-
-void ConsoleImpl::bindClass(const SchemaClassKey* classKey)
-{
- stringstream key;
- key << "console.obj.*.*." << classKey->getPackageName() << "." << classKey->getClassName() << ".#";
- Mutex::ScopedLock _lock(lock);
- bindingList.push_back(pair<string, string>(string(), key.str()));
- for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
- iter != brokerList.end(); iter++)
- (*iter)->addBinding(QMF_EXCHANGE, key.str());
-}
-
-void ConsoleImpl::bindClass(const char* packageName, const char* className)
-{
- stringstream key;
- key << "console.obj.*.*." << packageName << "." << className << ".#";
- Mutex::ScopedLock _lock(lock);
- bindingList.push_back(pair<string, string>(string(), key.str()));
- for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
- iter != brokerList.end(); iter++)
- (*iter)->addBinding(QMF_EXCHANGE, key.str());
-}
-
-
-void ConsoleImpl::bindEvent(const SchemaClassKey* classKey)
-{
- bindEvent(classKey->getPackageName(), classKey->getClassName());
-}
-
-void ConsoleImpl::bindEvent(const char* packageName, const char* eventName)
-{
- if (!settings.userBindings) throw qpid::Exception("Console not configured for userBindings.");
- if (settings.rcvEvents) throw qpid::Exception("Console already configured to receive all events.");
-
- stringstream key;
- key << "console.event.*.*." << packageName;
- if (eventName && *eventName) {
- key << "." << eventName << ".#";
- } else {
- key << ".#";
- }
-
- Mutex::ScopedLock _lock(lock);
- bindingList.push_back(pair<string, string>(string(), key.str()));
- for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
- iter != brokerList.end(); iter++)
- (*iter)->addBinding(QMF_EXCHANGE, key.str());
-}
-
-/*
-void ConsoleImpl::startSync(const Query& query, void* context, SyncQuery& sync)
-{
-}
-
-void ConsoleImpl::touchSync(SyncQuery& sync)
-{
-}
-
-void ConsoleImpl::endSync(SyncQuery& sync)
-{
-}
-*/
-
-void ConsoleImpl::learnPackage(const string& packageName)
-{
- Mutex::ScopedLock _lock(lock);
- if (packages.find(packageName) == packages.end()) {
- packages.insert(pair<string, pair<ObjectClassList, EventClassList> >
- (packageName, pair<ObjectClassList, EventClassList>(ObjectClassList(), EventClassList())));
- eventNewPackage(packageName);
- }
-}
-
-void ConsoleImpl::learnClass(SchemaObjectClass* cls)
-{
- Mutex::ScopedLock _lock(lock);
- const SchemaClassKey* key = cls->getClassKey();
- PackageList::iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return;
-
- ObjectClassList& list = pIter->second.first;
- if (list.find(key) == list.end()) {
- list[key] = cls;
- eventNewClass(key);
- }
-}
-
-void ConsoleImpl::learnClass(SchemaEventClass* cls)
-{
- Mutex::ScopedLock _lock(lock);
- const SchemaClassKey* key = cls->getClassKey();
- PackageList::iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return;
-
- EventClassList& list = pIter->second.second;
- if (list.find(key) == list.end()) {
- list[key] = cls;
- eventNewClass(key);
- }
-}
-
-bool ConsoleImpl::haveClass(const SchemaClassKey* key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return false;
-
- const ObjectClassList& oList = pIter->second.first;
- const EventClassList& eList = pIter->second.second;
-
- return oList.find(key) != oList.end() || eList.find(key) != eList.end();
-}
-
-SchemaObjectClass* ConsoleImpl::getSchema(const SchemaClassKey* key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return 0;
-
- const ObjectClassList& oList = pIter->second.first;
- ObjectClassList::const_iterator iter = oList.find(key);
- if (iter == oList.end())
- return 0;
-
- return iter->second;
-}
-
-void ConsoleImpl::eventAgentAdded(boost::shared_ptr<AgentProxy> agent)
-{
- ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::AGENT_ADDED));
- event->agent = agent;
- Mutex::ScopedLock _lock(lock);
- eventQueue.push_back(event);
-}
-
-void ConsoleImpl::eventAgentDeleted(boost::shared_ptr<AgentProxy> agent)
-{
- ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::AGENT_DELETED));
- event->agent = agent;
- Mutex::ScopedLock _lock(lock);
- eventQueue.push_back(event);
-}
-
-void ConsoleImpl::eventNewPackage(const string& packageName)
-{
- ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::NEW_PACKAGE));
- event->name = packageName;
- Mutex::ScopedLock _lock(lock);
- eventQueue.push_back(event);
-}
-
-void ConsoleImpl::eventNewClass(const SchemaClassKey* key)
-{
- ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::NEW_CLASS));
- event->classKey = key;
- Mutex::ScopedLock _lock(lock);
- eventQueue.push_back(event);
-}
-
-void ConsoleImpl::eventObjectUpdate(ObjectPtr object, bool prop, bool stat)
-{
- ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::OBJECT_UPDATE));
- event->object = object;
- event->hasProps = prop;
- event->hasStats = stat;
- Mutex::ScopedLock _lock(lock);
- eventQueue.push_back(event);
-}
-
-void ConsoleImpl::eventAgentHeartbeat(boost::shared_ptr<AgentProxy> agent, uint64_t timestamp)
-{
- ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::AGENT_HEARTBEAT));
- event->agent = agent;
- event->timestamp = timestamp;
- Mutex::ScopedLock _lock(lock);
- eventQueue.push_back(event);
-}
-
-
-void ConsoleImpl::eventEventReceived(EventPtr event)
-{
- ConsoleEventImpl::Ptr console_event(new ConsoleEventImpl(ConsoleEvent::EVENT_RECEIVED));
- console_event->event = event;
- Mutex::ScopedLock _lock(lock);
- eventQueue.push_back(console_event);
-}
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-Console::Console(const ConsoleSettings& settings) : impl(new ConsoleImpl(settings)) {}
-Console::~Console() { delete impl; }
-bool Console::getEvent(ConsoleEvent& event) const { return impl->getEvent(event); }
-void Console::popEvent() { impl->popEvent(); }
-void Console::addConnection(BrokerProxy& broker, void* context) { impl->addConnection(broker, context); }
-void Console::delConnection(BrokerProxy& broker) { impl->delConnection(broker); }
-uint32_t Console::packageCount() const { return impl->packageCount(); }
-const char* Console::getPackageName(uint32_t idx) const { return impl->getPackageName(idx).c_str(); }
-uint32_t Console::classCount(const char* packageName) const { return impl->classCount(packageName); }
-const SchemaClassKey* Console::getClass(const char* packageName, uint32_t idx) const { return impl->getClass(packageName, idx); }
-ClassKind Console::getClassKind(const SchemaClassKey* key) const { return impl->getClassKind(key); }
-const SchemaObjectClass* Console::getObjectClass(const SchemaClassKey* key) const { return impl->getObjectClass(key); }
-const SchemaEventClass* Console::getEventClass(const SchemaClassKey* key) const { return impl->getEventClass(key); }
-void Console::bindPackage(const char* packageName) { impl->bindPackage(packageName); }
-void Console::bindClass(const SchemaClassKey* key) { impl->bindClass(key); }
-void Console::bindClass(const char* packageName, const char* className) { impl->bindClass(packageName, className); }
-
-void Console::bindEvent(const SchemaClassKey *key) { impl->bindEvent(key); }
-void Console::bindEvent(const char* packageName, const char* eventName) { impl->bindEvent(packageName, eventName); }
-
-//void Console::startSync(const Query& query, void* context, SyncQuery& sync) { impl->startSync(query, context, sync); }
-//void Console::touchSync(SyncQuery& sync) { impl->touchSync(sync); }
-//void Console::endSync(SyncQuery& sync) { impl->endSync(sync); }
-
-
diff --git a/qpid/cpp/src/qmf/engine/ConsoleImpl.h b/qpid/cpp/src/qmf/engine/ConsoleImpl.h
deleted file mode 100644
index 0c27fdabcd..0000000000
--- a/qpid/cpp/src/qmf/engine/ConsoleImpl.h
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef _QmfEngineConsoleEngineImpl_
-#define _QmfEngineConsoleEngineImpl_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/Console.h"
-#include "qmf/engine/MessageImpl.h"
-#include "qmf/engine/SchemaImpl.h"
-#include "qmf/engine/Typecode.h"
-#include "qmf/engine/ObjectImpl.h"
-#include "qmf/engine/ObjectIdImpl.h"
-#include "qmf/engine/QueryImpl.h"
-#include "qmf/engine/ValueImpl.h"
-#include "qmf/engine/Protocol.h"
-#include "qmf/engine/SequenceManager.h"
-#include "qmf/engine/BrokerProxyImpl.h"
-#include <qpid/framing/Buffer.h>
-#include <qpid/framing/Uuid.h>
-#include <qpid/framing/FieldTable.h>
-#include <qpid/framing/FieldValue.h>
-#include <qpid/sys/Mutex.h>
-#include <qpid/sys/Time.h>
-#include <qpid/sys/SystemInfo.h>
-#include <string.h>
-#include <string>
-#include <deque>
-#include <map>
-#include <vector>
-#include <iostream>
-#include <fstream>
-#include <boost/shared_ptr.hpp>
-#include <boost/noncopyable.hpp>
-
-namespace qmf {
-namespace engine {
-
- struct ConsoleEventImpl {
- typedef boost::shared_ptr<ConsoleEventImpl> Ptr;
- ConsoleEvent::EventKind kind;
- boost::shared_ptr<AgentProxy> agent;
- std::string name;
- const SchemaClassKey* classKey;
- boost::shared_ptr<Object> object;
- void* context;
- boost::shared_ptr<Event> event;
- uint64_t timestamp;
- bool hasProps;
- bool hasStats;
-
- ConsoleEventImpl(ConsoleEvent::EventKind k) :
- kind(k), classKey(0), context(0), timestamp(0) {}
- ~ConsoleEventImpl() {}
- ConsoleEvent copy();
- };
-
- class ConsoleImpl : public boost::noncopyable {
- public:
- ConsoleImpl(const ConsoleSettings& settings = ConsoleSettings());
- ~ConsoleImpl();
-
- bool getEvent(ConsoleEvent& event) const;
- void popEvent();
-
- void addConnection(BrokerProxy& broker, void* context);
- void delConnection(BrokerProxy& broker);
-
- uint32_t packageCount() const;
- const std::string& getPackageName(uint32_t idx) const;
-
- uint32_t classCount(const char* packageName) const;
- const SchemaClassKey* getClass(const char* packageName, uint32_t idx) const;
-
- ClassKind getClassKind(const SchemaClassKey* key) const;
- const SchemaObjectClass* getObjectClass(const SchemaClassKey* key) const;
- const SchemaEventClass* getEventClass(const SchemaClassKey* key) const;
-
- void bindPackage(const char* packageName);
- void bindClass(const SchemaClassKey* key);
- void bindClass(const char* packageName, const char* className);
- void bindEvent(const SchemaClassKey* key);
- void bindEvent(const char* packageName, const char* eventName);
-
- /*
- void startSync(const Query& query, void* context, SyncQuery& sync);
- void touchSync(SyncQuery& sync);
- void endSync(SyncQuery& sync);
- */
-
- private:
- friend class BrokerProxyImpl;
- friend struct StaticContext;
- const ConsoleSettings& settings;
- mutable qpid::sys::Mutex lock;
- std::deque<ConsoleEventImpl::Ptr> eventQueue;
- std::vector<BrokerProxyImpl*> brokerList;
- std::vector<std::pair<std::string, std::string> > bindingList; // exchange/key (empty exchange => QMF_EXCHANGE)
-
- // Declare a compare class for the class maps that compares the dereferenced
- // class key pointers. The default behavior would be to compare the pointer
- // addresses themselves.
- struct KeyCompare {
- bool operator()(const SchemaClassKey* left, const SchemaClassKey* right) const {
- return *left < *right;
- }
- };
-
- typedef std::map<const SchemaClassKey*, SchemaObjectClass*, KeyCompare> ObjectClassList;
- typedef std::map<const SchemaClassKey*, SchemaEventClass*, KeyCompare> EventClassList;
- typedef std::map<std::string, std::pair<ObjectClassList, EventClassList> > PackageList;
-
- PackageList packages;
-
- void learnPackage(const std::string& packageName);
- void learnClass(SchemaObjectClass* cls);
- void learnClass(SchemaEventClass* cls);
- bool haveClass(const SchemaClassKey* key) const;
- SchemaObjectClass* getSchema(const SchemaClassKey* key) const;
-
- void eventAgentAdded(boost::shared_ptr<AgentProxy> agent);
- void eventAgentDeleted(boost::shared_ptr<AgentProxy> agent);
- void eventNewPackage(const std::string& packageName);
- void eventNewClass(const SchemaClassKey* key);
- void eventObjectUpdate(ObjectPtr object, bool prop, bool stat);
- void eventAgentHeartbeat(boost::shared_ptr<AgentProxy> agent, uint64_t timestamp);
- void eventEventReceived(boost::shared_ptr<Event> event);
- };
-}
-}
-
-#endif
-
diff --git a/qpid/cpp/src/qmf/engine/EventImpl.cpp b/qpid/cpp/src/qmf/engine/EventImpl.cpp
deleted file mode 100644
index 4b034e8e83..0000000000
--- a/qpid/cpp/src/qmf/engine/EventImpl.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <qmf/engine/EventImpl.h>
-#include <qmf/engine/ValueImpl.h>
-
-#include <sstream>
-
-using namespace std;
-using namespace qmf::engine;
-using qpid::framing::Buffer;
-
-EventImpl::EventImpl(const SchemaEventClass* type) : eventClass(type), timestamp(0), severity(0)
-{
- int argCount = eventClass->getArgumentCount();
- int idx;
-
- for (idx = 0; idx < argCount; idx++) {
- const SchemaArgument* arg = eventClass->getArgument(idx);
- arguments[arg->getName()] = ValuePtr(new Value(arg->getType()));
- }
-}
-
-
-EventImpl::EventImpl(const SchemaEventClass* type, Buffer& buffer) :
- eventClass(type), timestamp(0), severity(0)
-{
- int argCount = eventClass->getArgumentCount();
- int idx;
-
- timestamp = buffer.getLongLong();
- severity = buffer.getOctet();
-
- for (idx = 0; idx < argCount; idx++)
- {
- const SchemaArgument *arg = eventClass->getArgument(idx);
- Value* pval = ValueImpl::factory(arg->getType(), buffer);
- arguments[arg->getName()] = ValuePtr(pval);
- }
-}
-
-
-Event* EventImpl::factory(const SchemaEventClass* type, Buffer& buffer)
-{
- EventImpl* impl(new EventImpl(type, buffer));
- return new Event(impl);
-}
-
-
-Value* EventImpl::getValue(const char* key) const
-{
- map<string, ValuePtr>::const_iterator iter;
-
- iter = arguments.find(key);
- if (iter != arguments.end())
- return iter->second.get();
-
- return 0;
-}
-
-
-void EventImpl::encodeSchemaKey(Buffer& buffer) const
-{
- buffer.putShortString(eventClass->getClassKey()->getPackageName());
- buffer.putShortString(eventClass->getClassKey()->getClassName());
- buffer.putBin128(const_cast<uint8_t*>(eventClass->getClassKey()->getHash()));
-}
-
-
-void EventImpl::encode(Buffer& buffer) const
-{
- buffer.putOctet((uint8_t) eventClass->getSeverity());
-
- int argCount = eventClass->getArgumentCount();
- for (int idx = 0; idx < argCount; idx++) {
- const SchemaArgument* arg = eventClass->getArgument(idx);
- ValuePtr value = arguments[arg->getName()];
- value->impl->encode(buffer);
- }
-}
-
-
-string EventImpl::getRoutingKey(uint32_t brokerBank, uint32_t agentBank) const
-{
- stringstream key;
-
- key << "console.event." << brokerBank << "." << agentBank << "." <<
- eventClass->getClassKey()->getPackageName() << "." <<
- eventClass->getClassKey()->getClassName();
- return key.str();
-}
-
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-Event::Event(const SchemaEventClass* type) : impl(new EventImpl(type)) {}
-Event::Event(EventImpl* i) : impl(i) {}
-Event::Event(const Event& from) : impl(new EventImpl(*(from.impl))) {}
-Event::~Event() { delete impl; }
-const SchemaEventClass* Event::getClass() const { return impl->getClass(); }
-Value* Event::getValue(const char* key) const { return impl->getValue(key); }
-
diff --git a/qpid/cpp/src/qmf/engine/EventImpl.h b/qpid/cpp/src/qmf/engine/EventImpl.h
deleted file mode 100644
index 4046e71ef9..0000000000
--- a/qpid/cpp/src/qmf/engine/EventImpl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef _QmfEngineEventImpl_
-#define _QmfEngineEventImpl_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <qmf/engine/Event.h>
-#include <qmf/engine/Schema.h>
-#include <qpid/framing/Buffer.h>
-#include <boost/shared_ptr.hpp>
-#include <map>
-
-namespace qmf {
-namespace engine {
-
- typedef boost::shared_ptr<Event> EventPtr;
-
- struct EventImpl {
- typedef boost::shared_ptr<Value> ValuePtr;
- const SchemaEventClass* eventClass;
- uint64_t timestamp;
- uint8_t severity;
- mutable std::map<std::string, ValuePtr> arguments;
-
- EventImpl(const SchemaEventClass* type);
- EventImpl(const SchemaEventClass* type, qpid::framing::Buffer& buffer);
- static Event* factory(const SchemaEventClass* type, qpid::framing::Buffer& buffer);
-
- const SchemaEventClass* getClass() const { return eventClass; }
- Value* getValue(const char* key) const;
-
- void encodeSchemaKey(qpid::framing::Buffer& buffer) const;
- void encode(qpid::framing::Buffer& buffer) const;
- std::string getRoutingKey(uint32_t brokerBank, uint32_t agentBank) const;
- };
-
-}
-}
-
-#endif
-
diff --git a/qpid/cpp/src/qmf/engine/ObjectIdImpl.cpp b/qpid/cpp/src/qmf/engine/ObjectIdImpl.cpp
deleted file mode 100644
index 9216f7bac0..0000000000
--- a/qpid/cpp/src/qmf/engine/ObjectIdImpl.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/ObjectIdImpl.h"
-#include <stdlib.h>
-#include <sstream>
-
-using namespace std;
-using namespace qmf::engine;
-using qpid::framing::Buffer;
-
-void AgentAttachment::setBanks(uint32_t broker, uint32_t agent)
-{
- first =
- ((uint64_t) (broker & 0x000fffff)) << 28 |
- ((uint64_t) (agent & 0x0fffffff));
-}
-
-ObjectIdImpl::ObjectIdImpl(Buffer& buffer) : agent(0)
-{
- decode(buffer);
-}
-
-ObjectIdImpl::ObjectIdImpl(AgentAttachment* a, uint8_t flags, uint16_t seq, uint64_t object) : agent(a)
-{
- first =
- ((uint64_t) (flags & 0x0f)) << 60 |
- ((uint64_t) (seq & 0x0fff)) << 48;
- second = object;
-}
-
-ObjectId* ObjectIdImpl::factory(Buffer& buffer)
-{
- ObjectIdImpl* impl(new ObjectIdImpl(buffer));
- return new ObjectId(impl);
-}
-
-ObjectId* ObjectIdImpl::factory(AgentAttachment* agent, uint8_t flags, uint16_t seq, uint64_t object)
-{
- ObjectIdImpl* impl(new ObjectIdImpl(agent, flags, seq, object));
- return new ObjectId(impl);
-}
-
-void ObjectIdImpl::decode(Buffer& buffer)
-{
- first = buffer.getLongLong();
- second = buffer.getLongLong();
-}
-
-void ObjectIdImpl::encode(Buffer& buffer) const
-{
- if (agent == 0)
- buffer.putLongLong(first);
- else
- buffer.putLongLong(first | agent->first);
- buffer.putLongLong(second);
-}
-
-void ObjectIdImpl::fromString(const std::string& repr)
-{
-#define FIELDS 5
-#if defined (_WIN32) && !defined (atoll)
-# define atoll(X) _atoi64(X)
-#endif
-
- std::string copy(repr.c_str());
- char* cText;
- char* field[FIELDS];
- bool atFieldStart = true;
- int idx = 0;
-
- cText = const_cast<char*>(copy.c_str());
- for (char* cursor = cText; *cursor; cursor++) {
- if (atFieldStart) {
- if (idx >= FIELDS)
- return; // TODO error
- field[idx++] = cursor;
- atFieldStart = false;
- } else {
- if (*cursor == '-') {
- *cursor = '\0';
- atFieldStart = true;
- }
- }
- }
-
- if (idx != FIELDS)
- return; // TODO error
-
- first = (atoll(field[0]) << 60) +
- (atoll(field[1]) << 48) +
- (atoll(field[2]) << 28) +
- atoll(field[3]);
- second = atoll(field[4]);
- agent = 0;
-}
-
-const string& ObjectIdImpl::asString() const
-{
- stringstream val;
-
- val << (int) getFlags() << "-" << getSequence() << "-" << getBrokerBank() << "-" <<
- getAgentBank() << "-" << getObjectNum();
- repr = val.str();
- return repr;
-}
-
-#define ACTUAL_FIRST (agent == 0 ? first : first | agent->first)
-#define ACTUAL_OTHER (other.agent == 0 ? other.first : other.first | other.agent->first)
-
-uint8_t ObjectIdImpl::getFlags() const
-{
- return (ACTUAL_FIRST & 0xF000000000000000LL) >> 60;
-}
-
-uint16_t ObjectIdImpl::getSequence() const
-{
- return (ACTUAL_FIRST & 0x0FFF000000000000LL) >> 48;
-}
-
-uint32_t ObjectIdImpl::getBrokerBank() const
-{
- return (ACTUAL_FIRST & 0x0000FFFFF0000000LL) >> 28;
-}
-
-uint32_t ObjectIdImpl::getAgentBank() const
-{
- return ACTUAL_FIRST & 0x000000000FFFFFFFLL;
-}
-
-uint64_t ObjectIdImpl::getObjectNum() const
-{
- return second;
-}
-
-uint32_t ObjectIdImpl::getObjectNumHi() const
-{
- return (uint32_t) (second >> 32);
-}
-
-uint32_t ObjectIdImpl::getObjectNumLo() const
-{
- return (uint32_t) (second & 0x00000000FFFFFFFFLL);
-}
-
-bool ObjectIdImpl::operator==(const ObjectIdImpl& other) const
-{
- return ACTUAL_FIRST == ACTUAL_OTHER && second == other.second;
-}
-
-bool ObjectIdImpl::operator<(const ObjectIdImpl& other) const
-{
- return (ACTUAL_FIRST < ACTUAL_OTHER) || ((ACTUAL_FIRST == ACTUAL_OTHER) && (second < other.second));
-}
-
-bool ObjectIdImpl::operator>(const ObjectIdImpl& other) const
-{
- return (ACTUAL_FIRST > ACTUAL_OTHER) || ((ACTUAL_FIRST == ACTUAL_OTHER) && (second > other.second));
-}
-
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-ObjectId::ObjectId() : impl(new ObjectIdImpl()) {}
-ObjectId::ObjectId(const ObjectId& from) : impl(new ObjectIdImpl(*(from.impl))) {}
-ObjectId::ObjectId(ObjectIdImpl* i) : impl(i) {}
-ObjectId::~ObjectId() { delete impl; }
-uint64_t ObjectId::getObjectNum() const { return impl->getObjectNum(); }
-uint32_t ObjectId::getObjectNumHi() const { return impl->getObjectNumHi(); }
-uint32_t ObjectId::getObjectNumLo() const { return impl->getObjectNumLo(); }
-bool ObjectId::isDurable() const { return impl->isDurable(); }
-const char* ObjectId::str() const { return impl->asString().c_str(); }
-uint8_t ObjectId::getFlags() const { return impl->getFlags(); }
-uint16_t ObjectId::getSequence() const { return impl->getSequence(); }
-uint32_t ObjectId::getBrokerBank() const { return impl->getBrokerBank(); }
-uint32_t ObjectId::getAgentBank() const { return impl->getAgentBank(); }
-bool ObjectId::operator==(const ObjectId& other) const { return *impl == *other.impl; }
-bool ObjectId::operator<(const ObjectId& other) const { return *impl < *other.impl; }
-bool ObjectId::operator>(const ObjectId& other) const { return *impl > *other.impl; }
-bool ObjectId::operator<=(const ObjectId& other) const { return !(*impl > *other.impl); }
-bool ObjectId::operator>=(const ObjectId& other) const { return !(*impl < *other.impl); }
-ObjectId& ObjectId::operator=(const ObjectId& other) {
- ObjectIdImpl *old;
- if (this != &other) {
- old = impl;
- impl = new ObjectIdImpl(*(other.impl));
- if (old)
- delete old;
- }
- return *this;
-}
-
diff --git a/qpid/cpp/src/qmf/engine/ObjectIdImpl.h b/qpid/cpp/src/qmf/engine/ObjectIdImpl.h
deleted file mode 100644
index d70c8efff4..0000000000
--- a/qpid/cpp/src/qmf/engine/ObjectIdImpl.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _QmfEngineObjectIdImpl_
-#define _QmfEngineObjectIdImpl_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <qmf/engine/ObjectId.h>
-#include <qpid/framing/Buffer.h>
-
-namespace qmf {
-namespace engine {
-
- struct AgentAttachment {
- uint64_t first;
-
- AgentAttachment() : first(0) {}
- void setBanks(uint32_t broker, uint32_t bank);
- uint64_t getFirst() const { return first; }
- };
-
- struct ObjectIdImpl {
- AgentAttachment* agent;
- uint64_t first;
- uint64_t second;
- mutable std::string repr;
-
- ObjectIdImpl() : agent(0), first(0), second(0) {}
- ObjectIdImpl(qpid::framing::Buffer& buffer);
- ObjectIdImpl(AgentAttachment* agent, uint8_t flags, uint16_t seq, uint64_t object);
-
- static ObjectId* factory(qpid::framing::Buffer& buffer);
- static ObjectId* factory(AgentAttachment* agent, uint8_t flags, uint16_t seq, uint64_t object);
-
- void decode(qpid::framing::Buffer& buffer);
- void encode(qpid::framing::Buffer& buffer) const;
- void fromString(const std::string& repr);
- const std::string& asString() const;
- uint8_t getFlags() const;
- uint16_t getSequence() const;
- uint32_t getBrokerBank() const;
- uint32_t getAgentBank() const;
- uint64_t getObjectNum() const;
- uint32_t getObjectNumHi() const;
- uint32_t getObjectNumLo() const;
- bool isDurable() const { return getSequence() == 0; }
- void setValue(uint64_t f, uint64_t s) { first = f; second = s; agent = 0; }
-
- bool operator==(const ObjectIdImpl& other) const;
- bool operator<(const ObjectIdImpl& other) const;
- bool operator>(const ObjectIdImpl& other) const;
- };
-}
-}
-
-#endif
-
diff --git a/qpid/cpp/src/qmf/engine/ObjectImpl.cpp b/qpid/cpp/src/qmf/engine/ObjectImpl.cpp
deleted file mode 100644
index 45925cb804..0000000000
--- a/qpid/cpp/src/qmf/engine/ObjectImpl.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/ObjectImpl.h"
-#include "qmf/engine/ValueImpl.h"
-#include "qmf/engine/BrokerProxyImpl.h"
-#include <qpid/sys/Time.h>
-
-using namespace std;
-using namespace qmf::engine;
-using namespace qpid::sys;
-using qpid::framing::Buffer;
-
-ObjectImpl::ObjectImpl(const SchemaObjectClass* type) : objectClass(type), broker(0), createTime(uint64_t(Duration(EPOCH, now()))), destroyTime(0), lastUpdatedTime(createTime)
-{
- int propCount = objectClass->getPropertyCount();
- int statCount = objectClass->getStatisticCount();
- int idx;
-
- for (idx = 0; idx < propCount; idx++) {
- const SchemaProperty* prop = objectClass->getProperty(idx);
- properties[prop->getName()] = ValuePtr(new Value(prop->getType()));
- }
-
- for (idx = 0; idx < statCount; idx++) {
- const SchemaStatistic* stat = objectClass->getStatistic(idx);
- statistics[stat->getName()] = ValuePtr(new Value(stat->getType()));
- }
-}
-
-ObjectImpl::ObjectImpl(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed) :
- objectClass(type), broker(b), createTime(0), destroyTime(0), lastUpdatedTime(0)
-{
- int idx;
-
- if (managed) {
- lastUpdatedTime = buffer.getLongLong();
- createTime = buffer.getLongLong();
- destroyTime = buffer.getLongLong();
- objectId.reset(ObjectIdImpl::factory(buffer));
- }
-
- if (prop) {
- int propCount = objectClass->getPropertyCount();
- set<string> excludes;
- parsePresenceMasks(buffer, excludes);
- for (idx = 0; idx < propCount; idx++) {
- const SchemaProperty* prop = objectClass->getProperty(idx);
- if (excludes.count(prop->getName()) != 0) {
- properties[prop->getName()] = ValuePtr(new Value(prop->getType()));
- } else {
- Value* pval = ValueImpl::factory(prop->getType(), buffer);
- properties[prop->getName()] = ValuePtr(pval);
- }
- }
- }
-
- if (stat) {
- int statCount = objectClass->getStatisticCount();
- for (idx = 0; idx < statCount; idx++) {
- const SchemaStatistic* stat = objectClass->getStatistic(idx);
- Value* sval = ValueImpl::factory(stat->getType(), buffer);
- statistics[stat->getName()] = ValuePtr(sval);
- }
- }
-}
-
-Object* ObjectImpl::factory(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed)
-{
- ObjectImpl* impl(new ObjectImpl(type, b, buffer, prop, stat, managed));
- return new Object(impl);
-}
-
-ObjectImpl::~ObjectImpl()
-{
-}
-
-void ObjectImpl::destroy()
-{
- destroyTime = uint64_t(Duration(EPOCH, now()));
- // TODO - flag deletion
-}
-
-Value* ObjectImpl::getValue(const string& key) const
-{
- map<string, ValuePtr>::const_iterator iter;
-
- iter = properties.find(key);
- if (iter != properties.end())
- return iter->second.get();
-
- iter = statistics.find(key);
- if (iter != statistics.end())
- return iter->second.get();
-
- return 0;
-}
-
-void ObjectImpl::invokeMethod(const string& methodName, const Value* inArgs, void* context) const
-{
- if (broker != 0 && objectId.get() != 0)
- broker->sendMethodRequest(objectId.get(), objectClass, methodName, inArgs, context);
-}
-
-void ObjectImpl::merge(const Object& from)
-{
- for (map<string, ValuePtr>::const_iterator piter = from.impl->properties.begin();
- piter != from.impl->properties.end(); piter++)
- properties[piter->first] = piter->second;
- for (map<string, ValuePtr>::const_iterator siter = from.impl->statistics.begin();
- siter != from.impl->statistics.end(); siter++)
- statistics[siter->first] = siter->second;
-}
-
-void ObjectImpl::parsePresenceMasks(Buffer& buffer, set<string>& excludeList)
-{
- int propCount = objectClass->getPropertyCount();
- excludeList.clear();
- uint8_t bit = 0;
- uint8_t mask = 0;
-
- for (int idx = 0; idx < propCount; idx++) {
- const SchemaProperty* prop = objectClass->getProperty(idx);
- if (prop->isOptional()) {
- if (bit == 0) {
- mask = buffer.getOctet();
- bit = 1;
- }
- if ((mask & bit) == 0)
- excludeList.insert(string(prop->getName()));
- if (bit == 0x80)
- bit = 0;
- else
- bit = bit << 1;
- }
- }
-}
-
-void ObjectImpl::encodeSchemaKey(qpid::framing::Buffer& buffer) const
-{
- buffer.putShortString(objectClass->getClassKey()->getPackageName());
- buffer.putShortString(objectClass->getClassKey()->getClassName());
- buffer.putBin128(const_cast<uint8_t*>(objectClass->getClassKey()->getHash()));
-}
-
-void ObjectImpl::encodeManagedObjectData(qpid::framing::Buffer& buffer) const
-{
- buffer.putLongLong(lastUpdatedTime);
- buffer.putLongLong(createTime);
- buffer.putLongLong(destroyTime);
- objectId->impl->encode(buffer);
-}
-
-void ObjectImpl::encodeProperties(qpid::framing::Buffer& buffer) const
-{
- int propCount = objectClass->getPropertyCount();
- uint8_t bit = 0;
- uint8_t mask = 0;
- ValuePtr value;
-
- for (int idx = 0; idx < propCount; idx++) {
- const SchemaProperty* prop = objectClass->getProperty(idx);
- if (prop->isOptional()) {
- value = properties[prop->getName()];
- if (bit == 0)
- bit = 1;
- if (!value->isNull())
- mask |= bit;
- if (bit == 0x80) {
- buffer.putOctet(mask);
- bit = 0;
- mask = 0;
- } else
- bit = bit << 1;
- }
- }
- if (bit != 0) {
- buffer.putOctet(mask);
- }
-
- for (int idx = 0; idx < propCount; idx++) {
- const SchemaProperty* prop = objectClass->getProperty(idx);
- value = properties[prop->getName()];
- if (!prop->isOptional() || !value->isNull()) {
- value->impl->encode(buffer);
- }
- }
-}
-
-void ObjectImpl::encodeStatistics(qpid::framing::Buffer& buffer) const
-{
- int statCount = objectClass->getStatisticCount();
- for (int idx = 0; idx < statCount; idx++) {
- const SchemaStatistic* stat = objectClass->getStatistic(idx);
- ValuePtr value = statistics[stat->getName()];
- value->impl->encode(buffer);
- }
-}
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-Object::Object(const SchemaObjectClass* type) : impl(new ObjectImpl(type)) {}
-Object::Object(ObjectImpl* i) : impl(i) {}
-Object::Object(const Object& from) : impl(new ObjectImpl(*(from.impl))) {}
-Object::~Object() { delete impl; }
-void Object::destroy() { impl->destroy(); }
-const ObjectId* Object::getObjectId() const { return impl->getObjectId(); }
-void Object::setObjectId(ObjectId* oid) { impl->setObjectId(oid); }
-const SchemaObjectClass* Object::getClass() const { return impl->getClass(); }
-Value* Object::getValue(const char* key) const { return impl->getValue(key); }
-void Object::invokeMethod(const char* m, const Value* a, void* c) const { impl->invokeMethod(m, a, c); }
-bool Object::isDeleted() const { return impl->isDeleted(); }
-void Object::merge(const Object& from) { impl->merge(from); }
-
diff --git a/qpid/cpp/src/qmf/engine/ObjectImpl.h b/qpid/cpp/src/qmf/engine/ObjectImpl.h
deleted file mode 100644
index 6f25867004..0000000000
--- a/qpid/cpp/src/qmf/engine/ObjectImpl.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef _QmfEngineObjectImpl_
-#define _QmfEngineObjectImpl_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <qmf/engine/Object.h>
-#include <qmf/engine/ObjectIdImpl.h>
-#include <map>
-#include <set>
-#include <string>
-#include <qpid/framing/Buffer.h>
-#include <boost/shared_ptr.hpp>
-#include <qpid/sys/Mutex.h>
-
-namespace qmf {
-namespace engine {
-
- class BrokerProxyImpl;
-
- typedef boost::shared_ptr<Object> ObjectPtr;
-
- struct ObjectImpl {
- typedef boost::shared_ptr<Value> ValuePtr;
- const SchemaObjectClass* objectClass;
- BrokerProxyImpl* broker;
- boost::shared_ptr<ObjectId> objectId;
- uint64_t createTime;
- uint64_t destroyTime;
- uint64_t lastUpdatedTime;
- mutable std::map<std::string, ValuePtr> properties;
- mutable std::map<std::string, ValuePtr> statistics;
-
- ObjectImpl(const SchemaObjectClass* type);
- ObjectImpl(const SchemaObjectClass* type, BrokerProxyImpl* b, qpid::framing::Buffer& buffer,
- bool prop, bool stat, bool managed);
- static Object* factory(const SchemaObjectClass* type, BrokerProxyImpl* b, qpid::framing::Buffer& buffer,
- bool prop, bool stat, bool managed);
- ~ObjectImpl();
-
- void destroy();
- const ObjectId* getObjectId() const { return objectId.get(); }
- void setObjectId(ObjectId* oid) { objectId.reset(new ObjectId(*oid)); }
- const SchemaObjectClass* getClass() const { return objectClass; }
- Value* getValue(const std::string& key) const;
- void invokeMethod(const std::string& methodName, const Value* inArgs, void* context) const;
- bool isDeleted() const { return destroyTime != 0; }
- void merge(const Object& from);
-
- void parsePresenceMasks(qpid::framing::Buffer& buffer, std::set<std::string>& excludeList);
- void encodeSchemaKey(qpid::framing::Buffer& buffer) const;
- void encodeManagedObjectData(qpid::framing::Buffer& buffer) const;
- void encodeProperties(qpid::framing::Buffer& buffer) const;
- void encodeStatistics(qpid::framing::Buffer& buffer) const;
- };
-}
-}
-
-#endif
-
diff --git a/qpid/cpp/src/qmf/engine/Protocol.cpp b/qpid/cpp/src/qmf/engine/Protocol.cpp
deleted file mode 100644
index 9e5f490604..0000000000
--- a/qpid/cpp/src/qmf/engine/Protocol.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/Protocol.h"
-#include "qpid/framing/Buffer.h"
-
-using namespace std;
-using namespace qmf::engine;
-using namespace qpid::framing;
-
-
-bool Protocol::checkHeader(Buffer& buf, uint8_t *opcode, uint32_t *seq)
-{
- if (buf.available() < 8)
- return false;
-
- uint8_t h1 = buf.getOctet();
- uint8_t h2 = buf.getOctet();
- uint8_t h3 = buf.getOctet();
-
- *opcode = buf.getOctet();
- *seq = buf.getLong();
-
- return h1 == 'A' && h2 == 'M' && h3 == '2';
-}
-
-void Protocol::encodeHeader(qpid::framing::Buffer& buf, uint8_t opcode, uint32_t seq)
-{
- buf.putOctet('A');
- buf.putOctet('M');
- buf.putOctet('2');
- buf.putOctet(opcode);
- buf.putLong (seq);
-}
-
-
diff --git a/qpid/cpp/src/qmf/engine/Protocol.h b/qpid/cpp/src/qmf/engine/Protocol.h
deleted file mode 100644
index 1cdfa60c84..0000000000
--- a/qpid/cpp/src/qmf/engine/Protocol.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef _QmfEngineProtocol_
-#define _QmfEngineProtocol_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <qpid/sys/IntegerTypes.h>
-
-namespace qpid {
- namespace framing {
- class Buffer;
- }
-}
-
-namespace qmf {
-namespace engine {
-
- class Protocol {
- public:
- static bool checkHeader(qpid::framing::Buffer& buf, uint8_t *opcode, uint32_t *seq);
- static void encodeHeader(qpid::framing::Buffer& buf, uint8_t opcode, uint32_t seq = 0);
-
- const static uint8_t OP_ATTACH_REQUEST = 'A';
- const static uint8_t OP_ATTACH_RESPONSE = 'a';
-
- const static uint8_t OP_BROKER_REQUEST = 'B';
- const static uint8_t OP_BROKER_RESPONSE = 'b';
-
- const static uint8_t OP_CONSOLE_ADDED_INDICATION = 'x';
- const static uint8_t OP_COMMAND_COMPLETE = 'z';
- const static uint8_t OP_HEARTBEAT_INDICATION = 'h';
-
- const static uint8_t OP_PACKAGE_REQUEST = 'P';
- const static uint8_t OP_PACKAGE_INDICATION = 'p';
- const static uint8_t OP_CLASS_QUERY = 'Q';
- const static uint8_t OP_CLASS_INDICATION = 'q';
- const static uint8_t OP_SCHEMA_REQUEST = 'S';
- const static uint8_t OP_SCHEMA_RESPONSE = 's';
-
- const static uint8_t OP_METHOD_REQUEST = 'M';
- const static uint8_t OP_METHOD_RESPONSE = 'm';
- const static uint8_t OP_GET_QUERY = 'G';
- const static uint8_t OP_OBJECT_INDICATION = 'g';
- const static uint8_t OP_PROPERTY_INDICATION = 'c';
- const static uint8_t OP_STATISTIC_INDICATION = 'i';
- const static uint8_t OP_EVENT_INDICATION = 'e';
- };
-
-}
-}
-
-#endif
-
diff --git a/qpid/cpp/src/qmf/engine/QueryImpl.cpp b/qpid/cpp/src/qmf/engine/QueryImpl.cpp
deleted file mode 100644
index 6f2beeee87..0000000000
--- a/qpid/cpp/src/qmf/engine/QueryImpl.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/QueryImpl.h"
-#include "qmf/engine/ObjectIdImpl.h"
-#include "qpid/framing/Buffer.h"
-#include "qpid/framing/FieldTable.h"
-
-using namespace std;
-using namespace qmf::engine;
-using namespace qpid::framing;
-
-bool QueryElementImpl::evaluate(const Object* /*object*/) const
-{
- // TODO: Implement this
- return false;
-}
-
-bool QueryExpressionImpl::evaluate(const Object* /*object*/) const
-{
- // TODO: Implement this
- return false;
-}
-
-QueryImpl::QueryImpl(Buffer& buffer)
-{
- FieldTable ft;
- ft.decode(buffer);
- // TODO
-}
-
-Query* QueryImpl::factory(Buffer& buffer)
-{
- QueryImpl* impl(new QueryImpl(buffer));
- return new Query(impl);
-}
-
-void QueryImpl::encode(Buffer& buffer) const
-{
- FieldTable ft;
-
- if (oid.get() != 0) {
- ft.setString("_objectid", oid->impl->asString());
- } else {
- if (!packageName.empty())
- ft.setString("_package", packageName);
- ft.setString("_class", className);
- }
-
- ft.encode(buffer);
-}
-
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-QueryElement::QueryElement(const char* attrName, const Value* value, ValueOper oper) : impl(new QueryElementImpl(attrName, value, oper)) {}
-QueryElement::QueryElement(QueryElementImpl* i) : impl(i) {}
-QueryElement::~QueryElement() { delete impl; }
-bool QueryElement::evaluate(const Object* object) const { return impl->evaluate(object); }
-
-QueryExpression::QueryExpression(ExprOper oper, const QueryOperand* operand1, const QueryOperand* operand2) : impl(new QueryExpressionImpl(oper, operand1, operand2)) {}
-QueryExpression::QueryExpression(QueryExpressionImpl* i) : impl(i) {}
-QueryExpression::~QueryExpression() { delete impl; }
-bool QueryExpression::evaluate(const Object* object) const { return impl->evaluate(object); }
-
-Query::Query(const char* className, const char* packageName) : impl(new QueryImpl(className, packageName)) {}
-Query::Query(const SchemaClassKey* key) : impl(new QueryImpl(key)) {}
-Query::Query(const ObjectId* oid) : impl(new QueryImpl(oid)) {}
-Query::Query(QueryImpl* i) : impl(i) {}
-Query::Query(const Query& from) : impl(new QueryImpl(*(from.impl))) {}
-Query::~Query() { delete impl; }
-void Query::setSelect(const QueryOperand* criterion) { impl->setSelect(criterion); }
-void Query::setLimit(uint32_t maxResults) { impl->setLimit(maxResults); }
-void Query::setOrderBy(const char* attrName, bool decreasing) { impl->setOrderBy(attrName, decreasing); }
-const char* Query::getPackage() const { return impl->getPackage().c_str(); }
-const char* Query::getClass() const { return impl->getClass().c_str(); }
-const ObjectId* Query::getObjectId() const { return impl->getObjectId(); }
-bool Query::haveSelect() const { return impl->haveSelect(); }
-bool Query::haveLimit() const { return impl->haveLimit(); }
-bool Query::haveOrderBy() const { return impl->haveOrderBy(); }
-const QueryOperand* Query::getSelect() const { return impl->getSelect(); }
-uint32_t Query::getLimit() const { return impl->getLimit(); }
-const char* Query::getOrderBy() const { return impl->getOrderBy().c_str(); }
-bool Query::getDecreasing() const { return impl->getDecreasing(); }
-
diff --git a/qpid/cpp/src/qmf/engine/QueryImpl.h b/qpid/cpp/src/qmf/engine/QueryImpl.h
deleted file mode 100644
index 8ebe0d932f..0000000000
--- a/qpid/cpp/src/qmf/engine/QueryImpl.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef _QmfEngineQueryImpl_
-#define _QmfEngineQueryImpl_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/Query.h"
-#include "qmf/engine/Schema.h"
-#include <string>
-#include <boost/shared_ptr.hpp>
-
-namespace qpid {
- namespace framing {
- class Buffer;
- }
-}
-
-namespace qmf {
-namespace engine {
-
- struct QueryElementImpl {
- QueryElementImpl(const std::string& a, const Value* v, ValueOper o) : attrName(a), value(v), oper(o) {}
- ~QueryElementImpl() {}
- bool evaluate(const Object* object) const;
-
- std::string attrName;
- const Value* value;
- ValueOper oper;
- };
-
- struct QueryExpressionImpl {
- QueryExpressionImpl(ExprOper o, const QueryOperand* operand1, const QueryOperand* operand2) : oper(o), left(operand1), right(operand2) {}
- ~QueryExpressionImpl() {}
- bool evaluate(const Object* object) const;
-
- ExprOper oper;
- const QueryOperand* left;
- const QueryOperand* right;
- };
-
- struct QueryImpl {
- // Constructors mapped to public
- QueryImpl(const std::string& c, const std::string& p) : packageName(p), className(c), select(0), resultLimit(0) {}
- QueryImpl(const SchemaClassKey* key) : packageName(key->getPackageName()), className(key->getClassName()), select(0), resultLimit(0) {}
- QueryImpl(const ObjectId* oid) : oid(new ObjectId(*oid)), select(0), resultLimit(0) {}
-
- // Factory constructors
- QueryImpl(qpid::framing::Buffer& buffer);
-
- ~QueryImpl() {};
- static Query* factory(qpid::framing::Buffer& buffer);
-
- void setSelect(const QueryOperand* criterion) { select = criterion; }
- void setLimit(uint32_t maxResults) { resultLimit = maxResults; }
- void setOrderBy(const std::string& attrName, bool decreasing) {
- orderBy = attrName; orderDecreasing = decreasing;
- }
-
- const std::string& getPackage() const { return packageName; }
- const std::string& getClass() const { return className; }
- const ObjectId* getObjectId() const { return oid.get(); }
-
- bool haveSelect() const { return select != 0; }
- bool haveLimit() const { return resultLimit > 0; }
- bool haveOrderBy() const { return !orderBy.empty(); }
- const QueryOperand* getSelect() const { return select; }
- uint32_t getLimit() const { return resultLimit; }
- const std::string& getOrderBy() const { return orderBy; }
- bool getDecreasing() const { return orderDecreasing; }
-
- void encode(qpid::framing::Buffer& buffer) const;
- bool singleAgent() const { return oid.get() != 0; }
- uint32_t agentBank() const { return singleAgent() ? oid->getAgentBank() : 0; }
-
- std::string packageName;
- std::string className;
- boost::shared_ptr<ObjectId> oid;
- const QueryOperand* select;
- uint32_t resultLimit;
- std::string orderBy;
- bool orderDecreasing;
- };
-}
-}
-
-#endif
diff --git a/qpid/cpp/src/qmf/engine/ResilientConnection.cpp b/qpid/cpp/src/qmf/engine/ResilientConnection.cpp
deleted file mode 100644
index 851193ccc1..0000000000
--- a/qpid/cpp/src/qmf/engine/ResilientConnection.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/ResilientConnection.h"
-#include "qmf/engine/MessageImpl.h"
-#include "qmf/engine/ConnectionSettingsImpl.h"
-#include <qpid/client/Connection.h>
-#include <qpid/client/Session.h>
-#include <qpid/client/MessageListener.h>
-#include <qpid/client/SubscriptionManager.h>
-#include <qpid/client/Message.h>
-#include <qpid/sys/Thread.h>
-#include <qpid/sys/Runnable.h>
-#include <qpid/sys/Mutex.h>
-#include <qpid/sys/Condition.h>
-#include <qpid/sys/Time.h>
-#include <qpid/log/Statement.h>
-#include <qpid/RefCounted.h>
-#include <boost/bind.hpp>
-#include <string>
-#include <deque>
-#include <vector>
-#include <set>
-#include <boost/intrusive_ptr.hpp>
-#include <boost/noncopyable.hpp>
-#include <unistd.h>
-#include <fcntl.h>
-
-using namespace std;
-using namespace qmf::engine;
-using namespace qpid;
-using qpid::sys::Mutex;
-
-namespace qmf {
-namespace engine {
- struct ResilientConnectionEventImpl {
- ResilientConnectionEvent::EventKind kind;
- void* sessionContext;
- string errorText;
- MessageImpl message;
-
- ResilientConnectionEventImpl(ResilientConnectionEvent::EventKind k,
- const MessageImpl& m = MessageImpl()) :
- kind(k), sessionContext(0), message(m) {}
- ResilientConnectionEvent copy();
- };
-
- struct RCSession : public client::MessageListener, public qpid::sys::Runnable, public qpid::RefCounted {
- typedef boost::intrusive_ptr<RCSession> Ptr;
- ResilientConnectionImpl& connImpl;
- string name;
- client::Connection& connection;
- client::Session session;
- client::SubscriptionManager* subscriptions;
- string userId;
- void* userContext;
- vector<string> dests;
- qpid::sys::Thread thread;
-
- RCSession(ResilientConnectionImpl& ci, const string& n, client::Connection& c, void* uc);
- ~RCSession();
- void received(client::Message& msg);
- void run();
- void stop();
- };
-
- class ResilientConnectionImpl : public qpid::sys::Runnable, public boost::noncopyable {
- public:
- ResilientConnectionImpl(const ConnectionSettings& settings);
- ~ResilientConnectionImpl();
-
- bool isConnected() const;
- bool getEvent(ResilientConnectionEvent& event);
- void popEvent();
- bool createSession(const char* name, void* sessionContext, SessionHandle& handle);
- void destroySession(SessionHandle handle);
- void sendMessage(SessionHandle handle, qmf::engine::Message& message);
- void declareQueue(SessionHandle handle, char* queue);
- void deleteQueue(SessionHandle handle, char* queue);
- void bind(SessionHandle handle, char* exchange, char* queue, char* key);
- void unbind(SessionHandle handle, char* exchange, char* queue, char* key);
- void setNotifyFd(int fd);
- void notify();
-
- void run();
- void failure();
- void sessionClosed(RCSession* sess);
-
- void EnqueueEvent(ResilientConnectionEvent::EventKind kind,
- void* sessionContext = 0,
- const MessageImpl& message = MessageImpl(),
- const string& errorText = "");
-
- private:
- int notifyFd;
- bool connected;
- bool shutdown;
- string lastError;
- const ConnectionSettings settings;
- client::Connection connection;
- mutable qpid::sys::Mutex lock;
- int delayMin;
- int delayMax;
- int delayFactor;
- qpid::sys::Condition cond;
- deque<ResilientConnectionEventImpl> eventQueue;
- set<RCSession::Ptr> sessions;
- qpid::sys::Thread connThread;
- };
-}
-}
-
-ResilientConnectionEvent ResilientConnectionEventImpl::copy()
-{
- ResilientConnectionEvent item;
-
- ::memset(&item, 0, sizeof(ResilientConnectionEvent));
- item.kind = kind;
- item.sessionContext = sessionContext;
- item.message = message.copy();
- item.errorText = const_cast<char*>(errorText.c_str());
-
- return item;
-}
-
-RCSession::RCSession(ResilientConnectionImpl& ci, const string& n, client::Connection& c, void* uc) :
- connImpl(ci), name(n), connection(c), session(connection.newSession(name)),
- subscriptions(new client::SubscriptionManager(session)), userContext(uc), thread(*this)
-{
- const qpid::client::ConnectionSettings& operSettings = connection.getNegotiatedSettings();
- userId = operSettings.username;
-}
-
-RCSession::~RCSession()
-{
- subscriptions->stop();
- thread.join();
- session.close();
- delete subscriptions;
-}
-
-void RCSession::run()
-{
- try {
- subscriptions->run();
- } catch (exception& /*e*/) {
- connImpl.sessionClosed(this);
- }
-}
-
-void RCSession::stop()
-{
- subscriptions->stop();
-}
-
-void RCSession::received(client::Message& msg)
-{
- MessageImpl qmsg;
- qmsg.body = msg.getData();
-
- qpid::framing::DeliveryProperties dp = msg.getDeliveryProperties();
- if (dp.hasRoutingKey()) {
- qmsg.routingKey = dp.getRoutingKey();
- }
-
- qpid::framing::MessageProperties mp = msg.getMessageProperties();
- if (mp.hasReplyTo()) {
- const qpid::framing::ReplyTo& rt = mp.getReplyTo();
- qmsg.replyExchange = rt.getExchange();
- qmsg.replyKey = rt.getRoutingKey();
- }
-
- if (mp.hasUserId()) {
- qmsg.userId = mp.getUserId();
- }
-
- connImpl.EnqueueEvent(ResilientConnectionEvent::RECV, userContext, qmsg);
-}
-
-ResilientConnectionImpl::ResilientConnectionImpl(const ConnectionSettings& _settings) :
- notifyFd(-1), connected(false), shutdown(false), settings(_settings), delayMin(1), connThread(*this)
-{
- connection.registerFailureCallback(boost::bind(&ResilientConnectionImpl::failure, this));
- settings.impl->getRetrySettings(&delayMin, &delayMax, &delayFactor);
-}
-
-ResilientConnectionImpl::~ResilientConnectionImpl()
-{
- shutdown = true;
- connected = false;
- cond.notify();
- connThread.join();
- connection.close();
-}
-
-bool ResilientConnectionImpl::isConnected() const
-{
- Mutex::ScopedLock _lock(lock);
- return connected;
-}
-
-bool ResilientConnectionImpl::getEvent(ResilientConnectionEvent& event)
-{
- Mutex::ScopedLock _lock(lock);
- if (eventQueue.empty())
- return false;
- event = eventQueue.front().copy();
- return true;
-}
-
-void ResilientConnectionImpl::popEvent()
-{
- Mutex::ScopedLock _lock(lock);
- if (!eventQueue.empty())
- eventQueue.pop_front();
-}
-
-bool ResilientConnectionImpl::createSession(const char* name, void* sessionContext,
- SessionHandle& handle)
-{
- Mutex::ScopedLock _lock(lock);
- if (!connected)
- return false;
-
- RCSession::Ptr sess = RCSession::Ptr(new RCSession(*this, name, connection, sessionContext));
-
- handle.impl = (void*) sess.get();
- sessions.insert(sess);
-
- return true;
-}
-
-void ResilientConnectionImpl::destroySession(SessionHandle handle)
-{
- Mutex::ScopedLock _lock(lock);
- RCSession::Ptr sess = RCSession::Ptr((RCSession*) handle.impl);
- set<RCSession::Ptr>::iterator iter = sessions.find(sess);
- if (iter != sessions.end()) {
- for (vector<string>::iterator dIter = sess->dests.begin(); dIter != sess->dests.end(); dIter++)
- sess->subscriptions->cancel(dIter->c_str());
- sess->subscriptions->stop();
- sess->subscriptions->wait();
-
- sessions.erase(iter);
- return;
- }
-}
-
-void ResilientConnectionImpl::sendMessage(SessionHandle handle, qmf::engine::Message& message)
-{
- Mutex::ScopedLock _lock(lock);
- RCSession::Ptr sess = RCSession::Ptr((RCSession*) handle.impl);
- set<RCSession::Ptr>::iterator iter = sessions.find(sess);
- qpid::client::Message msg;
- string data(message.body, message.length);
- msg.getDeliveryProperties().setRoutingKey(message.routingKey);
- msg.getMessageProperties().setReplyTo(qpid::framing::ReplyTo(message.replyExchange, message.replyKey));
- if (settings.impl->getSendUserId())
- msg.getMessageProperties().setUserId(sess->userId);
- msg.setData(data);
-
- try {
- sess->session.messageTransfer(client::arg::content=msg, client::arg::destination=message.destination);
- } catch(exception& e) {
- QPID_LOG(error, "Session Exception during message-transfer: " << e.what());
- sessions.erase(iter);
- EnqueueEvent(ResilientConnectionEvent::SESSION_CLOSED, (*iter)->userContext);
- }
-}
-
-void ResilientConnectionImpl::declareQueue(SessionHandle handle, char* queue)
-{
- Mutex::ScopedLock _lock(lock);
- RCSession* sess = (RCSession*) handle.impl;
-
- sess->session.queueDeclare(client::arg::queue=queue, client::arg::autoDelete=true, client::arg::exclusive=true);
- sess->subscriptions->setAcceptMode(client::ACCEPT_MODE_NONE);
- sess->subscriptions->setAcquireMode(client::ACQUIRE_MODE_PRE_ACQUIRED);
- sess->subscriptions->subscribe(*sess, queue, queue);
- sess->subscriptions->setFlowControl(queue, client::FlowControl::unlimited());
- sess->dests.push_back(string(queue));
-}
-
-void ResilientConnectionImpl::deleteQueue(SessionHandle handle, char* queue)
-{
- Mutex::ScopedLock _lock(lock);
- RCSession* sess = (RCSession*) handle.impl;
-
- sess->session.queueDelete(client::arg::queue=queue);
- for (vector<string>::iterator iter = sess->dests.begin();
- iter != sess->dests.end(); iter++)
- if (*iter == queue) {
- sess->subscriptions->cancel(queue);
- sess->dests.erase(iter);
- break;
- }
-}
-
-void ResilientConnectionImpl::bind(SessionHandle handle,
- char* exchange, char* queue, char* key)
-{
- Mutex::ScopedLock _lock(lock);
- RCSession* sess = (RCSession*) handle.impl;
-
- sess->session.exchangeBind(client::arg::exchange=exchange, client::arg::queue=queue, client::arg::bindingKey=key);
-}
-
-void ResilientConnectionImpl::unbind(SessionHandle handle,
- char* exchange, char* queue, char* key)
-{
- Mutex::ScopedLock _lock(lock);
- RCSession* sess = (RCSession*) handle.impl;
-
- sess->session.exchangeUnbind(client::arg::exchange=exchange, client::arg::queue=queue, client::arg::bindingKey=key);
-}
-
-void ResilientConnectionImpl::notify()
-{
- if (notifyFd != -1)
- {
- if (::write(notifyFd, ".", 1)) {}
- }
-}
-
-
-void ResilientConnectionImpl::setNotifyFd(int fd)
-{
- notifyFd = fd;
- if (notifyFd > 0) {
- int original = fcntl(notifyFd, F_GETFL);
- fcntl(notifyFd, F_SETFL, O_NONBLOCK | original);
- }
-}
-
-void ResilientConnectionImpl::run()
-{
- int delay(delayMin);
-
- while (true) {
- try {
- QPID_LOG(trace, "Trying to open connection...");
- connection.open(settings.impl->getClientSettings());
- {
- Mutex::ScopedLock _lock(lock);
- connected = true;
- EnqueueEvent(ResilientConnectionEvent::CONNECTED);
-
- while (connected)
- cond.wait(lock);
- delay = delayMin;
-
- while (!sessions.empty()) {
- set<RCSession::Ptr>::iterator iter = sessions.begin();
- RCSession::Ptr sess = *iter;
- sessions.erase(iter);
- EnqueueEvent(ResilientConnectionEvent::SESSION_CLOSED, sess->userContext);
- Mutex::ScopedUnlock _u(lock);
- sess->stop();
-
- // Nullify the intrusive pointer within the scoped unlock, otherwise,
- // the reference is held until overwritted above (under lock) which causes
- // the session destructor to be called with the lock held.
- sess = 0;
- }
-
- EnqueueEvent(ResilientConnectionEvent::DISCONNECTED);
-
- if (shutdown)
- return;
- }
- connection.close();
- } catch (exception &e) {
- QPID_LOG(debug, "connection.open exception: " << e.what());
- Mutex::ScopedLock _lock(lock);
- lastError = e.what();
- if (delay < delayMax)
- delay *= delayFactor;
- }
-
- ::qpid::sys::sleep(delay);
- }
-}
-
-void ResilientConnectionImpl::failure()
-{
- Mutex::ScopedLock _lock(lock);
-
- connected = false;
- lastError = "Closed by Peer";
- cond.notify();
-}
-
-void ResilientConnectionImpl::sessionClosed(RCSession*)
-{
- Mutex::ScopedLock _lock(lock);
- connected = false;
- lastError = "Closed due to Session failure";
- cond.notify();
-}
-
-void ResilientConnectionImpl::EnqueueEvent(ResilientConnectionEvent::EventKind kind,
- void* sessionContext,
- const MessageImpl& message,
- const string& errorText)
-{
- {
- Mutex::ScopedLock _lock(lock);
- ResilientConnectionEventImpl event(kind, message);
-
- event.sessionContext = sessionContext;
- event.errorText = errorText;
-
- eventQueue.push_back(event);
- }
-
- if (notifyFd != -1)
- {
- if (::write(notifyFd, ".", 1)) {}
- }
-}
-
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-ResilientConnection::ResilientConnection(const ConnectionSettings& settings)
-{
- impl = new ResilientConnectionImpl(settings);
-}
-
-ResilientConnection::~ResilientConnection()
-{
- delete impl;
-}
-
-bool ResilientConnection::isConnected() const
-{
- return impl->isConnected();
-}
-
-bool ResilientConnection::getEvent(ResilientConnectionEvent& event)
-{
- return impl->getEvent(event);
-}
-
-void ResilientConnection::popEvent()
-{
- impl->popEvent();
-}
-
-bool ResilientConnection::createSession(const char* name, void* sessionContext, SessionHandle& handle)
-{
- return impl->createSession(name, sessionContext, handle);
-}
-
-void ResilientConnection::destroySession(SessionHandle handle)
-{
- impl->destroySession(handle);
-}
-
-void ResilientConnection::sendMessage(SessionHandle handle, qmf::engine::Message& message)
-{
- impl->sendMessage(handle, message);
-}
-
-void ResilientConnection::declareQueue(SessionHandle handle, char* queue)
-{
- impl->declareQueue(handle, queue);
-}
-
-void ResilientConnection::deleteQueue(SessionHandle handle, char* queue)
-{
- impl->deleteQueue(handle, queue);
-}
-
-void ResilientConnection::bind(SessionHandle handle, char* exchange, char* queue, char* key)
-{
- impl->bind(handle, exchange, queue, key);
-}
-
-void ResilientConnection::unbind(SessionHandle handle, char* exchange, char* queue, char* key)
-{
- impl->unbind(handle, exchange, queue, key);
-}
-
-void ResilientConnection::setNotifyFd(int fd)
-{
- impl->setNotifyFd(fd);
-}
-
-void ResilientConnection::notify()
-{
- impl->notify();
-}
-
diff --git a/qpid/cpp/src/qmf/engine/SchemaImpl.cpp b/qpid/cpp/src/qmf/engine/SchemaImpl.cpp
deleted file mode 100644
index 9d363d3012..0000000000
--- a/qpid/cpp/src/qmf/engine/SchemaImpl.cpp
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/SchemaImpl.h"
-#include <qpid/framing/Buffer.h>
-#include <qpid/framing/FieldTable.h>
-#include <qpid/framing/Uuid.h>
-#include <string.h>
-#include <string>
-#include <vector>
-#include <sstream>
-
-using namespace std;
-using namespace qmf::engine;
-using qpid::framing::Buffer;
-using qpid::framing::FieldTable;
-using qpid::framing::Uuid;
-
-SchemaHash::SchemaHash()
-{
- for (int idx = 0; idx < 16; idx++)
- hash.b[idx] = 0x5A;
-}
-
-void SchemaHash::encode(Buffer& buffer) const
-{
- buffer.putBin128(hash.b);
-}
-
-void SchemaHash::decode(Buffer& buffer)
-{
- buffer.getBin128(hash.b);
-}
-
-void SchemaHash::update(uint8_t data)
-{
- update((char*) &data, 1);
-}
-
-void SchemaHash::update(const char* data, uint32_t len)
-{
- uint64_t* first = &hash.q[0];
- uint64_t* second = &hash.q[1];
- for (uint32_t idx = 0; idx < len; idx++) {
- *first = *first ^ (uint64_t) data[idx];
- *second = *second << 1;
- *second |= ((*first & 0x8000000000000000LL) >> 63);
- *first = *first << 1;
- *first = *first ^ *second;
- }
-}
-
-bool SchemaHash::operator==(const SchemaHash& other) const
-{
- return ::memcmp(&hash, &other.hash, 16) == 0;
-}
-
-bool SchemaHash::operator<(const SchemaHash& other) const
-{
- return ::memcmp(&hash, &other.hash, 16) < 0;
-}
-
-bool SchemaHash::operator>(const SchemaHash& other) const
-{
- return ::memcmp(&hash, &other.hash, 16) > 0;
-}
-
-SchemaArgumentImpl::SchemaArgumentImpl(Buffer& buffer)
-{
- FieldTable map;
- map.decode(buffer);
-
- name = map.getAsString("name");
- typecode = (Typecode) map.getAsInt("type");
- unit = map.getAsString("unit");
- description = map.getAsString("desc");
-
- dir = DIR_IN;
- string dstr(map.getAsString("dir"));
- if (dstr == "O")
- dir = DIR_OUT;
- else if (dstr == "IO")
- dir = DIR_IN_OUT;
-}
-
-SchemaArgument* SchemaArgumentImpl::factory(Buffer& buffer)
-{
- SchemaArgumentImpl* impl(new SchemaArgumentImpl(buffer));
- return new SchemaArgument(impl);
-}
-
-void SchemaArgumentImpl::encode(Buffer& buffer) const
-{
- FieldTable map;
-
- map.setString("name", name);
- map.setInt("type", (int) typecode);
- if (dir == DIR_IN)
- map.setString("dir", "I");
- else if (dir == DIR_OUT)
- map.setString("dir", "O");
- else
- map.setString("dir", "IO");
- if (!unit.empty())
- map.setString("unit", unit);
- if (!description.empty())
- map.setString("desc", description);
-
- map.encode(buffer);
-}
-
-void SchemaArgumentImpl::updateHash(SchemaHash& hash) const
-{
- hash.update(name);
- hash.update(typecode);
- hash.update(dir);
- hash.update(unit);
- hash.update(description);
-}
-
-SchemaMethodImpl::SchemaMethodImpl(Buffer& buffer)
-{
- FieldTable map;
- int argCount;
-
- map.decode(buffer);
- name = map.getAsString("name");
- argCount = map.getAsInt("argCount");
- description = map.getAsString("desc");
-
- for (int idx = 0; idx < argCount; idx++) {
- SchemaArgument* arg = SchemaArgumentImpl::factory(buffer);
- addArgument(arg);
- }
-}
-
-SchemaMethod* SchemaMethodImpl::factory(Buffer& buffer)
-{
- SchemaMethodImpl* impl(new SchemaMethodImpl(buffer));
- return new SchemaMethod(impl);
-}
-
-void SchemaMethodImpl::encode(Buffer& buffer) const
-{
- FieldTable map;
-
- map.setString("name", name);
- map.setInt("argCount", arguments.size());
- if (!description.empty())
- map.setString("desc", description);
- map.encode(buffer);
-
- for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
- iter != arguments.end(); iter++)
- (*iter)->impl->encode(buffer);
-}
-
-void SchemaMethodImpl::addArgument(const SchemaArgument* argument)
-{
- arguments.push_back(argument);
-}
-
-const SchemaArgument* SchemaMethodImpl::getArgument(int idx) const
-{
- int count = 0;
- for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
- iter != arguments.end(); iter++, count++)
- if (idx == count)
- return (*iter);
- return 0;
-}
-
-void SchemaMethodImpl::updateHash(SchemaHash& hash) const
-{
- hash.update(name);
- hash.update(description);
- for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
- iter != arguments.end(); iter++)
- (*iter)->impl->updateHash(hash);
-}
-
-SchemaPropertyImpl::SchemaPropertyImpl(Buffer& buffer)
-{
- FieldTable map;
- map.decode(buffer);
-
- name = map.getAsString("name");
- typecode = (Typecode) map.getAsInt("type");
- access = (Access) map.getAsInt("access");
- index = map.getAsInt("index") != 0;
- optional = map.getAsInt("optional") != 0;
- unit = map.getAsString("unit");
- description = map.getAsString("desc");
-}
-
-SchemaProperty* SchemaPropertyImpl::factory(Buffer& buffer)
-{
- SchemaPropertyImpl* impl(new SchemaPropertyImpl(buffer));
- return new SchemaProperty(impl);
-}
-
-void SchemaPropertyImpl::encode(Buffer& buffer) const
-{
- FieldTable map;
-
- map.setString("name", name);
- map.setInt("type", (int) typecode);
- map.setInt("access", (int) access);
- map.setInt("index", index ? 1 : 0);
- map.setInt("optional", optional ? 1 : 0);
- if (!unit.empty())
- map.setString("unit", unit);
- if (!description.empty())
- map.setString("desc", description);
-
- map.encode(buffer);
-}
-
-void SchemaPropertyImpl::updateHash(SchemaHash& hash) const
-{
- hash.update(name);
- hash.update(typecode);
- hash.update(access);
- hash.update(index);
- hash.update(optional);
- hash.update(unit);
- hash.update(description);
-}
-
-SchemaStatisticImpl::SchemaStatisticImpl(Buffer& buffer)
-{
- FieldTable map;
- map.decode(buffer);
-
- name = map.getAsString("name");
- typecode = (Typecode) map.getAsInt("type");
- unit = map.getAsString("unit");
- description = map.getAsString("desc");
-}
-
-SchemaStatistic* SchemaStatisticImpl::factory(Buffer& buffer)
-{
- SchemaStatisticImpl* impl(new SchemaStatisticImpl(buffer));
- return new SchemaStatistic(impl);
-}
-
-void SchemaStatisticImpl::encode(Buffer& buffer) const
-{
- FieldTable map;
-
- map.setString("name", name);
- map.setInt("type", (int) typecode);
- if (!unit.empty())
- map.setString("unit", unit);
- if (!description.empty())
- map.setString("desc", description);
-
- map.encode(buffer);
-}
-
-void SchemaStatisticImpl::updateHash(SchemaHash& hash) const
-{
- hash.update(name);
- hash.update(typecode);
- hash.update(unit);
- hash.update(description);
-}
-
-SchemaClassKeyImpl::SchemaClassKeyImpl(const string& p, const string& n, const SchemaHash& h) : package(p), name(n), hash(h) {}
-
-SchemaClassKeyImpl::SchemaClassKeyImpl(Buffer& buffer) : package(packageContainer), name(nameContainer), hash(hashContainer)
-{
- buffer.getShortString(packageContainer);
- buffer.getShortString(nameContainer);
- hashContainer.decode(buffer);
-}
-
-SchemaClassKey* SchemaClassKeyImpl::factory(const string& package, const string& name, const SchemaHash& hash)
-{
- SchemaClassKeyImpl* impl(new SchemaClassKeyImpl(package, name, hash));
- return new SchemaClassKey(impl);
-}
-
-SchemaClassKey* SchemaClassKeyImpl::factory(Buffer& buffer)
-{
- SchemaClassKeyImpl* impl(new SchemaClassKeyImpl(buffer));
- return new SchemaClassKey(impl);
-}
-
-void SchemaClassKeyImpl::encode(Buffer& buffer) const
-{
- buffer.putShortString(package);
- buffer.putShortString(name);
- hash.encode(buffer);
-}
-
-bool SchemaClassKeyImpl::operator==(const SchemaClassKeyImpl& other) const
-{
- return package == other.package &&
- name == other.name &&
- hash == other.hash;
-}
-
-bool SchemaClassKeyImpl::operator<(const SchemaClassKeyImpl& other) const
-{
- if (package < other.package) return true;
- if (package > other.package) return false;
- if (name < other.name) return true;
- if (name > other.name) return false;
- return hash < other.hash;
-}
-
-const string& SchemaClassKeyImpl::str() const
-{
- Uuid printableHash(hash.get());
- stringstream str;
- str << package << ":" << name << "(" << printableHash << ")";
- repr = str.str();
- return repr;
-}
-
-SchemaObjectClassImpl::SchemaObjectClassImpl(Buffer& buffer) : hasHash(true), classKey(SchemaClassKeyImpl::factory(package, name, hash))
-{
- buffer.getShortString(package);
- buffer.getShortString(name);
- hash.decode(buffer);
-
- uint16_t propCount = buffer.getShort();
- uint16_t statCount = buffer.getShort();
- uint16_t methodCount = buffer.getShort();
-
- for (uint16_t idx = 0; idx < propCount; idx++) {
- const SchemaProperty* property = SchemaPropertyImpl::factory(buffer);
- addProperty(property);
- }
-
- for (uint16_t idx = 0; idx < statCount; idx++) {
- const SchemaStatistic* statistic = SchemaStatisticImpl::factory(buffer);
- addStatistic(statistic);
- }
-
- for (uint16_t idx = 0; idx < methodCount; idx++) {
- SchemaMethod* method = SchemaMethodImpl::factory(buffer);
- addMethod(method);
- }
-}
-
-SchemaObjectClass* SchemaObjectClassImpl::factory(Buffer& buffer)
-{
- SchemaObjectClassImpl* impl(new SchemaObjectClassImpl(buffer));
- return new SchemaObjectClass(impl);
-}
-
-void SchemaObjectClassImpl::encode(Buffer& buffer) const
-{
- buffer.putOctet((uint8_t) CLASS_OBJECT);
- buffer.putShortString(package);
- buffer.putShortString(name);
- hash.encode(buffer);
- //buffer.putOctet(0); // No parent class
- buffer.putShort((uint16_t) properties.size());
- buffer.putShort((uint16_t) statistics.size());
- buffer.putShort((uint16_t) methods.size());
-
- for (vector<const SchemaProperty*>::const_iterator iter = properties.begin();
- iter != properties.end(); iter++)
- (*iter)->impl->encode(buffer);
- for (vector<const SchemaStatistic*>::const_iterator iter = statistics.begin();
- iter != statistics.end(); iter++)
- (*iter)->impl->encode(buffer);
- for (vector<const SchemaMethod*>::const_iterator iter = methods.begin();
- iter != methods.end(); iter++)
- (*iter)->impl->encode(buffer);
-}
-
-const SchemaClassKey* SchemaObjectClassImpl::getClassKey() const
-{
- if (!hasHash) {
- hasHash = true;
- hash.update(package);
- hash.update(name);
- for (vector<const SchemaProperty*>::const_iterator iter = properties.begin();
- iter != properties.end(); iter++)
- (*iter)->impl->updateHash(hash);
- for (vector<const SchemaStatistic*>::const_iterator iter = statistics.begin();
- iter != statistics.end(); iter++)
- (*iter)->impl->updateHash(hash);
- for (vector<const SchemaMethod*>::const_iterator iter = methods.begin();
- iter != methods.end(); iter++)
- (*iter)->impl->updateHash(hash);
- }
-
- return classKey.get();
-}
-
-void SchemaObjectClassImpl::addProperty(const SchemaProperty* property)
-{
- properties.push_back(property);
-}
-
-void SchemaObjectClassImpl::addStatistic(const SchemaStatistic* statistic)
-{
- statistics.push_back(statistic);
-}
-
-void SchemaObjectClassImpl::addMethod(const SchemaMethod* method)
-{
- methods.push_back(method);
-}
-
-const SchemaProperty* SchemaObjectClassImpl::getProperty(int idx) const
-{
- int count = 0;
- for (vector<const SchemaProperty*>::const_iterator iter = properties.begin();
- iter != properties.end(); iter++, count++)
- if (idx == count)
- return *iter;
- return 0;
-}
-
-const SchemaStatistic* SchemaObjectClassImpl::getStatistic(int idx) const
-{
- int count = 0;
- for (vector<const SchemaStatistic*>::const_iterator iter = statistics.begin();
- iter != statistics.end(); iter++, count++)
- if (idx == count)
- return *iter;
- return 0;
-}
-
-const SchemaMethod* SchemaObjectClassImpl::getMethod(int idx) const
-{
- int count = 0;
- for (vector<const SchemaMethod*>::const_iterator iter = methods.begin();
- iter != methods.end(); iter++, count++)
- if (idx == count)
- return *iter;
- return 0;
-}
-
-SchemaEventClassImpl::SchemaEventClassImpl(Buffer& buffer) : hasHash(true), classKey(SchemaClassKeyImpl::factory(package, name, hash))
-{
- buffer.getShortString(package);
- buffer.getShortString(name);
- hash.decode(buffer);
-
- uint16_t argCount = buffer.getShort();
-
- for (uint16_t idx = 0; idx < argCount; idx++) {
- SchemaArgument* argument = SchemaArgumentImpl::factory(buffer);
- addArgument(argument);
- }
-}
-
-SchemaEventClass* SchemaEventClassImpl::factory(Buffer& buffer)
-{
- SchemaEventClassImpl* impl(new SchemaEventClassImpl(buffer));
- return new SchemaEventClass(impl);
-}
-
-void SchemaEventClassImpl::encode(Buffer& buffer) const
-{
- buffer.putOctet((uint8_t) CLASS_EVENT);
- buffer.putShortString(package);
- buffer.putShortString(name);
- hash.encode(buffer);
- buffer.putShort((uint16_t) arguments.size());
-
- for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
- iter != arguments.end(); iter++)
- (*iter)->impl->encode(buffer);
-}
-
-const SchemaClassKey* SchemaEventClassImpl::getClassKey() const
-{
- if (!hasHash) {
- hasHash = true;
- hash.update(package);
- hash.update(name);
- for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
- iter != arguments.end(); iter++)
- (*iter)->impl->updateHash(hash);
- }
- return classKey.get();
-}
-
-void SchemaEventClassImpl::addArgument(const SchemaArgument* argument)
-{
- arguments.push_back(argument);
-}
-
-const SchemaArgument* SchemaEventClassImpl::getArgument(int idx) const
-{
- int count = 0;
- for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
- iter != arguments.end(); iter++, count++)
- if (idx == count)
- return (*iter);
- return 0;
-}
-
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-SchemaArgument::SchemaArgument(const char* name, Typecode typecode) { impl = new SchemaArgumentImpl(name, typecode); }
-SchemaArgument::SchemaArgument(SchemaArgumentImpl* i) : impl(i) {}
-SchemaArgument::SchemaArgument(const SchemaArgument& from) : impl(new SchemaArgumentImpl(*(from.impl))) {}
-SchemaArgument::~SchemaArgument() { delete impl; }
-void SchemaArgument::setDirection(Direction dir) { impl->setDirection(dir); }
-void SchemaArgument::setUnit(const char* val) { impl->setUnit(val); }
-void SchemaArgument::setDesc(const char* desc) { impl->setDesc(desc); }
-const char* SchemaArgument::getName() const { return impl->getName().c_str(); }
-Typecode SchemaArgument::getType() const { return impl->getType(); }
-Direction SchemaArgument::getDirection() const { return impl->getDirection(); }
-const char* SchemaArgument::getUnit() const { return impl->getUnit().c_str(); }
-const char* SchemaArgument::getDesc() const { return impl->getDesc().c_str(); }
-
-SchemaMethod::SchemaMethod(const char* name) : impl(new SchemaMethodImpl(name)) {}
-SchemaMethod::SchemaMethod(SchemaMethodImpl* i) : impl(i) {}
-SchemaMethod::SchemaMethod(const SchemaMethod& from) : impl(new SchemaMethodImpl(*(from.impl))) {}
-SchemaMethod::~SchemaMethod() { delete impl; }
-void SchemaMethod::addArgument(const SchemaArgument* argument) { impl->addArgument(argument); }
-void SchemaMethod::setDesc(const char* desc) { impl->setDesc(desc); }
-const char* SchemaMethod::getName() const { return impl->getName().c_str(); }
-const char* SchemaMethod::getDesc() const { return impl->getDesc().c_str(); }
-int SchemaMethod::getArgumentCount() const { return impl->getArgumentCount(); }
-const SchemaArgument* SchemaMethod::getArgument(int idx) const { return impl->getArgument(idx); }
-
-SchemaProperty::SchemaProperty(const char* name, Typecode typecode) : impl(new SchemaPropertyImpl(name, typecode)) {}
-SchemaProperty::SchemaProperty(SchemaPropertyImpl* i) : impl(i) {}
-SchemaProperty::SchemaProperty(const SchemaProperty& from) : impl(new SchemaPropertyImpl(*(from.impl))) {}
-SchemaProperty::~SchemaProperty() { delete impl; }
-void SchemaProperty::setAccess(Access access) { impl->setAccess(access); }
-void SchemaProperty::setIndex(bool val) { impl->setIndex(val); }
-void SchemaProperty::setOptional(bool val) { impl->setOptional(val); }
-void SchemaProperty::setUnit(const char* val) { impl->setUnit(val); }
-void SchemaProperty::setDesc(const char* desc) { impl->setDesc(desc); }
-const char* SchemaProperty::getName() const { return impl->getName().c_str(); }
-Typecode SchemaProperty::getType() const { return impl->getType(); }
-Access SchemaProperty::getAccess() const { return impl->getAccess(); }
-bool SchemaProperty::isIndex() const { return impl->isIndex(); }
-bool SchemaProperty::isOptional() const { return impl->isOptional(); }
-const char* SchemaProperty::getUnit() const { return impl->getUnit().c_str(); }
-const char* SchemaProperty::getDesc() const { return impl->getDesc().c_str(); }
-
-SchemaStatistic::SchemaStatistic(const char* name, Typecode typecode) : impl(new SchemaStatisticImpl(name, typecode)) {}
-SchemaStatistic::SchemaStatistic(SchemaStatisticImpl* i) : impl(i) {}
-SchemaStatistic::SchemaStatistic(const SchemaStatistic& from) : impl(new SchemaStatisticImpl(*(from.impl))) {}
-SchemaStatistic::~SchemaStatistic() { delete impl; }
-void SchemaStatistic::setUnit(const char* val) { impl->setUnit(val); }
-void SchemaStatistic::setDesc(const char* desc) { impl->setDesc(desc); }
-const char* SchemaStatistic::getName() const { return impl->getName().c_str(); }
-Typecode SchemaStatistic::getType() const { return impl->getType(); }
-const char* SchemaStatistic::getUnit() const { return impl->getUnit().c_str(); }
-const char* SchemaStatistic::getDesc() const { return impl->getDesc().c_str(); }
-
-SchemaClassKey::SchemaClassKey(SchemaClassKeyImpl* i) : impl(i) {}
-SchemaClassKey::SchemaClassKey(const SchemaClassKey& from) : impl(new SchemaClassKeyImpl(*(from.impl))) {}
-SchemaClassKey::~SchemaClassKey() { delete impl; }
-const char* SchemaClassKey::getPackageName() const { return impl->getPackageName().c_str(); }
-const char* SchemaClassKey::getClassName() const { return impl->getClassName().c_str(); }
-const uint8_t* SchemaClassKey::getHash() const { return impl->getHash(); }
-const char* SchemaClassKey::asString() const { return impl->str().c_str(); }
-bool SchemaClassKey::operator==(const SchemaClassKey& other) const { return *impl == *(other.impl); }
-bool SchemaClassKey::operator<(const SchemaClassKey& other) const { return *impl < *(other.impl); }
-
-SchemaObjectClass::SchemaObjectClass(const char* package, const char* name) : impl(new SchemaObjectClassImpl(package, name)) {}
-SchemaObjectClass::SchemaObjectClass(SchemaObjectClassImpl* i) : impl(i) {}
-SchemaObjectClass::SchemaObjectClass(const SchemaObjectClass& from) : impl(new SchemaObjectClassImpl(*(from.impl))) {}
-SchemaObjectClass::~SchemaObjectClass() { delete impl; }
-void SchemaObjectClass::addProperty(const SchemaProperty* property) { impl->addProperty(property); }
-void SchemaObjectClass::addStatistic(const SchemaStatistic* statistic) { impl->addStatistic(statistic); }
-void SchemaObjectClass::addMethod(const SchemaMethod* method) { impl->addMethod(method); }
-const SchemaClassKey* SchemaObjectClass::getClassKey() const { return impl->getClassKey(); }
-int SchemaObjectClass::getPropertyCount() const { return impl->getPropertyCount(); }
-int SchemaObjectClass::getStatisticCount() const { return impl->getStatisticCount(); }
-int SchemaObjectClass::getMethodCount() const { return impl->getMethodCount(); }
-const SchemaProperty* SchemaObjectClass::getProperty(int idx) const { return impl->getProperty(idx); }
-const SchemaStatistic* SchemaObjectClass::getStatistic(int idx) const { return impl->getStatistic(idx); }
-const SchemaMethod* SchemaObjectClass::getMethod(int idx) const { return impl->getMethod(idx); }
-
-SchemaEventClass::SchemaEventClass(const char* package, const char* name, Severity s) : impl(new SchemaEventClassImpl(package, name, s)) {}
-SchemaEventClass::SchemaEventClass(SchemaEventClassImpl* i) : impl(i) {}
-SchemaEventClass::SchemaEventClass(const SchemaEventClass& from) : impl(new SchemaEventClassImpl(*(from.impl))) {}
-SchemaEventClass::~SchemaEventClass() { delete impl; }
-void SchemaEventClass::addArgument(const SchemaArgument* argument) { impl->addArgument(argument); }
-void SchemaEventClass::setDesc(const char* desc) { impl->setDesc(desc); }
-const SchemaClassKey* SchemaEventClass::getClassKey() const { return impl->getClassKey(); }
-Severity SchemaEventClass::getSeverity() const { return impl->getSeverity(); }
-int SchemaEventClass::getArgumentCount() const { return impl->getArgumentCount(); }
-const SchemaArgument* SchemaEventClass::getArgument(int idx) const { return impl->getArgument(idx); }
-
diff --git a/qpid/cpp/src/qmf/engine/SchemaImpl.h b/qpid/cpp/src/qmf/engine/SchemaImpl.h
deleted file mode 100644
index 683fb6f8f0..0000000000
--- a/qpid/cpp/src/qmf/engine/SchemaImpl.h
+++ /dev/null
@@ -1,230 +0,0 @@
-#ifndef _QmfEngineSchemaImpl_
-#define _QmfEngineSchemaImpl_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/Schema.h"
-#include "qpid/framing/Buffer.h"
-
-#include <string>
-#include <vector>
-#include <memory>
-
-namespace qmf {
-namespace engine {
-
- // TODO: Destructors for schema classes
- // TODO: Add "frozen" attribute for schema classes so they can't be modified after
- // they've been registered.
-
- class SchemaHash {
- union h {
- uint8_t b[16];
- uint64_t q[2];
- } hash;
- public:
- SchemaHash();
- void encode(qpid::framing::Buffer& buffer) const;
- void decode(qpid::framing::Buffer& buffer);
- void update(const char* data, uint32_t len);
- void update(uint8_t data);
- void update(const std::string& data) { update(data.c_str(), data.size()); }
- void update(Typecode t) { update((uint8_t) t); }
- void update(Direction d) { update((uint8_t) d); }
- void update(Access a) { update((uint8_t) a); }
- void update(bool b) { update((uint8_t) (b ? 1 : 0)); }
- const uint8_t* get() const { return hash.b; }
- bool operator==(const SchemaHash& other) const;
- bool operator<(const SchemaHash& other) const;
- bool operator>(const SchemaHash& other) const;
- };
-
- struct SchemaArgumentImpl {
- std::string name;
- Typecode typecode;
- Direction dir;
- std::string unit;
- std::string description;
-
- SchemaArgumentImpl(const char* n, Typecode t) : name(n), typecode(t), dir(DIR_IN) {}
- SchemaArgumentImpl(qpid::framing::Buffer& buffer);
- static SchemaArgument* factory(qpid::framing::Buffer& buffer);
- void encode(qpid::framing::Buffer& buffer) const;
- void setDirection(Direction d) { dir = d; }
- void setUnit(const char* val) { unit = val; }
- void setDesc(const char* desc) { description = desc; }
- const std::string& getName() const { return name; }
- Typecode getType() const { return typecode; }
- Direction getDirection() const { return dir; }
- const std::string& getUnit() const { return unit; }
- const std::string& getDesc() const { return description; }
- void updateHash(SchemaHash& hash) const;
- };
-
- struct SchemaMethodImpl {
- std::string name;
- std::string description;
- std::vector<const SchemaArgument*> arguments;
-
- SchemaMethodImpl(const char* n) : name(n) {}
- SchemaMethodImpl(qpid::framing::Buffer& buffer);
- static SchemaMethod* factory(qpid::framing::Buffer& buffer);
- void encode(qpid::framing::Buffer& buffer) const;
- void addArgument(const SchemaArgument* argument);
- void setDesc(const char* desc) { description = desc; }
- const std::string& getName() const { return name; }
- const std::string& getDesc() const { return description; }
- int getArgumentCount() const { return arguments.size(); }
- const SchemaArgument* getArgument(int idx) const;
- void updateHash(SchemaHash& hash) const;
- };
-
- struct SchemaPropertyImpl {
- std::string name;
- Typecode typecode;
- Access access;
- bool index;
- bool optional;
- std::string unit;
- std::string description;
-
- SchemaPropertyImpl(const char* n, Typecode t) : name(n), typecode(t), access(ACCESS_READ_ONLY), index(false), optional(false) {}
- SchemaPropertyImpl(qpid::framing::Buffer& buffer);
- static SchemaProperty* factory(qpid::framing::Buffer& buffer);
- void encode(qpid::framing::Buffer& buffer) const;
- void setAccess(Access a) { access = a; }
- void setIndex(bool val) { index = val; }
- void setOptional(bool val) { optional = val; }
- void setUnit(const char* val) { unit = val; }
- void setDesc(const char* desc) { description = desc; }
- const std::string& getName() const { return name; }
- Typecode getType() const { return typecode; }
- Access getAccess() const { return access; }
- bool isIndex() const { return index; }
- bool isOptional() const { return optional; }
- const std::string& getUnit() const { return unit; }
- const std::string& getDesc() const { return description; }
- void updateHash(SchemaHash& hash) const;
- };
-
- struct SchemaStatisticImpl {
- std::string name;
- Typecode typecode;
- std::string unit;
- std::string description;
-
- SchemaStatisticImpl(const char* n, Typecode t) : name(n), typecode(t) {}
- SchemaStatisticImpl(qpid::framing::Buffer& buffer);
- static SchemaStatistic* factory(qpid::framing::Buffer& buffer);
- void encode(qpid::framing::Buffer& buffer) const;
- void setUnit(const char* val) { unit = val; }
- void setDesc(const char* desc) { description = desc; }
- const std::string& getName() const { return name; }
- Typecode getType() const { return typecode; }
- const std::string& getUnit() const { return unit; }
- const std::string& getDesc() const { return description; }
- void updateHash(SchemaHash& hash) const;
- };
-
- struct SchemaClassKeyImpl {
- const std::string& package;
- const std::string& name;
- const SchemaHash& hash;
- mutable std::string repr;
-
- // The *Container elements are only used if there isn't an external place to
- // store these values.
- std::string packageContainer;
- std::string nameContainer;
- SchemaHash hashContainer;
-
- SchemaClassKeyImpl(const std::string& package, const std::string& name, const SchemaHash& hash);
- SchemaClassKeyImpl(qpid::framing::Buffer& buffer);
- static SchemaClassKey* factory(const std::string& package, const std::string& name, const SchemaHash& hash);
- static SchemaClassKey* factory(qpid::framing::Buffer& buffer);
-
- const std::string& getPackageName() const { return package; }
- const std::string& getClassName() const { return name; }
- const uint8_t* getHash() const { return hash.get(); }
-
- void encode(qpid::framing::Buffer& buffer) const;
- bool operator==(const SchemaClassKeyImpl& other) const;
- bool operator<(const SchemaClassKeyImpl& other) const;
- const std::string& str() const;
- };
-
- struct SchemaObjectClassImpl {
- std::string package;
- std::string name;
- mutable SchemaHash hash;
- mutable bool hasHash;
- std::auto_ptr<SchemaClassKey> classKey;
- std::vector<const SchemaProperty*> properties;
- std::vector<const SchemaStatistic*> statistics;
- std::vector<const SchemaMethod*> methods;
-
- SchemaObjectClassImpl(const char* p, const char* n) :
- package(p), name(n), hasHash(false), classKey(SchemaClassKeyImpl::factory(package, name, hash)) {}
- SchemaObjectClassImpl(qpid::framing::Buffer& buffer);
- static SchemaObjectClass* factory(qpid::framing::Buffer& buffer);
-
- void encode(qpid::framing::Buffer& buffer) const;
- void addProperty(const SchemaProperty* property);
- void addStatistic(const SchemaStatistic* statistic);
- void addMethod(const SchemaMethod* method);
-
- const SchemaClassKey* getClassKey() const;
- int getPropertyCount() const { return properties.size(); }
- int getStatisticCount() const { return statistics.size(); }
- int getMethodCount() const { return methods.size(); }
- const SchemaProperty* getProperty(int idx) const;
- const SchemaStatistic* getStatistic(int idx) const;
- const SchemaMethod* getMethod(int idx) const;
- };
-
- struct SchemaEventClassImpl {
- std::string package;
- std::string name;
- mutable SchemaHash hash;
- mutable bool hasHash;
- std::auto_ptr<SchemaClassKey> classKey;
- std::string description;
- Severity severity;
- std::vector<const SchemaArgument*> arguments;
-
- SchemaEventClassImpl(const char* p, const char* n, Severity sev) :
- package(p), name(n), hasHash(false), classKey(SchemaClassKeyImpl::factory(package, name, hash)), severity(sev) {}
- SchemaEventClassImpl(qpid::framing::Buffer& buffer);
- static SchemaEventClass* factory(qpid::framing::Buffer& buffer);
-
- void encode(qpid::framing::Buffer& buffer) const;
- void addArgument(const SchemaArgument* argument);
- void setDesc(const char* desc) { description = desc; }
-
- const SchemaClassKey* getClassKey() const;
- Severity getSeverity() const { return severity; }
- int getArgumentCount() const { return arguments.size(); }
- const SchemaArgument* getArgument(int idx) const;
- };
-}
-}
-
-#endif
-
diff --git a/qpid/cpp/src/qmf/engine/SequenceManager.cpp b/qpid/cpp/src/qmf/engine/SequenceManager.cpp
deleted file mode 100644
index 4a4644a8b9..0000000000
--- a/qpid/cpp/src/qmf/engine/SequenceManager.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/SequenceManager.h"
-
-using namespace std;
-using namespace qmf::engine;
-using namespace qpid::sys;
-
-SequenceManager::SequenceManager() : nextSequence(1) {}
-
-void SequenceManager::setUnsolicitedContext(SequenceContext::Ptr ctx)
-{
- unsolicitedContext = ctx;
-}
-
-uint32_t SequenceManager::reserve(SequenceContext::Ptr ctx)
-{
- Mutex::ScopedLock _lock(lock);
- if (ctx.get() == 0)
- ctx = unsolicitedContext;
- uint32_t seq = nextSequence;
- while (contextMap.find(seq) != contextMap.end())
- seq = seq < 0xFFFFFFFF ? seq + 1 : 1;
- nextSequence = seq < 0xFFFFFFFF ? seq + 1 : 1;
- contextMap[seq] = ctx;
- ctx->reserve();
- return seq;
-}
-
-void SequenceManager::release(uint32_t sequence)
-{
- Mutex::ScopedLock _lock(lock);
-
- if (sequence == 0) {
- if (unsolicitedContext.get() != 0)
- unsolicitedContext->release();
- return;
- }
-
- map<uint32_t, SequenceContext::Ptr>::iterator iter = contextMap.find(sequence);
- if (iter != contextMap.end()) {
- if (iter->second != 0)
- iter->second->release();
- contextMap.erase(iter);
- }
-}
-
-void SequenceManager::releaseAll()
-{
- Mutex::ScopedLock _lock(lock);
- contextMap.clear();
-}
-
-void SequenceManager::dispatch(uint8_t opcode, uint32_t sequence, const string& routingKey, qpid::framing::Buffer& buffer)
-{
- Mutex::ScopedLock _lock(lock);
- bool done;
-
- if (sequence == 0) {
- if (unsolicitedContext.get() != 0) {
- done = unsolicitedContext->handleMessage(opcode, sequence, routingKey, buffer);
- if (done)
- unsolicitedContext->release();
- }
- return;
- }
-
- map<uint32_t, SequenceContext::Ptr>::iterator iter = contextMap.find(sequence);
- if (iter != contextMap.end()) {
- if (iter->second != 0) {
- done = iter->second->handleMessage(opcode, sequence, routingKey, buffer);
- if (done) {
- iter->second->release();
- contextMap.erase(iter);
- }
- }
- }
-}
-
diff --git a/qpid/cpp/src/qmf/engine/SequenceManager.h b/qpid/cpp/src/qmf/engine/SequenceManager.h
deleted file mode 100644
index 9e47e38610..0000000000
--- a/qpid/cpp/src/qmf/engine/SequenceManager.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef _QmfEngineSequenceManager_
-#define _QmfEngineSequenceManager_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qpid/sys/Mutex.h"
-#include <boost/shared_ptr.hpp>
-#include <map>
-
-namespace qpid {
- namespace framing {
- class Buffer;
- }
-}
-
-namespace qmf {
-namespace engine {
-
- class SequenceContext {
- public:
- typedef boost::shared_ptr<SequenceContext> Ptr;
- SequenceContext() {}
- virtual ~SequenceContext() {}
-
- virtual void reserve() = 0;
- virtual bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer) = 0;
- virtual void release() = 0;
- };
-
- class SequenceManager {
- public:
- SequenceManager();
-
- void setUnsolicitedContext(SequenceContext::Ptr ctx);
- uint32_t reserve(SequenceContext::Ptr ctx = SequenceContext::Ptr());
- void release(uint32_t sequence);
- void releaseAll();
- void dispatch(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer);
-
- private:
- mutable qpid::sys::Mutex lock;
- uint32_t nextSequence;
- SequenceContext::Ptr unsolicitedContext;
- std::map<uint32_t, SequenceContext::Ptr> contextMap;
- };
-
-}
-}
-
-#endif
-
diff --git a/qpid/cpp/src/qmf/engine/ValueImpl.cpp b/qpid/cpp/src/qmf/engine/ValueImpl.cpp
deleted file mode 100644
index f9ebbf5028..0000000000
--- a/qpid/cpp/src/qmf/engine/ValueImpl.cpp
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/engine/ValueImpl.h"
-#include <qpid/framing/FieldValue.h>
-#include <qpid/framing/FieldTable.h>
-#include <qpid/framing/List.h>
-#include <qpid/log/Statement.h>
-
-using namespace std;
-using namespace qmf::engine;
-//using qpid::framing::Buffer;
-//using qpid::framing::FieldTable;
-//using qpid::framing::FieldValue;
-using namespace qpid::framing;
-
-ValueImpl::ValueImpl(Typecode t, Buffer& buf) : typecode(t)
-{
- uint64_t first;
- uint64_t second;
- FieldTable ft;
- List fl;
-
- switch (typecode) {
- case TYPE_UINT8 : value.u32 = (uint32_t) buf.getOctet(); break;
- case TYPE_UINT16 : value.u32 = (uint32_t) buf.getShort(); break;
- case TYPE_UINT32 : value.u32 = (uint32_t) buf.getLong(); break;
- case TYPE_UINT64 : value.u64 = buf.getLongLong(); break;
- case TYPE_SSTR : buf.getShortString(stringVal); break;
- case TYPE_LSTR : buf.getMediumString(stringVal); break;
- case TYPE_ABSTIME : value.s64 = buf.getLongLong(); break;
- case TYPE_DELTATIME : value.u64 = buf.getLongLong(); break;
- case TYPE_BOOL : value.boolVal = (buf.getOctet() != 0); break;
- case TYPE_FLOAT : value.floatVal = buf.getFloat(); break;
- case TYPE_DOUBLE : value.doubleVal = buf.getDouble(); break;
- case TYPE_INT8 : value.s32 = (int32_t) ((int8_t) buf.getOctet()); break;
- case TYPE_INT16 : value.s32 = (int32_t) ((int16_t) buf.getShort()); break;
- case TYPE_INT32 : value.s32 = (int32_t) buf.getLong(); break;
- case TYPE_INT64 : value.s64 = buf.getLongLong(); break;
- case TYPE_UUID : buf.getBin128(value.uuidVal); break;
- case TYPE_REF:
- first = buf.getLongLong();
- second = buf.getLongLong();
- refVal.impl->setValue(first, second);
- break;
-
- case TYPE_MAP:
- ft.decode(buf);
- initMap(ft);
- break;
-
- case TYPE_LIST:
- fl.decode(buf);
- initList(fl);
- break;
-
- case TYPE_ARRAY:
- case TYPE_OBJECT:
- default:
- break;
- }
-}
-
-ValueImpl::ValueImpl(Typecode t, Typecode at) : typecode(t), valid(false), arrayTypecode(at)
-{
-}
-
-ValueImpl::ValueImpl(Typecode t) : typecode(t)
-{
- ::memset(&value, 0, sizeof(value));
-}
-
-Value* ValueImpl::factory(Typecode t, Buffer& b)
-{
- ValueImpl* impl(new ValueImpl(t, b));
- return new Value(impl);
-}
-
-Value* ValueImpl::factory(Typecode t)
-{
- ValueImpl* impl(new ValueImpl(t));
- return new Value(impl);
-}
-
-ValueImpl::~ValueImpl()
-{
-}
-
-void ValueImpl::initMap(const FieldTable& ft)
-{
- for (FieldTable::ValueMap::const_iterator iter = ft.begin();
- iter != ft.end(); iter++) {
- const string& name(iter->first);
- const FieldValue& fvalue(*iter->second);
- uint8_t amqType = fvalue.getType();
-
- if (amqType == 0x32) {
- Value* subval(new Value(TYPE_UINT64));
- subval->setUint64(fvalue.get<int64_t>());
- insert(name.c_str(), subval);
- } else if ((amqType & 0xCF) == 0x02) {
- Value* subval(new Value(TYPE_UINT32));
- switch (amqType) {
- case 0x02 : subval->setUint(fvalue.get<int>()); break;
- case 0x12 : subval->setUint(fvalue.get<int>()); break;
- case 0x22 : subval->setUint(fvalue.get<int>()); break;
- }
- insert(name.c_str(), subval);
- } else if (amqType == 0x31) { // int64
- Value* subval(new Value(TYPE_INT64));
- subval->setInt64(fvalue.get<int64_t>());
- insert(name.c_str(), subval);
- } else if ((amqType & 0xCF) == 0x01) { // 0x01:int8, 0x11:int16, 0x21:int21
- Value* subval(new Value(TYPE_INT32));
- subval->setInt((int32_t)fvalue.get<int>());
- insert(name.c_str(), subval);
- } else if (amqType == 0x85 || amqType == 0x95) {
- Value* subval(new Value(TYPE_LSTR));
- subval->setString(fvalue.get<string>().c_str());
- insert(name.c_str(), subval);
- } else if (amqType == 0x23 || amqType == 0x33) {
- Value* subval(new Value(TYPE_DOUBLE));
- subval->setDouble(fvalue.get<double>());
- insert(name.c_str(), subval);
- } else if (amqType == 0xa8) {
- FieldTable subFt;
- bool valid = qpid::framing::getEncodedValue<FieldTable>(iter->second, subFt);
- if (valid) {
- Value* subval(new Value(TYPE_MAP));
- subval->impl->initMap(subFt);
- insert(name.c_str(), subval);
- }
- } else if (amqType == 0xa9) {
- List subList;
- bool valid = qpid::framing::getEncodedValue<List>(iter->second, subList);
- if (valid) {
- Value* subval(new Value(TYPE_LIST));
- subval->impl->initList(subList);
- insert(name.c_str(), subval);
- }
- } else if (amqType == 0x08) {
- Value* subval(new Value(TYPE_BOOL));
- subval->setBool(fvalue.get<int>() ? true : false);
- insert(name.c_str(), subval);
- } else {
- QPID_LOG(error, "Unable to decode unsupported AMQP typecode=" << amqType << " map index=" << name);
- }
- }
-}
-
-void ValueImpl::mapToFieldTable(FieldTable& ft) const
-{
- FieldTable subFt;
-
- for (map<string, Value>::const_iterator iter = mapVal.begin();
- iter != mapVal.end(); iter++) {
- const string& name(iter->first);
- const Value& subval(iter->second);
-
- switch (subval.getType()) {
- case TYPE_UINT8:
- case TYPE_UINT16:
- case TYPE_UINT32:
- ft.setUInt64(name, (uint64_t) subval.asUint());
- break;
- case TYPE_UINT64:
- case TYPE_DELTATIME:
- ft.setUInt64(name, subval.asUint64());
- break;
- case TYPE_SSTR:
- case TYPE_LSTR:
- ft.setString(name, subval.asString());
- break;
- case TYPE_INT64:
- case TYPE_ABSTIME:
- ft.setInt64(name, subval.asInt64());
- break;
- case TYPE_BOOL:
- ft.set(name, FieldTable::ValuePtr(new BoolValue(subval.asBool())));
- break;
- case TYPE_FLOAT:
- ft.setFloat(name, subval.asFloat());
- break;
- case TYPE_DOUBLE:
- ft.setDouble(name, subval.asDouble());
- break;
- case TYPE_INT8:
- case TYPE_INT16:
- case TYPE_INT32:
- ft.setInt(name, subval.asInt());
- break;
- case TYPE_MAP:
- subFt.clear();
- subval.impl->mapToFieldTable(subFt);
- ft.setTable(name, subFt);
- break;
- case TYPE_LIST:
- {
- List subList;
- subval.impl->listToFramingList(subList);
- ft.set(name,
- ::qpid::framing::FieldTable::ValuePtr(
- new ListValue(
- subList)));
- } break;
- case TYPE_ARRAY:
- case TYPE_OBJECT:
- case TYPE_UUID:
- case TYPE_REF:
- default:
- break;
- }
- }
- }
-
-
-void ValueImpl::initList(const List& fl)
-{
- for (List::const_iterator iter = fl.begin();
- iter != fl.end(); iter++) {
- const FieldValue& fvalue(*iter->get());
- uint8_t amqType = fvalue.getType();
-
- if (amqType == 0x32) {
- Value* subval(new Value(TYPE_UINT64));
- subval->setUint64(fvalue.get<int64_t>());
- appendToList(subval);
- } else if ((amqType & 0xCF) == 0x02) {
- Value* subval(new Value(TYPE_UINT32));
- switch (amqType) {
- case 0x02 : subval->setUint(fvalue.get<int>()); break; // uint8
- case 0x12 : subval->setUint(fvalue.get<int>()); break; // uint16
- case 0x22 : subval->setUint(fvalue.get<int>()); break; // uint32
- }
- appendToList(subval);
- } else if (amqType == 0x31) { // int64
- Value* subval(new Value(TYPE_INT64));
- subval->setInt64(fvalue.get<int64_t>());
- appendToList(subval);
- } else if ((amqType & 0xCF) == 0x01) { // 0x01:int8, 0x11:int16, 0x21:int32
- Value* subval(new Value(TYPE_INT32));
- subval->setInt((int32_t)fvalue.get<int>());
- appendToList(subval);
- } else if (amqType == 0x85 || amqType == 0x95) {
- Value* subval(new Value(TYPE_LSTR));
- subval->setString(fvalue.get<string>().c_str());
- appendToList(subval);
- } else if (amqType == 0x23 || amqType == 0x33) {
- Value* subval(new Value(TYPE_DOUBLE));
- subval->setDouble(fvalue.get<double>());
- appendToList(subval);
- } else if (amqType == 0xa8) {
- FieldTable subFt;
- bool valid = qpid::framing::getEncodedValue<FieldTable>(*iter, subFt);
- if (valid) {
- Value* subval(new Value(TYPE_MAP));
- subval->impl->initMap(subFt);
- appendToList(subval);
- }
- } else if (amqType == 0xa9) {
- List subList;
- bool valid = qpid::framing::getEncodedValue<List>(*iter, subList);
- if (valid) {
- Value *subVal(new Value(TYPE_LIST));
- subVal->impl->initList(subList);
- appendToList(subVal);
- }
- } else if (amqType == 0x08) {
- Value* subval(new Value(TYPE_BOOL));
- subval->setBool(fvalue.get<int>() ? true : false);
- appendToList(subval);
- } else {
- QPID_LOG(error, "Unable to decode unsupported AMQP typecode =" << amqType);
- }
- }
-}
-
-void ValueImpl::listToFramingList(List& fl) const
-{
- for (vector<Value>::const_iterator iter = vectorVal.begin();
- iter != vectorVal.end(); iter++) {
- const Value& subval(*iter);
-
- switch (subval.getType()) {
- case TYPE_UINT8:
- case TYPE_UINT16:
- case TYPE_UINT32:
- fl.push_back(List::ValuePtr(new Unsigned64Value((uint64_t) subval.asUint())));
- break;
- case TYPE_UINT64:
- case TYPE_DELTATIME:
- fl.push_back(List::ValuePtr(new Unsigned64Value(subval.asUint64())));
- break;
- case TYPE_SSTR:
- case TYPE_LSTR:
- fl.push_back(List::ValuePtr(new Str16Value(subval.asString())));
- break;
- case TYPE_INT64:
- case TYPE_ABSTIME:
- fl.push_back(List::ValuePtr(new Integer64Value(subval.asInt64())));
- break;
- case TYPE_BOOL:
- fl.push_back(List::ValuePtr(new BoolValue(subval.asBool() ? 1 : 0)));
- break;
- case TYPE_FLOAT:
- fl.push_back(List::ValuePtr(new FloatValue(subval.asFloat())));
- break;
- case TYPE_DOUBLE:
- fl.push_back(List::ValuePtr(new DoubleValue(subval.asDouble())));
- break;
- case TYPE_INT8:
- case TYPE_INT16:
- case TYPE_INT32:
- fl.push_back(List::ValuePtr(new IntegerValue(subval.asInt())));
- break;
- case TYPE_MAP:
- {
- FieldTable subFt;
- subval.impl->mapToFieldTable(subFt);
- fl.push_back(List::ValuePtr(new FieldTableValue(subFt)));
-
- } break;
- case TYPE_LIST:
- {
- List subList;
- subval.impl->listToFramingList(subList);
- fl.push_back(List::ValuePtr(new ListValue(subList)));
- } break;
-
- case TYPE_ARRAY:
- case TYPE_OBJECT:
- case TYPE_UUID:
- case TYPE_REF:
- default:
- break;
- }
- }
- }
-
-
-
-void ValueImpl::encode(Buffer& buf) const
-{
- FieldTable ft;
- List fl;
-
- switch (typecode) {
- case TYPE_UINT8 : buf.putOctet((uint8_t) value.u32); break;
- case TYPE_UINT16 : buf.putShort((uint16_t) value.u32); break;
- case TYPE_UINT32 : buf.putLong(value.u32); break;
- case TYPE_UINT64 : buf.putLongLong(value.u64); break;
- case TYPE_SSTR : buf.putShortString(stringVal); break;
- case TYPE_LSTR : buf.putMediumString(stringVal); break;
- case TYPE_ABSTIME : buf.putLongLong(value.s64); break;
- case TYPE_DELTATIME : buf.putLongLong(value.u64); break;
- case TYPE_BOOL : buf.putOctet(value.boolVal ? 1 : 0); break;
- case TYPE_FLOAT : buf.putFloat(value.floatVal); break;
- case TYPE_DOUBLE : buf.putDouble(value.doubleVal); break;
- case TYPE_INT8 : buf.putOctet((uint8_t) value.s32); break;
- case TYPE_INT16 : buf.putShort((uint16_t) value.s32); break;
- case TYPE_INT32 : buf.putLong(value.s32); break;
- case TYPE_INT64 : buf.putLongLong(value.s64); break;
- case TYPE_UUID : buf.putBin128(value.uuidVal); break;
- case TYPE_REF : refVal.impl->encode(buf); break;
- case TYPE_MAP:
- mapToFieldTable(ft);
- ft.encode(buf);
- break;
- case TYPE_LIST:
- listToFramingList(fl);
- fl.encode(buf);
- break;
-
- case TYPE_ARRAY:
- case TYPE_OBJECT:
- default:
- break;
- }
-}
-
-uint32_t ValueImpl::encodedSize() const
-{
- FieldTable ft;
- List fl;
-
- switch (typecode) {
- case TYPE_UINT8 :
- case TYPE_BOOL :
- case TYPE_INT8 : return 1;
-
- case TYPE_UINT16 :
- case TYPE_INT16 : return 2;
-
- case TYPE_UINT32 :
- case TYPE_INT32 :
- case TYPE_FLOAT : return 4;
-
- case TYPE_UINT64 :
- case TYPE_INT64 :
- case TYPE_DOUBLE :
- case TYPE_ABSTIME :
- case TYPE_DELTATIME : return 8;
-
- case TYPE_UUID :
- case TYPE_REF : return 16;
-
- case TYPE_SSTR : return 1 + stringVal.size();
- case TYPE_LSTR : return 2 + stringVal.size();
- case TYPE_MAP:
- mapToFieldTable(ft);
- return ft.encodedSize();
-
- case TYPE_LIST:
- listToFramingList(fl);
- return fl.encodedSize();
-
- case TYPE_ARRAY:
- case TYPE_OBJECT:
- default:
- break;
- }
-
- return 0;
-}
-
-bool ValueImpl::keyInMap(const char* key) const
-{
- return typecode == TYPE_MAP && mapVal.count(key) > 0;
-}
-
-Value* ValueImpl::byKey(const char* key)
-{
- if (keyInMap(key)) {
- map<string, Value>::iterator iter = mapVal.find(key);
- if (iter != mapVal.end())
- return &iter->second;
- }
- return 0;
-}
-
-const Value* ValueImpl::byKey(const char* key) const
-{
- if (keyInMap(key)) {
- map<string, Value>::const_iterator iter = mapVal.find(key);
- if (iter != mapVal.end())
- return &iter->second;
- }
- return 0;
-}
-
-void ValueImpl::deleteKey(const char* key)
-{
- mapVal.erase(key);
-}
-
-void ValueImpl::insert(const char* key, Value* val)
-{
- pair<string, Value> entry(key, *val);
- mapVal.insert(entry);
-}
-
-const char* ValueImpl::key(uint32_t idx) const
-{
- map<string, Value>::const_iterator iter = mapVal.begin();
- for (uint32_t i = 0; i < idx; i++) {
- if (iter == mapVal.end())
- break;
- iter++;
- }
-
- if (iter == mapVal.end())
- return 0;
- else
- return iter->first.c_str();
-}
-
-Value* ValueImpl::arrayItem(uint32_t)
-{
- return 0;
-}
-
-void ValueImpl::appendToArray(Value*)
-{
-}
-
-void ValueImpl::deleteArrayItem(uint32_t)
-{
-}
-
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-Value::Value(const Value& from) : impl(new ValueImpl(*(from.impl))) {}
-Value::Value(Typecode t, Typecode at) : impl(new ValueImpl(t, at)) {}
-Value::Value(ValueImpl* i) : impl(i) {}
-Value::~Value() { delete impl;}
-
-Typecode Value::getType() const { return impl->getType(); }
-bool Value::isNull() const { return impl->isNull(); }
-void Value::setNull() { impl->setNull(); }
-bool Value::isObjectId() const { return impl->isObjectId(); }
-const ObjectId& Value::asObjectId() const { return impl->asObjectId(); }
-void Value::setObjectId(const ObjectId& oid) { impl->setObjectId(oid); }
-bool Value::isUint() const { return impl->isUint(); }
-uint32_t Value::asUint() const { return impl->asUint(); }
-void Value::setUint(uint32_t val) { impl->setUint(val); }
-bool Value::isInt() const { return impl->isInt(); }
-int32_t Value::asInt() const { return impl->asInt(); }
-void Value::setInt(int32_t val) { impl->setInt(val); }
-bool Value::isUint64() const { return impl->isUint64(); }
-uint64_t Value::asUint64() const { return impl->asUint64(); }
-void Value::setUint64(uint64_t val) { impl->setUint64(val); }
-bool Value::isInt64() const { return impl->isInt64(); }
-int64_t Value::asInt64() const { return impl->asInt64(); }
-void Value::setInt64(int64_t val) { impl->setInt64(val); }
-bool Value::isString() const { return impl->isString(); }
-const char* Value::asString() const { return impl->asString(); }
-void Value::setString(const char* val) { impl->setString(val); }
-bool Value::isBool() const { return impl->isBool(); }
-bool Value::asBool() const { return impl->asBool(); }
-void Value::setBool(bool val) { impl->setBool(val); }
-bool Value::isFloat() const { return impl->isFloat(); }
-float Value::asFloat() const { return impl->asFloat(); }
-void Value::setFloat(float val) { impl->setFloat(val); }
-bool Value::isDouble() const { return impl->isDouble(); }
-double Value::asDouble() const { return impl->asDouble(); }
-void Value::setDouble(double val) { impl->setDouble(val); }
-bool Value::isUuid() const { return impl->isUuid(); }
-const uint8_t* Value::asUuid() const { return impl->asUuid(); }
-void Value::setUuid(const uint8_t* val) { impl->setUuid(val); }
-bool Value::isObject() const { return impl->isObject(); }
-const Object* Value::asObject() const { return impl->asObject(); }
-void Value::setObject(Object* val) { impl->setObject(val); }
-bool Value::isMap() const { return impl->isMap(); }
-bool Value::keyInMap(const char* key) const { return impl->keyInMap(key); }
-Value* Value::byKey(const char* key) { return impl->byKey(key); }
-const Value* Value::byKey(const char* key) const { return impl->byKey(key); }
-void Value::deleteKey(const char* key) { impl->deleteKey(key); }
-void Value::insert(const char* key, Value* val) { impl->insert(key, val); }
-uint32_t Value::keyCount() const { return impl->keyCount(); }
-const char* Value::key(uint32_t idx) const { return impl->key(idx); }
-bool Value::isList() const { return impl->isList(); }
-uint32_t Value::listItemCount() const { return impl->listItemCount(); }
-Value* Value::listItem(uint32_t idx) { return impl->listItem(idx); }
-void Value::appendToList(Value* val) { impl->appendToList(val); }
-void Value::deleteListItem(uint32_t idx) { impl->deleteListItem(idx); }
-bool Value::isArray() const { return impl->isArray(); }
-Typecode Value::arrayType() const { return impl->arrayType(); }
-uint32_t Value::arrayItemCount() const { return impl->arrayItemCount(); }
-Value* Value::arrayItem(uint32_t idx) { return impl->arrayItem(idx); }
-void Value::appendToArray(Value* val) { impl->appendToArray(val); }
-void Value::deleteArrayItem(uint32_t idx) { impl->deleteArrayItem(idx); }
-
diff --git a/qpid/cpp/src/qmf/engine/ValueImpl.h b/qpid/cpp/src/qmf/engine/ValueImpl.h
deleted file mode 100644
index 8de8c5329f..0000000000
--- a/qpid/cpp/src/qmf/engine/ValueImpl.h
+++ /dev/null
@@ -1,166 +0,0 @@
-#ifndef _QmfEngineValueImpl_
-#define _QmfEngineValueImpl_
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <qmf/engine/Value.h>
-#include <qmf/engine/ObjectIdImpl.h>
-#include <qmf/engine/Object.h>
-#include <qpid/framing/Buffer.h>
-#include <string>
-#include <string.h>
-#include <map>
-#include <vector>
-#include <boost/shared_ptr.hpp>
-
-namespace qpid {
-namespace framing {
- class FieldTable;
- class List;
-}
-}
-
-namespace qmf {
-namespace engine {
-
- // TODO: set valid flag on all value settors
- // TODO: add a modified flag and accessors
-
- struct ValueImpl {
- const Typecode typecode;
- bool valid;
-
- ObjectId refVal;
- std::string stringVal;
- std::auto_ptr<Object> objectVal;
- std::map<std::string, Value> mapVal;
- std::vector<Value> vectorVal;
- Typecode arrayTypecode;
-
- union {
- uint32_t u32;
- uint64_t u64;
- int32_t s32;
- int64_t s64;
- bool boolVal;
- float floatVal;
- double doubleVal;
- uint8_t uuidVal[16];
- } value;
-
- ValueImpl(const ValueImpl& from) :
- typecode(from.typecode), valid(from.valid), refVal(from.refVal), stringVal(from.stringVal),
- objectVal(from.objectVal.get() ? new Object(*(from.objectVal)) : 0),
- mapVal(from.mapVal), vectorVal(from.vectorVal), arrayTypecode(from.arrayTypecode),
- value(from.value) {}
-
- ValueImpl(Typecode t, Typecode at);
- ValueImpl(Typecode t, qpid::framing::Buffer& b);
- ValueImpl(Typecode t);
- static Value* factory(Typecode t, qpid::framing::Buffer& b);
- static Value* factory(Typecode t);
- ~ValueImpl();
-
- void encode(qpid::framing::Buffer& b) const;
- uint32_t encodedSize() const;
-
- Typecode getType() const { return typecode; }
- bool isNull() const { return !valid; }
- void setNull() { valid = false; }
-
- bool isObjectId() const { return typecode == TYPE_REF; }
- const ObjectId& asObjectId() const { return refVal; }
- void setObjectId(const ObjectId& o) { refVal = o; } // TODO
-
- bool isUint() const { return typecode >= TYPE_UINT8 && typecode <= TYPE_UINT32; }
- uint32_t asUint() const { return value.u32; }
- void setUint(uint32_t val) { value.u32 = val; }
-
- bool isInt() const { return typecode >= TYPE_INT8 && typecode <= TYPE_INT32; }
- int32_t asInt() const { return value.s32; }
- void setInt(int32_t val) { value.s32 = val; }
-
- bool isUint64() const { return typecode == TYPE_UINT64 || typecode == TYPE_DELTATIME; }
- uint64_t asUint64() const { return value.u64; }
- void setUint64(uint64_t val) { value.u64 = val; }
-
- bool isInt64() const { return typecode == TYPE_INT64 || typecode == TYPE_ABSTIME; }
- int64_t asInt64() const { return value.s64; }
- void setInt64(int64_t val) { value.s64 = val; }
-
- bool isString() const { return typecode == TYPE_SSTR || typecode == TYPE_LSTR; }
- const char* asString() const { return stringVal.c_str(); }
- void setString(const char* val) { stringVal = val; }
-
- bool isBool() const { return typecode == TYPE_BOOL; }
- bool asBool() const { return value.boolVal; }
- void setBool(bool val) { value.boolVal = val; }
-
- bool isFloat() const { return typecode == TYPE_FLOAT; }
- float asFloat() const { return value.floatVal; }
- void setFloat(float val) { value.floatVal = val; }
-
- bool isDouble() const { return typecode == TYPE_DOUBLE; }
- double asDouble() const { return value.doubleVal; }
- void setDouble(double val) { value.doubleVal = val; }
-
- bool isUuid() const { return typecode == TYPE_UUID; }
- const uint8_t* asUuid() const { return value.uuidVal; }
- void setUuid(const uint8_t* val) { ::memcpy(value.uuidVal, val, 16); }
-
- bool isObject() const { return typecode == TYPE_OBJECT; }
- Object* asObject() const { return objectVal.get(); }
- void setObject(Object* val) { objectVal.reset(val); }
-
- bool isMap() const { return typecode == TYPE_MAP; }
- bool keyInMap(const char* key) const;
- Value* byKey(const char* key);
- const Value* byKey(const char* key) const;
- void deleteKey(const char* key);
- void insert(const char* key, Value* val);
- uint32_t keyCount() const { return mapVal.size(); }
- const char* key(uint32_t idx) const;
-
- bool isList() const { return typecode == TYPE_LIST; }
- uint32_t listItemCount() const { return vectorVal.size(); }
- Value* listItem(uint32_t idx) { return idx < listItemCount() ? &vectorVal[idx] : 0; }
- const Value* listItem(uint32_t idx) const { return idx < listItemCount() ? &vectorVal[idx] : 0; }
- void appendToList(Value* val) { vectorVal.push_back(*val); }
- void deleteListItem(uint32_t idx) { if (idx < listItemCount()) vectorVal.erase(vectorVal.begin()+idx); }
-
- bool isArray() const { return typecode == TYPE_ARRAY; }
- Typecode arrayType() const { return arrayTypecode; }
- uint32_t arrayItemCount() const { return 0; }
- Value* arrayItem(uint32_t idx);
- void appendToArray(Value* val);
- void deleteArrayItem(uint32_t idx);
-
- private:
- void mapToFieldTable(qpid::framing::FieldTable& ft) const;
- void initMap(const qpid::framing::FieldTable& ft);
-
- void listToFramingList(qpid::framing::List& fl) const;
- void initList(const qpid::framing::List& fl);
- };
-}
-}
-
-#endif
-
diff --git a/qpid/cpp/src/qmfc.mk b/qpid/cpp/src/qmfc.mk
deleted file mode 100644
index e445a538a1..0000000000
--- a/qpid/cpp/src/qmfc.mk
+++ /dev/null
@@ -1,57 +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.
-#
-
-#
-# qmf console library makefile fragment, to be included in Makefile.am
-#
-lib_LTLIBRARIES += libqmfconsole.la
-
-# Public header files.
-nobase_include_HEADERS += \
- ../include/qpid/console/Agent.h \
- ../include/qpid/console/Broker.h \
- ../include/qpid/console/ClassKey.h \
- ../include/qpid/console/ConsoleImportExport.h \
- ../include/qpid/console/ConsoleListener.h \
- ../include/qpid/console/Event.h \
- ../include/qpid/console/Object.h \
- ../include/qpid/console/ObjectId.h \
- ../include/qpid/console/Package.h \
- ../include/qpid/console/Schema.h \
- ../include/qpid/console/SequenceManager.h \
- ../include/qpid/console/SessionManager.h \
- ../include/qpid/console/Value.h
-
-libqmfconsole_la_SOURCES = \
- qpid/console/Agent.cpp \
- qpid/console/Broker.cpp \
- qpid/console/ClassKey.cpp \
- qpid/console/Event.cpp \
- qpid/console/Object.cpp \
- qpid/console/ObjectId.cpp \
- qpid/console/Package.cpp \
- qpid/console/Schema.cpp \
- qpid/console/SequenceManager.cpp \
- qpid/console/SessionManager.cpp \
- qpid/console/Value.cpp
-
-libqmfconsole_la_LIBADD = libqpidclient.la
-
-QMFCONSOLE_VERSION_INFO = 2:0:0
-libqmfconsole_la_LDFLAGS = -version-info $(QMFCONSOLE_VERSION_INFO)
diff --git a/qpid/cpp/src/qpid.linkmap b/qpid/cpp/src/qpid.linkmap
new file mode 100644
index 0000000000..4556985b1b
--- /dev/null
+++ b/qpid/cpp/src/qpid.linkmap
@@ -0,0 +1,10 @@
+{
+ global:
+ extern "C++" {
+ typeinfo*qpid::*;
+ vtable*qpid::*;
+ qpid::*;
+ qpid::*operator*qpid::*;
+ };
+ local: *;
+};
diff --git a/qpid/cpp/src/qpid/Address.h b/qpid/cpp/src/qpid/Address.h
new file mode 100755
index 0000000000..fe43f3847d
--- /dev/null
+++ b/qpid/cpp/src/qpid/Address.h
@@ -0,0 +1,56 @@
+#ifndef QPID_ADDRESS_H
+#define QPID_ADDRESS_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/sys/IntegerTypes.h"
+#include "qpid/CommonImportExport.h"
+#include <iosfwd>
+#include <string>
+
+namespace qpid {
+namespace client { struct ConnectionSettings; }
+
+
+/**
+ * Contains the protocol address of an AMQP broker.
+ */
+struct Address {
+public:
+ QPID_COMMON_EXTERN static const std::string TCP; // Default TCP protocol tag.
+ QPID_COMMON_EXTERN static const uint16_t AMQP_PORT=5672; // Default AMQP port.
+
+ QPID_COMMON_INLINE_EXTERN explicit Address(
+ const std::string& protocol_=std::string(),
+ const std::string& host_=std::string(),
+ uint16_t port_=0
+ ) : protocol(protocol_), host(host_), port(port_) {}
+
+ std::string protocol;
+ std::string host;
+ uint16_t port;
+};
+
+QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& os, const Address& addr);
+QPID_COMMON_EXTERN bool operator==(const Address& x, const Address& y);
+QPID_COMMON_EXTERN bool operator!=(const Address& x, const Address& y);
+
+} // namespace qpid
+
+#endif /*!QPID_ADDRESS_H*/
diff --git a/qpid/cpp/src/qpid/CommonImportExport.h b/qpid/cpp/src/qpid/CommonImportExport.h
new file mode 100644
index 0000000000..dd2b900b73
--- /dev/null
+++ b/qpid/cpp/src/qpid/CommonImportExport.h
@@ -0,0 +1,35 @@
+#ifndef QPID_COMMON_IMPORT_EXPORT_H
+#define QPID_COMMON_IMPORT_EXPORT_H
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "qpid/ImportExport.h"
+
+#if defined(COMMON_EXPORT) || defined (qpidcommon_EXPORTS)
+# define QPID_COMMON_EXTERN QPID_EXPORT
+# define QPID_COMMON_CLASS_EXTERN QPID_CLASS_EXPORT
+# define QPID_COMMON_INLINE_EXTERN QPID_INLINE_EXPORT
+#else
+# define QPID_COMMON_EXTERN QPID_IMPORT
+# define QPID_COMMON_CLASS_EXTERN QPID_CLASS_IMPORT
+# define QPID_COMMON_INLINE_EXTERN QPID_INLINE_IMPORT
+#endif
+
+#endif
diff --git a/qpid/cpp/src/qpid/Exception.h b/qpid/cpp/src/qpid/Exception.h
new file mode 100644
index 0000000000..cbd175214d
--- /dev/null
+++ b/qpid/cpp/src/qpid/Exception.h
@@ -0,0 +1,91 @@
+#ifndef _Exception_
+#define _Exception_
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/framing/amqp_types.h"
+#include "qpid/framing/constants.h"
+#include "qpid/framing/enum.h"
+#include "qpid/sys/StrError.h"
+#include "qpid/CommonImportExport.h"
+#include <string>
+#include <errno.h>
+
+namespace qpid
+{
+
+/**
+ * Base class for Qpid runtime exceptions.
+ */
+class QPID_COMMON_CLASS_EXTERN Exception : public std::exception
+{
+ public:
+ QPID_COMMON_EXTERN explicit Exception(const std::string& message=std::string()) throw();
+ QPID_COMMON_EXTERN virtual ~Exception() throw();
+ QPID_COMMON_EXTERN virtual const char* what() const throw(); // prefix: message
+ QPID_COMMON_EXTERN virtual std::string getMessage() const; // Unprefixed message
+ QPID_COMMON_EXTERN virtual std::string getPrefix() const; // Prefix
+
+ private:
+ std::string message;
+ mutable std::string whatStr;
+};
+
+/** Exception that includes an errno message. */
+struct QPID_COMMON_CLASS_EXTERN ErrnoException : public Exception {
+ ErrnoException(const std::string& msg, int err) : Exception(msg+": "+qpid::sys::strError(err)) {}
+ ErrnoException(const std::string& msg) : Exception(msg+": "+qpid::sys::strError(errno)) {}
+};
+
+struct QPID_COMMON_CLASS_EXTERN SessionException : public Exception {
+ const framing::execution::ErrorCode code;
+ SessionException(framing::execution::ErrorCode code_, const std::string& message)
+ : Exception(message), code(code_) {}
+};
+
+struct QPID_COMMON_CLASS_EXTERN ChannelException : public Exception {
+ const framing::session::DetachCode code;
+ ChannelException(framing::session::DetachCode _code, const std::string& message)
+ : Exception(message), code(_code) {}
+};
+
+struct QPID_COMMON_CLASS_EXTERN ConnectionException : public Exception {
+ const framing::connection::CloseCode code;
+ ConnectionException(framing::connection::CloseCode _code, const std::string& message)
+ : Exception(message), code(_code) {}
+};
+
+struct QPID_COMMON_CLASS_EXTERN ClosedException : public Exception {
+ QPID_COMMON_EXTERN ClosedException(const std::string& msg=std::string());
+ QPID_COMMON_EXTERN std::string getPrefix() const;
+};
+
+/**
+ * Exception representing transport failure
+ */
+struct TransportFailure : public Exception {
+ TransportFailure(const std::string& msg=std::string()) : Exception(msg) {}
+};
+
+} // namespace qpid
+
+#endif /*!_Exception_*/
diff --git a/qpid/cpp/src/qpid/InlineAllocator.h b/qpid/cpp/src/qpid/InlineAllocator.h
new file mode 100644
index 0000000000..2502545dcb
--- /dev/null
+++ b/qpid/cpp/src/qpid/InlineAllocator.h
@@ -0,0 +1,101 @@
+#ifndef QPID_INLINEALLOCATOR_H
+#define QPID_INLINEALLOCATOR_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <memory>
+#include <assert.h>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+namespace qpid {
+
+template <typename RequestedType, typename InlineType, typename BaseAllocator, size_t Max>
+struct InlineRebind;
+
+
+/**
+ * An allocator that has inline storage for up to Max objects
+ * of type BaseAllocator::value_type.
+ */
+template <class BaseAllocator, size_t Max>
+class InlineAllocator : public BaseAllocator {
+ public:
+ typedef typename BaseAllocator::pointer pointer;
+ typedef typename BaseAllocator::size_type size_type;
+ typedef typename BaseAllocator::value_type value_type;
+
+ InlineAllocator() : allocated(false) {}
+ InlineAllocator(const InlineAllocator& x) : BaseAllocator(x), allocated(false) {}
+
+ pointer allocate(size_type n) {
+ if (n <= Max && !allocated) {
+ allocated=true;
+ return reinterpret_cast<value_type*>(address());
+ }
+ else
+ return BaseAllocator::allocate(n, 0);
+ }
+
+ void deallocate(pointer p, size_type n) {
+ if (p == address()) {
+ assert(allocated);
+ allocated=false;
+ }
+ else
+ BaseAllocator::deallocate(p, n);
+ }
+
+ template<typename T1>
+ struct rebind {
+ typedef typename InlineRebind<T1, value_type, BaseAllocator, Max>::other other;
+ };
+
+ private:
+ // POD object with alignment and size to hold Max value_types.
+ static const size_t ALIGNMENT=boost::alignment_of<value_type>::value;
+ typedef typename boost::type_with_alignment<ALIGNMENT>::type Aligner;
+ union Store {
+ Aligner aligner_;
+ char sizer_[sizeof(value_type)*Max];
+ } store;
+ value_type* address() { return reinterpret_cast<value_type*>(&store); }
+ bool allocated;
+};
+
+
+// Rebind: if RequestedType == InlineType, use the InlineAllocator,
+// otherwise, use the BaseAllocator without any inlining.
+
+template <typename RequestedType, typename InlineType, typename BaseAllocator, size_t Max>
+struct InlineRebind {
+ typedef typename BaseAllocator::template rebind<RequestedType>::other other;
+};
+
+template <typename T, typename BaseAllocator, size_t Max>
+struct InlineRebind<T, T, BaseAllocator, Max> {
+ typedef typename qpid::InlineAllocator<BaseAllocator, Max> other;
+};
+
+} // namespace qpid
+
+#endif /*!QPID_INLINEALLOCATOR_H*/
diff --git a/qpid/cpp/src/qpid/InlineVector.h b/qpid/cpp/src/qpid/InlineVector.h
new file mode 100644
index 0000000000..c55db295f3
--- /dev/null
+++ b/qpid/cpp/src/qpid/InlineVector.h
@@ -0,0 +1,68 @@
+#ifndef QPID_INLINEVECTOR_H
+#define QPID_INLINEVECTOR_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/InlineAllocator.h"
+#include <vector>
+
+namespace qpid {
+
+/**
+ * A vector that stores up to Max elements in inline storage,
+ * otherwise uses normal vector allocation.
+ *
+ * NOTE: depends on some non-standard but highly probably assumptions
+ * about how std::vector uses its allocator, they are true for g++.
+ * - default constructor does not allocate.
+ * - reserve(N) does not allocate more than N elements.
+ * - vector never re-allocates when size() < capacity()
+ */
+template <class T, size_t Max, class Alloc=std::allocator<T> >
+class InlineVector : public std::vector<T, InlineAllocator<Alloc, Max> >
+{
+ typedef std::vector<T, InlineAllocator<Alloc, Max> > Base;
+ public:
+ typedef typename Base::allocator_type allocator_type;
+ typedef typename Base::value_type value_type;
+ typedef typename Base::size_type size_type;
+
+ explicit InlineVector(const allocator_type& a=allocator_type()) : Base(a) {
+ this->reserve(Max);
+ }
+
+ explicit InlineVector(size_type n, const value_type& x = value_type(),
+ const allocator_type& a=allocator_type()) : Base(a)
+ {
+ this->reserve(std::max(n, Max));
+ this->insert(this->end(), n, x);
+ }
+
+ InlineVector(const InlineVector& x) : Base() {
+ this->reserve(std::max(x.size(), Max));
+ *this = x;
+ }
+};
+
+} // namespace qpid
+
+#endif /*!QPID_INLINEVECTOR_H*/
diff --git a/qpid/cpp/src/qpid/Msg.h b/qpid/cpp/src/qpid/Msg.h
new file mode 100644
index 0000000000..5f0b11bc60
--- /dev/null
+++ b/qpid/cpp/src/qpid/Msg.h
@@ -0,0 +1,79 @@
+#ifndef QPID_MSG_H
+#define QPID_MSG_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <sstream>
+#include <iostream>
+#include "qpid/types/ImportExport.h"
+
+namespace qpid {
+
+/** A simple wrapper for std::ostringstream that allows
+ * in place construction of a message and automatic conversion
+ * to string.
+ * E.g.
+ *@code
+ * void foo(const std::string&);
+ * foo(Msg() << "hello " << 32);
+ *@endcode
+ * Will construct the string "hello 32" and pass it to foo()
+ */
+struct Msg {
+ std::ostringstream os;
+ Msg() {}
+ Msg(const Msg& m) : os(m.str()) {}
+ std::string str() const { return os.str(); }
+ operator std::string() const { return str(); }
+
+ Msg& operator<<(long n) { os << n; return *this; }
+ Msg& operator<<(unsigned long n) { os << n; return *this; }
+ Msg& operator<<(bool n) { os << n; return *this; }
+ Msg& operator<<(short n) { os << n; return *this; }
+ Msg& operator<<(unsigned short n) { os << n; return *this; }
+ Msg& operator<<(int n) { os << n; return *this; }
+ Msg& operator<<(unsigned int n) { os << n; return *this; }
+#ifdef _GLIBCXX_USE_LONG_LONG
+ Msg& operator<<(long long n) { os << n; return *this; }
+ Msg& operator<<(unsigned long long n) { os << n; return *this; }
+#endif
+ Msg& operator<<(double n) { os << n; return *this; }
+ Msg& operator<<(float n) { os << n; return *this; }
+ Msg& operator<<(long double n) { os << n; return *this; }
+
+ template <class T> Msg& operator<<(const T& t) { os <<t; return *this; }
+};
+
+
+
+inline std::ostream& operator<<(std::ostream& o, const Msg& m) {
+ return o << m.str();
+}
+
+/** Construct a message using operator << and append (file:line) */
+#define QUOTE_(x) #x
+#define QUOTE(x) QUOTE_(x)
+#define QPID_MSG(message) (::qpid::Msg() << message << " (" __FILE__ ":" QUOTE(__LINE__) ")")
+
+} // namespace qpid
+
+#endif /*!QPID_MSG_H*/
diff --git a/qpid/cpp/src/tests/ConsoleTest.cpp b/qpid/cpp/src/qpid/NullSaslClient.cpp
index 107472ed9e..d1f2706f50 100644
--- a/qpid/cpp/src/tests/ConsoleTest.cpp
+++ b/qpid/cpp/src/qpid/NullSaslClient.cpp
@@ -18,29 +18,37 @@
* under the License.
*
*/
-
-#include "qpid/console/Package.h"
-#include "qpid/console/ClassKey.h"
-#include "unit_test.h"
+#include "NullSaslClient.h"
+#include "qpid/sys/SecurityLayer.h"
+#include "Exception.h"
namespace qpid {
-namespace tests {
-
-QPID_AUTO_TEST_SUITE(ConsoleTestSuite)
-
-using namespace qpid::framing;
-using namespace qpid::console;
-
-QPID_AUTO_TEST_CASE(testClassKey) {
- uint8_t hash[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
- ClassKey k("com.redhat.test", "class", hash);
-
- BOOST_CHECK_EQUAL(k.getPackageName(), "com.redhat.test");
- BOOST_CHECK_EQUAL(k.getClassName(), "class");
- BOOST_CHECK_EQUAL(k.getHashString(), "00010203-04050607-08090a0b-0c0d0e0f");
- BOOST_CHECK_EQUAL(k.str(), "com.redhat.test:class(00010203-04050607-08090a0b-0c0d0e0f)");
+namespace {
+const std::string ANONYMOUS("ANONYMOUS");
}
-QPID_AUTO_TEST_SUITE_END()
-
-}} // namespace qpid::tests
+bool NullSaslClient::start(const std::string& mechanisms, std::string&,
+ const qpid::sys::SecuritySettings*)
+{
+ if (mechanisms.find(ANONYMOUS) == std::string::npos) {
+ throw qpid::Exception("No suitable mechanism!");
+ }
+ return false;
+}
+std::string NullSaslClient::step(const std::string&)
+{
+ return std::string();
+}
+std::string NullSaslClient::getMechanism()
+{
+ return ANONYMOUS;
+}
+std::string NullSaslClient::getUserId()
+{
+ return ANONYMOUS;
+}
+std::auto_ptr<qpid::sys::SecurityLayer> NullSaslClient::getSecurityLayer(uint16_t)
+{
+ return std::auto_ptr<qpid::sys::SecurityLayer>();
+}
+} // namespace qpid
diff --git a/qpid/cpp/src/qpid/NullSaslClient.h b/qpid/cpp/src/qpid/NullSaslClient.h
new file mode 100644
index 0000000000..b0a63a8ecb
--- /dev/null
+++ b/qpid/cpp/src/qpid/NullSaslClient.h
@@ -0,0 +1,41 @@
+#ifndef QPID_NULLSASLCLIENT_H
+#define QPID_NULLSASLCLIENT_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "Sasl.h"
+
+namespace qpid {
+
+class NullSaslClient : public Sasl
+{
+ public:
+ bool start(const std::string& mechanisms, std::string& response,
+ const qpid::sys::SecuritySettings* externalSecuritySettings = 0);
+ std::string step(const std::string& challenge);
+ std::string getMechanism();
+ std::string getUserId();
+ std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
+ private:
+};
+} // namespace qpid
+
+#endif /*!QPID_NULLSASLCLIENT_H*/
diff --git a/qpid/cpp/src/qpid/NullSaslServer.h b/qpid/cpp/src/qpid/NullSaslServer.h
index 810defe574..22a1b293a3 100644
--- a/qpid/cpp/src/qpid/NullSaslServer.h
+++ b/qpid/cpp/src/qpid/NullSaslServer.h
@@ -21,6 +21,7 @@
* under the License.
*
*/
+#include "qpid/CommonImportExport.h"
#include "qpid/SaslServer.h"
namespace qpid {
@@ -34,7 +35,7 @@ namespace qpid {
class NullSaslServer : public SaslServer
{
public:
- NullSaslServer(const std::string& realm);
+ QPID_COMMON_EXTERN NullSaslServer(const std::string& realm);
Status start(const std::string& mechanism, const std::string* response, std::string& challenge);
Status step(const std::string* response, std::string& challenge);
std::string getMechanisms();
diff --git a/qpid/cpp/src/qpid/Options.h b/qpid/cpp/src/qpid/Options.h
new file mode 100644
index 0000000000..6c908518b8
--- /dev/null
+++ b/qpid/cpp/src/qpid/Options.h
@@ -0,0 +1,193 @@
+#ifndef QPID_COMMONOPTIONS_H
+#define QPID_COMMONOPTIONS_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/Exception.h"
+
+// Disable warnings triggered by boost.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable : 4251 4275)
+#endif
+
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#include <sstream>
+#include <iterator>
+#include <algorithm>
+#include <string>
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+namespace po=boost::program_options;
+
+
+
+///@internal
+QPID_COMMON_EXTERN std::string prettyArg(const std::string&, const std::string&);
+
+/** @internal Normally only constructed by optValue() */
+template <class T>
+class OptionValue : public po::typed_value<T> {
+ public:
+ OptionValue(T& value, const std::string& arg)
+ : po::typed_value<T>(&value), argName(arg) {}
+ std::string name() const { return argName; }
+
+ private:
+ std::string argName;
+};
+
+
+/** Create an option value.
+ * name, value appear after the option name in help like this:
+ * <name> (=<value>)
+ * T must support operator <<.
+ *@see Options for example of use.
+ */
+template<class T>
+po::value_semantic* optValue(T& value, const char* name) {
+ std::string valstr(boost::lexical_cast<std::string>(value));
+ return new OptionValue<T>(value, prettyArg(name, valstr));
+}
+
+/** Create a vector value. Multiple occurences of the option are
+ * accumulated into the vector
+ */
+template <class T>
+po::value_semantic* optValue(std::vector<T>& value, const char* name) {
+ std::ostringstream os;
+ std::copy(value.begin(), value.end(), std::ostream_iterator<T>(os, " "));
+ std::string val=os.str();
+ if (!val.empty())
+ val.erase(val.end()-1); // Remove trailing " "
+ return (new OptionValue<std::vector<T> >(value, prettyArg(name, val)));
+}
+
+/** Create a boolean switch value. Presence of the option sets the value. */
+inline po::value_semantic* optValue(bool& value) {
+#if (BOOST_VERSION >= 103500)
+ return (new OptionValue<bool>(value, ""))->implicit_value(true);
+#else
+ return po::bool_switch(&value);
+#endif
+}
+
+inline po::value_semantic* pure_switch(bool& value) {
+ return po::bool_switch(&value);
+}
+
+/**
+ * Base class for options.
+ * Example of use:
+ @code
+ struct MySubOptions : public Options {
+ int x;
+ string y;
+ MySubOptions() : Options("Sub options") {
+ addOptions()
+ ("x", optValue(x,"XUNIT"), "Option X")
+ ("y", optValue(y, "YUNIT"), "Option Y");
+ }
+ };
+
+ struct MyOptions : public Options {
+ bool z;
+ vector<string> foo;
+ MySubOptions subOptions;
+ MyOptions() : Options("My Options") {
+ addOptions()
+ ("z", boolSwitch(z), "Option Z")
+ ("foo", optValue(foo), "Multiple option foo");
+ add(subOptions);
+ }
+
+ main(int argc, char** argv) {
+ Options opts;
+ opts.parse(argc, char** argv);
+ // Use values
+ dosomething(opts.subOptions.x);
+ if (error)
+ cout << opts << end; // Help message.
+ }
+
+ @endcode
+ */
+
+
+
+
+struct Options : public po::options_description {
+
+ struct Exception : public qpid::Exception {
+ Exception(const std::string& msg) : qpid::Exception(msg) {}
+ };
+
+ QPID_COMMON_EXTERN Options(const std::string& name=std::string());
+
+ /**
+ * Parses options from argc/argv, environment variables and config file.
+ * Note the filename argument can reference an options variable that
+ * is updated by argc/argv or environment variable parsing.
+ */
+ QPID_COMMON_EXTERN void parse(int argc, char const* const* argv,
+ const std::string& configfile=std::string(),
+ bool allowUnknown = false);
+
+ /**
+ * Tests for presence of argc/argv switch
+ */
+ QPID_COMMON_EXTERN bool findArg(int argc, char const* const* argv,
+ const std::string& theArg);
+
+ boost::program_options::options_description_easy_init addOptions() {
+ return add_options();
+ }
+};
+
+
+
+/**
+ * Standard options for configuration
+ */
+struct CommonOptions : public Options {
+ QPID_COMMON_EXTERN CommonOptions(const std::string& name=std::string(),
+ const std::string& configfile=std::string(),
+ const std::string& clientConfigFile=std::string());
+ bool help;
+ bool version;
+ std::string config;
+ std::string clientConfig;
+};
+
+
+
+
+} // namespace qpid
+
+#endif /*!QPID_COMMONOPTIONS_H*/
diff --git a/qpid/cpp/src/qpid/RangeSet.h b/qpid/cpp/src/qpid/RangeSet.h
new file mode 100644
index 0000000000..ef0ad032da
--- /dev/null
+++ b/qpid/cpp/src/qpid/RangeSet.h
@@ -0,0 +1,328 @@
+#ifndef QPID_RANGESET_H
+#define QPID_RANGESET_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/InlineVector.h"
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/operators.hpp>
+#include <boost/bind.hpp>
+#include <algorithm>
+#include <numeric>
+
+namespace qpid {
+
+/** A range of values, used in RangeSet.
+ * Range(begin, end) includes begin but excludes end.
+ * Range::makeClosed(first,last) includes both first and last.
+ */
+template <class T>
+class Range {
+ public:
+ static Range makeClosed(const T& first, T last) { return Range(first, ++last); }
+
+ Range() : begin_(), end_() {}
+ explicit Range(const T& t) : begin_(t), end_(t) { ++end_; }
+ Range(const T& b, const T& e) : begin_(b), end_(e) { assert(b <= e); }
+
+ T begin() const { return begin_; }
+ /** End of _open_ range, i.e. !contains(end()) */
+ T end() const { return end_; }
+
+ T first() const { assert(!empty()); return begin_; }
+ /** Last in closed range, i.e. contains(end()) */
+ T last() const { assert(!empty()); T ret=end_; return --ret; }
+
+ void begin(const T& t) { begin_ = t; }
+ void end(const T& t) { end_ = t; }
+ size_t size() const { return end_ - begin_; }
+ bool empty() const { return begin_ == end_; }
+
+ bool contains(const T& x) const { return begin_ <= x && x < end_; }
+ bool contains(const Range& r) const { return begin_ <= r.begin_ && r.end_ <= end_; }
+ bool strictContains(const Range& r) const { return begin_ < r.begin_ && r.end_ < end_; }
+
+ bool operator==(const Range& x) { return begin_ == x.begin_ && end_== x.end_; }
+
+ bool operator<(const T& t) const { return end_ < t; }
+ bool operator<(const Range<T>& r) const { return end_ < r.begin_; }
+
+ /** touching ranges can be merged into a single range. */
+ bool touching(const Range& r) const {
+ return std::max(begin_, r.begin_) <= std::min(end_, r.end_);
+ }
+
+ /** @pre touching */
+ void merge(const Range& r) {
+ assert(touching(r));
+ begin_ = std::min(begin_, r.begin_);
+ end_ = std::max(end_, r.end_);
+ }
+
+ operator bool() const { return !empty(); }
+
+ template <class S> void serialize(S& s) { s(begin_)(end_); }
+
+ private:
+ T begin_, end_;
+};
+
+
+/**
+ * A set implemented as a list of [begin, end) ranges.
+ * T must be LessThanComparable and Incrementable.
+ * RangeSet only provides const iterators.
+ */
+template <class T>
+class RangeSet
+ : boost::additive1<RangeSet<T>,
+ boost::additive2<RangeSet<T>, Range<T>,
+ boost::additive2<RangeSet<T>, T> > >
+{
+ typedef InlineVector<Range<T>, 3> Ranges; // TODO aconway 2008-04-21: what's the optimial inlined value?
+
+ public:
+
+ class iterator : public boost::iterator_facade<
+ iterator,
+ const T,
+ boost::forward_traversal_tag>
+ {
+ public:
+ iterator() : ranges(), iter(), value() {}
+
+ private:
+ typedef typename Ranges::const_iterator RangesIter;
+ iterator(const Ranges& r, const RangesIter& i, const T& t)
+ : ranges(&r), iter(i), value(t) {}
+
+ void increment();
+ bool equal(const iterator& i) const;
+ const T& dereference() const { return value; }
+
+ const Ranges* ranges;
+ RangesIter iter;
+ T value;
+
+ friend class RangeSet<T>;
+ friend class boost::iterator_core_access;
+ };
+
+ typedef iterator const_iterator;
+
+ RangeSet() {}
+ explicit RangeSet(const Range<T>& r) { *this += r; }
+ RangeSet(const T& a, const T& b) { *this += Range<T>(a,b); }
+
+ bool contiguous() const { return ranges.size() <= 1; }
+
+ bool contains(const T& t) const;
+ bool contains(const Range<T>&) const;
+
+ /**@pre contiguous() */
+ Range<T> toRange() const;
+
+ bool operator==(const RangeSet<T>&) const;
+
+ void addRange (const Range<T>&);
+ void addSet (const RangeSet<T>&);
+
+ RangeSet<T>& operator+=(const T& t) { return *this += Range<T>(t); }
+ RangeSet<T>& operator+=(const Range<T>& r) { addRange(r); return *this; }
+ RangeSet<T>& operator+=(const RangeSet<T>& s) { addSet(s); return *this; }
+
+ void removeRange (const Range<T>&);
+ void removeSet (const RangeSet<T>&);
+
+ RangeSet<T>& operator-=(const T& t) { return *this -= Range<T>(t); }
+ RangeSet<T>& operator-=(const Range<T>& r) { removeRange(r); return *this; }
+ RangeSet<T>& operator-=(const RangeSet<T>& s) { removeSet(s); return *this; }
+
+ T front() const { return ranges.front().begin(); }
+ T back() const { return ranges.back().end(); }
+
+ // Iterate over elements in the set.
+ iterator begin() const;
+ iterator end() const;
+
+ // Iterate over ranges in the set.
+ typedef typename Ranges::const_iterator RangeIterator;
+ RangeIterator rangesBegin() const { return ranges.begin(); }
+ RangeIterator rangesEnd() const { return ranges.end(); }
+ size_t rangesSize() const { return ranges.size(); }
+
+ // The difference between the start and end of this range set
+ uint32_t span() const;
+
+ size_t size() const;
+ bool empty() const { return ranges.empty(); }
+ void clear() { ranges.clear(); }
+
+ /** Return the largest contiguous range containing x.
+ * Returns the empty range [x,x) if x is not in the set.
+ */
+ Range<T> rangeContaining(const T&) const;
+
+ template <class S> void serialize(S& s) { s.split(*this); s(ranges.begin(), ranges.end()); }
+ template <class S> void encode(S& s) const { s(uint16_t(ranges.size()*sizeof(Range<T>))); }
+ template <class S> void decode(S& s) { uint16_t sz; s(sz); ranges.resize(sz/sizeof(Range<T>)); }
+
+ private:
+ static size_t accumulateSize(size_t s, const Range<T>& r) { return s+r.size(); }
+ Ranges ranges;
+
+ template <class U> friend std::ostream& operator<<(std::ostream& o, const RangeSet<U>& r);
+
+ friend class iterator;
+};
+
+template <class T>
+std::ostream& operator<<(std::ostream& o, const Range<T>& r) {
+ return o << "[" << r.begin() << "," << r.end() << ")";
+}
+
+template <class T>
+std::ostream& operator<<(std::ostream& o, const RangeSet<T>& rs) {
+ std::ostream_iterator<Range<T> > i(o, " ");
+ o << "{ ";
+ std::copy(rs.ranges.begin(), rs.ranges.end(), i);
+ return o << "}";
+}
+
+template <class T>
+bool RangeSet<T>::contains(const T& t) const {
+ typename Ranges::const_iterator i =
+ std::lower_bound(ranges.begin(), ranges.end(), Range<T>(t));
+ return i != ranges.end() && i->contains(t);
+}
+
+template <class T>
+bool RangeSet<T>::contains(const Range<T>& r) const {
+ typename Ranges::const_iterator i =
+ std::lower_bound(ranges.begin(), ranges.end(), r);
+ return i != ranges.end() && i->contains(r);
+}
+
+template <class T> void RangeSet<T>::addRange(const Range<T>& r) {
+ if (r.empty()) return;
+ typename Ranges::iterator i = std::lower_bound(ranges.begin(), ranges.end(), r);
+ if (i == ranges.end() || !i->touching(r))
+ ranges.insert(i, r); // No overlap
+ else {
+ i->merge(r);
+ typename Ranges::iterator j = i;
+ while (++j != ranges.end() && i->touching(*j))
+ i->merge(*j);
+ ranges.erase(i+1,j);
+ }
+}
+
+
+template <class T> void RangeSet<T>::addSet(const RangeSet<T>& s) {
+ typedef RangeSet<T>& (RangeSet<T>::*RangeSetRangeOp)(const Range<T>&);
+ std::for_each(s.ranges.begin(), s.ranges.end(),
+ boost::bind((RangeSetRangeOp)&RangeSet<T>::operator+=, this, _1));
+}
+
+template <class T> void RangeSet<T>::removeRange(const Range<T>& r) {
+ if (r.empty()) return;
+ typename Ranges::iterator i,j;
+ i = std::lower_bound(ranges.begin(), ranges.end(), r);
+ if (i == ranges.end() || i->begin() >= r.end())
+ return; // Outside of set
+ if (*i == r) // Erase i
+ ranges.erase(i);
+ else if (i->strictContains(r)) { // Split i
+ Range<T> i1(i->begin(), r.begin());
+ Range<T> i2(r.end(), i->end());
+ *i = i2;
+ ranges.insert(i, i1);
+ } else {
+ if (i->begin() < r.begin()) { // Truncate i
+ i->end(r.begin());
+ ++i;
+ }
+ for (j = i; j != ranges.end() && r.contains(*j); ++j)
+ ; // Ranges to erase.
+ if (j != ranges.end() && r.end() > j->begin())
+ j->begin(r.end()); // Truncate j
+ ranges.erase(i,j);
+ }
+}
+
+template <class T> void RangeSet<T>::removeSet(const RangeSet<T>& r) {
+ std::for_each(
+ r.ranges.begin(), r.ranges.end(),
+ boost::bind(&RangeSet<T>::removeRange, this, _1));
+}
+
+template <class T> Range<T> RangeSet<T>::toRange() const {
+ assert(contiguous());
+ return empty() ? Range<T>() : ranges.front();
+}
+
+template <class T> void RangeSet<T>::iterator::increment() {
+ assert(ranges && iter != ranges->end());
+ if (!iter->contains(++value)) {
+ ++iter;
+ if (iter == ranges->end())
+ *this=iterator(); // end() iterator
+ else
+ value=iter->begin();
+ }
+}
+
+template <class T> bool RangeSet<T>::operator==(const RangeSet<T>& r) const {
+ return ranges.size() == r.ranges.size() && std::equal(ranges.begin(), ranges.end(), r.ranges.begin());
+}
+
+template <class T> typename RangeSet<T>::iterator RangeSet<T>::begin() const {
+ return empty() ? end() : iterator(ranges, ranges.begin(), front());
+}
+
+template <class T> typename RangeSet<T>::iterator RangeSet<T>::end() const {
+ return iterator();
+}
+
+template <class T> bool RangeSet<T>::iterator::equal(const iterator& i) const {
+ return ranges==i.ranges && (ranges==0 || value==i.value);
+}
+
+template <class T> Range<T> RangeSet<T>::rangeContaining(const T& t) const {
+ typename Ranges::const_iterator i =
+ std::lower_bound(ranges.begin(), ranges.end(), Range<T>(t));
+ return (i != ranges.end() && i->contains(t)) ? *i : Range<T>(t,t);
+}
+
+template <class T> uint32_t RangeSet<T>::span() const {
+ if (ranges.empty()) return 0;
+ return ranges.back().last() - ranges.front().first();
+}
+
+template <class T> size_t RangeSet<T>::size() const {
+ return std::accumulate(rangesBegin(), rangesEnd(), 0, &RangeSet<T>::accumulateSize);
+}
+
+} // namespace qpid
+
+
+#endif /*!QPID_RANGESET_H*/
diff --git a/qpid/cpp/src/qpid/Sasl.h b/qpid/cpp/src/qpid/Sasl.h
index efda92d718..1164fb5ec3 100644
--- a/qpid/cpp/src/qpid/Sasl.h
+++ b/qpid/cpp/src/qpid/Sasl.h
@@ -24,6 +24,7 @@
#include <memory>
#include <string>
+#include "qpid/CommonImportExport.h"
#include "qpid/sys/IntegerTypes.h"
namespace qpid {
@@ -53,7 +54,7 @@ class Sasl
virtual std::string getMechanism() = 0;
virtual std::string getUserId() = 0;
virtual std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(uint16_t maxFrameSize) = 0;
- virtual ~Sasl() {}
+ QPID_COMMON_EXTERN virtual ~Sasl() {}
};
} // namespace qpid
diff --git a/qpid/cpp/src/qpid/SaslFactory.cpp b/qpid/cpp/src/qpid/SaslFactory.cpp
index 97e1d6e18a..bd771fc920 100644
--- a/qpid/cpp/src/qpid/SaslFactory.cpp
+++ b/qpid/cpp/src/qpid/SaslFactory.cpp
@@ -20,6 +20,7 @@
*/
#include "qpid/SaslFactory.h"
#include "qpid/SaslServer.h"
+#include "qpid/NullSaslClient.h"
#include "qpid/NullSaslServer.h"
#include <map>
#include <string.h>
@@ -48,7 +49,8 @@ SaslFactory& SaslFactory::getInstance()
std::auto_ptr<Sasl> SaslFactory::create( const std::string &, const std::string &, const std::string &, const std::string &, int, int, bool )
{
- return std::auto_ptr<Sasl>();
+ std::auto_ptr<Sasl> client(new NullSaslClient);
+ return client;
}
std::auto_ptr<SaslServer> SaslFactory::createServer(const std::string& realm, bool /*encryptionRequired*/, const qpid::sys::SecuritySettings&)
diff --git a/qpid/cpp/src/qpid/SaslFactory.h b/qpid/cpp/src/qpid/SaslFactory.h
index da7e892f1d..5d99bd2e51 100644
--- a/qpid/cpp/src/qpid/SaslFactory.h
+++ b/qpid/cpp/src/qpid/SaslFactory.h
@@ -21,6 +21,7 @@
* under the License.
*
*/
+#include "qpid/CommonImportExport.h"
#include "qpid/Sasl.h"
#include "qpid/sys/Mutex.h"
#include <memory>
diff --git a/qpid/cpp/src/qpid/SaslServer.h b/qpid/cpp/src/qpid/SaslServer.h
index a707a468eb..88909c69a9 100644
--- a/qpid/cpp/src/qpid/SaslServer.h
+++ b/qpid/cpp/src/qpid/SaslServer.h
@@ -35,7 +35,7 @@ class SaslServer
{
public:
typedef enum {OK, FAIL, CHALLENGE} Status;
- virtual ~SaslServer() {}
+ QPID_COMMON_EXTERN virtual ~SaslServer() {}
virtual Status start(const std::string& mechanism, const std::string* response, std::string& challenge) = 0;
virtual Status step(const std::string* response, std::string& challenge) = 0;
virtual std::string getMechanisms() = 0;
diff --git a/qpid/cpp/src/qpid/SessionId.h b/qpid/cpp/src/qpid/SessionId.h
new file mode 100644
index 0000000000..e18b360999
--- /dev/null
+++ b/qpid/cpp/src/qpid/SessionId.h
@@ -0,0 +1,60 @@
+#ifndef QPID_SESSIONID_H
+#define QPID_SESSIONID_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <boost/operators.hpp>
+#include <string>
+#include <qpid/CommonImportExport.h>
+
+namespace qpid {
+
+/** Identifier for a session.
+ * There are two parts to a session identifier:
+ *
+ * getUserId() returns the authentication principal associated with
+ * the session's connection.
+ *
+ * getName() returns the session name.
+ *
+ * The name must be unique among sessions with the same authentication
+ * principal.
+ */
+class SessionId : boost::totally_ordered1<SessionId> {
+ std::string userId;
+ std::string name;
+ public:
+ QPID_COMMON_EXTERN SessionId(const std::string& userId=std::string(), const std::string& name=std::string());
+ std::string getUserId() const { return userId; }
+ std::string getName() const { return name; }
+ QPID_COMMON_EXTERN bool operator<(const SessionId&) const ;
+ QPID_COMMON_EXTERN bool operator==(const SessionId& id) const;
+ // Convert to a string
+ QPID_COMMON_EXTERN std::string str() const;
+};
+
+QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const SessionId&);
+
+
+} // namespace qpid
+
+#endif /*!QPID_SESSIONID_H*/
diff --git a/qpid/cpp/src/qpid/Url.h b/qpid/cpp/src/qpid/Url.h
new file mode 100644
index 0000000000..f9ed87c24b
--- /dev/null
+++ b/qpid/cpp/src/qpid/Url.h
@@ -0,0 +1,96 @@
+#ifndef QPID_URL_H
+#define QPID_URL_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/Address.h"
+#include "qpid/Exception.h"
+#include <string>
+#include <vector>
+#include <new>
+#include <ostream>
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+
+/** An AMQP URL contains a list of addresses */
+struct Url : public std::vector<Address> {
+
+ struct Invalid : public Exception { QPID_COMMON_EXTERN Invalid(const std::string& s); };
+
+ /** Convert to string form. */
+ QPID_COMMON_EXTERN std::string str() const;
+
+ /** Empty URL. */
+ Url() {}
+
+ /** URL containing a single address */
+ explicit Url(const Address& addr) { push_back(addr); }
+
+ /** Parse url, throw Invalid if invalid. */
+ explicit Url(const std::string& url) { parse(url.c_str()); }
+ /** Parse url, throw Invalid if invalid. */
+ explicit Url(const std::string& url, const std::string& defaultProtocol) { parse(url.c_str(), defaultProtocol); }
+
+ /** Parse url, throw Invalid if invalid. */
+ explicit Url(const char* url) { parse(url); }
+
+ Url& operator=(const char* s) { parse(s); return *this; }
+ Url& operator=(const std::string& s) { parse(s); return *this; }
+
+ /** Throw Invalid if the URL does not contain any addresses. */
+ QPID_COMMON_EXTERN void throwIfEmpty() const;
+
+ /** Replace contents with parsed url
+ *@exception Invalid if the url is invalid.
+ */
+ QPID_COMMON_EXTERN void parse(const char* url);
+ QPID_COMMON_EXTERN void parse(const char* url, const std::string& defaultProtocol);
+ QPID_COMMON_INLINE_EXTERN void parse(const std::string& url) { parse(url.c_str()); }
+
+ /** Replace contesnts with parsed URL. Replace with empty URL if invalid. */
+ QPID_COMMON_EXTERN void parseNoThrow(const char* url);
+ QPID_COMMON_EXTERN void parseNoThrow(const char* url, const std::string& defaultProtocol);
+
+ /** Add a protocol tag to be recognzed in URLs.
+ * Only for use by protcol plug-in initializers.
+ */
+ QPID_COMMON_EXTERN static void addProtocol(const std::string& tag);
+
+ QPID_COMMON_EXTERN void setUser(const std::string&);
+ QPID_COMMON_EXTERN void setPass(const std::string&);
+ QPID_COMMON_EXTERN std::string getUser() const;
+ QPID_COMMON_EXTERN std::string getPass() const;
+
+ private:
+ mutable std::string cache; // cache string form for efficiency.
+ std::string user, pass;
+
+ friend class UrlParser;
+};
+
+inline bool operator==(const Url& a, const Url& b) { return a.str()==b.str(); }
+inline bool operator!=(const Url& a, const Url& b) { return a.str()!=b.str(); }
+
+QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& os, const Url& url);
+QPID_COMMON_EXTERN std::istream& operator>>(std::istream& is, Url& url);
+
+} // namespace qpid
+
+#endif /*!QPID_URL_H*/
diff --git a/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp b/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp
index 3d703066b4..7a5d0ab53d 100644
--- a/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp
+++ b/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp
@@ -102,10 +102,12 @@ bool ConnectionCounter::countConnectionLH(
if (eRef != theMap.end()) {
count = (uint16_t)(*eRef).second + 1;
(*eRef).second = count;
- result = (enforceLimit ? count <= theLimit : true);
} else {
theMap[theName] = count = 1;
}
+ if (enforceLimit) {
+ result = count <= theLimit;
+ }
if (emitLog) {
QPID_LOG(trace, "ACL ConnectionApprover user=" << theName
<< " limit=" << theLimit
diff --git a/qpid/cpp/src/qpid/agent/ManagementAgentImpl.cpp b/qpid/cpp/src/qpid/agent/ManagementAgentImpl.cpp
deleted file mode 100644
index a48789973a..0000000000
--- a/qpid/cpp/src/qpid/agent/ManagementAgentImpl.cpp
+++ /dev/null
@@ -1,1434 +0,0 @@
-
-//
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-//
-
-#include "qpid/management/Manageable.h"
-#include "qpid/management/ManagementObject.h"
-#include "qpid/log/Statement.h"
-#include "qpid/agent/ManagementAgentImpl.h"
-#include "qpid/amqp_0_10/Codecs.h"
-#include <list>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <iostream>
-#include <fstream>
-#include <boost/lexical_cast.hpp>
-
-namespace qpid {
-namespace management {
-
-using namespace qpid::client;
-using namespace qpid::framing;
-using namespace qpid::sys;
-using namespace std;
-using std::stringstream;
-using std::ofstream;
-using std::ifstream;
-using std::string;
-using std::endl;
-using qpid::types::Variant;
-using qpid::amqp_0_10::MapCodec;
-using qpid::amqp_0_10::ListCodec;
-
-namespace {
- qpid::sys::Mutex lock;
- bool disabled = false;
- ManagementAgent* agent = 0;
- int refCount = 0;
-
- const string defaultVendorName("vendor");
- const string defaultProductName("product");
-
- // Create a valid binding key substring by
- // replacing all '.' chars with '_'
- const string keyifyNameStr(const string& name)
- {
- string n2 = name;
-
- size_t pos = n2.find('.');
- while (pos != n2.npos) {
- n2.replace(pos, 1, "_");
- pos = n2.find('.', pos);
- }
- return n2;
- }
-}
-
-ManagementAgent::Singleton::Singleton(bool disableManagement)
-{
- sys::Mutex::ScopedLock _lock(lock);
- if (disableManagement && !disabled) {
- disabled = true;
- assert(refCount == 0); // can't disable after agent has been allocated
- }
- if (refCount == 0 && !disabled)
- agent = new ManagementAgentImpl();
- refCount++;
-}
-
-ManagementAgent::Singleton::~Singleton()
-{
- sys::Mutex::ScopedLock _lock(lock);
- refCount--;
- if (refCount == 0 && !disabled) {
- delete agent;
- agent = 0;
- }
-}
-
-ManagementAgent* ManagementAgent::Singleton::getInstance()
-{
- return agent;
-}
-
-const string ManagementAgentImpl::storeMagicNumber("MA02");
-
-ManagementAgentImpl::ManagementAgentImpl() :
- interval(10), extThread(false), pipeHandle(0), notifyCallback(0), notifyContext(0),
- notifyable(0), inCallback(false),
- initialized(false), connected(false), useMapMsg(false), lastFailure("never connected"),
- topicExchange("qmf.default.topic"), directExchange("qmf.default.direct"),
- schemaTimestamp(Duration(EPOCH, now())),
- publishAllData(true), requestedBrokerBank(0), requestedAgentBank(0),
- assignedBrokerBank(0), assignedAgentBank(0), bootSequence(0),
- maxV2ReplyObjs(10), // KAG todo: make this a tuneable parameter
- connThreadBody(*this), connThread(connThreadBody),
- pubThreadBody(*this), pubThread(pubThreadBody)
-{
-}
-
-ManagementAgentImpl::~ManagementAgentImpl()
-{
- // shutdown & cleanup all threads
- connThreadBody.close();
- pubThreadBody.close();
-
- connThread.join();
- pubThread.join();
-
- if (pipeHandle) {
- delete pipeHandle;
- pipeHandle = 0;
- }
-}
-
-void ManagementAgentImpl::setName(const string& vendor, const string& product, const string& instance)
-{
- if (vendor.find(':') != vendor.npos) {
- throw Exception("vendor string cannot contain a ':' character.");
- }
- if (product.find(':') != product.npos) {
- throw Exception("product string cannot contain a ':' character.");
- }
-
- attrMap["_vendor"] = vendor;
- attrMap["_product"] = product;
- if (!instance.empty()) {
- attrMap["_instance"] = instance;
- }
-}
-
-
-void ManagementAgentImpl::getName(string& vendor, string& product, string& instance)
-{
- vendor = std::string(attrMap["_vendor"]);
- product = std::string(attrMap["_product"]);
- instance = std::string(attrMap["_instance"]);
-}
-
-
-const std::string& ManagementAgentImpl::getAddress()
-{
- return name_address;
-}
-
-
-void ManagementAgentImpl::init(const string& brokerHost,
- uint16_t brokerPort,
- uint16_t intervalSeconds,
- bool useExternalThread,
- const string& _storeFile,
- const string& uid,
- const string& pwd,
- const string& mech,
- const string& proto)
-{
- management::ConnectionSettings settings;
- settings.protocol = proto;
- settings.host = brokerHost;
- settings.port = brokerPort;
- settings.username = uid;
- settings.password = pwd;
- settings.mechanism = mech;
- settings.heartbeat = 10;
- init(settings, intervalSeconds, useExternalThread, _storeFile);
-}
-
-void ManagementAgentImpl::init(const qpid::management::ConnectionSettings& settings,
- uint16_t intervalSeconds,
- bool useExternalThread,
- const string& _storeFile)
-{
- std::string cfgVendor, cfgProduct, cfgInstance;
-
- interval = intervalSeconds;
- extThread = useExternalThread;
- storeFile = _storeFile;
- nextObjectId = 1;
-
- //
- // Convert from management::ConnectionSettings to client::ConnectionSettings
- //
- connectionSettings.protocol = settings.protocol;
- connectionSettings.host = settings.host;
- connectionSettings.port = settings.port;
- connectionSettings.virtualhost = settings.virtualhost;
- connectionSettings.username = settings.username;
- connectionSettings.password = settings.password;
- connectionSettings.mechanism = settings.mechanism;
- connectionSettings.locale = settings.locale;
- connectionSettings.heartbeat = settings.heartbeat;
- connectionSettings.maxChannels = settings.maxChannels;
- connectionSettings.maxFrameSize = settings.maxFrameSize;
- connectionSettings.bounds = settings.bounds;
- connectionSettings.tcpNoDelay = settings.tcpNoDelay;
- connectionSettings.service = settings.service;
- connectionSettings.minSsf = settings.minSsf;
- connectionSettings.maxSsf = settings.maxSsf;
-
- retrieveData(cfgVendor, cfgProduct, cfgInstance);
-
- bootSequence++;
- if ((bootSequence & 0xF000) != 0)
- bootSequence = 1;
-
- // setup the agent's name. The name may be set via a call to setName(). If setName()
- // has not been called, the name can be read from the configuration file. If there is
- // no name in the configuration file, a unique default name is provided.
- if (attrMap.empty()) {
- // setName() never called by application, so use names retrieved from config, otherwise defaults.
- setName(cfgVendor.empty() ? defaultVendorName : cfgVendor,
- cfgProduct.empty() ? defaultProductName : cfgProduct,
- cfgInstance.empty() ? qpid::types::Uuid(true).str() : cfgInstance);
- } else if (attrMap.find("_instance") == attrMap.end()) {
- // setName() called, but instance was not specified, use config or generate a uuid
- setName(attrMap["_vendor"].asString(), attrMap["_product"].asString(),
- cfgInstance.empty() ? qpid::types::Uuid(true).str() : cfgInstance);
- }
-
- name_address = attrMap["_vendor"].asString() + ":" + attrMap["_product"].asString() + ":" + attrMap["_instance"].asString();
- vendorNameKey = keyifyNameStr(attrMap["_vendor"].asString());
- productNameKey = keyifyNameStr(attrMap["_product"].asString());
- instanceNameKey = keyifyNameStr(attrMap["_instance"].asString());
- attrMap["_name"] = name_address;
-
- storeData(true);
-
- QPID_LOG(info, "QMF Agent Initialized: broker=" << settings.host << ":" << settings.port <<
- " interval=" << intervalSeconds << " storeFile=" << _storeFile << " name=" << name_address);
-
- initialized = true;
-}
-
-void ManagementAgentImpl::registerClass(const string& packageName,
- const string& className,
- uint8_t* md5Sum,
- ManagementObject::writeSchemaCall_t schemaCall)
-{
- sys::Mutex::ScopedLock lock(agentLock);
- PackageMap::iterator pIter = findOrAddPackage(packageName);
- addClassLocal(ManagementItem::CLASS_KIND_TABLE, pIter, className, md5Sum, schemaCall);
-}
-
-void ManagementAgentImpl::registerEvent(const string& packageName,
- const string& eventName,
- uint8_t* md5Sum,
- ManagementObject::writeSchemaCall_t schemaCall)
-{
- sys::Mutex::ScopedLock lock(agentLock);
- PackageMap::iterator pIter = findOrAddPackage(packageName);
- addClassLocal(ManagementItem::CLASS_KIND_EVENT, pIter, eventName, md5Sum, schemaCall);
-}
-
-// old-style add object: 64bit id - deprecated
-ObjectId ManagementAgentImpl::addObject(ManagementObject* object,
- uint64_t persistId)
-{
- std::string key;
- if (persistId) {
- key = boost::lexical_cast<std::string>(persistId);
- }
- return addObject(object, key, persistId != 0);
-}
-
-
-// new style add object - use this approach!
-ObjectId ManagementAgentImpl::addObject(ManagementObject* object,
- const std::string& key,
- bool persistent)
-{
- sys::Mutex::ScopedLock lock(addLock);
-
- uint16_t sequence = persistent ? 0 : bootSequence;
-
- ObjectId objectId(&attachment, 0, sequence);
- if (key.empty())
- objectId.setV2Key(*object); // let object generate the key
- else
- objectId.setV2Key(key);
- objectId.setAgentName(name_address);
-
- object->setObjectId(objectId);
- newManagementObjects[objectId] = boost::shared_ptr<ManagementObject>(object);
- return objectId;
-}
-
-
-void ManagementAgentImpl::raiseEvent(const ManagementEvent& event, severity_t severity)
-{
- static const std::string severityStr[] = {
- "emerg", "alert", "crit", "error", "warn",
- "note", "info", "debug"
- };
- string content;
- stringstream key;
- Variant::Map headers;
-
- {
- sys::Mutex::ScopedLock lock(agentLock);
- Buffer outBuffer(eventBuffer, MA_BUFFER_SIZE);
- uint8_t sev = (severity == SEV_DEFAULT) ? event.getSeverity() : (uint8_t) severity;
-
- // key << "console.event." << assignedBrokerBank << "." << assignedAgentBank << "." <<
- // event.getPackageName() << "." << event.getEventName();
- key << "agent.ind.event." << keyifyNameStr(event.getPackageName())
- << "." << keyifyNameStr(event.getEventName())
- << "." << severityStr[sev]
- << "." << vendorNameKey
- << "." << productNameKey
- << "." << instanceNameKey;
-
- Variant::Map map_;
- Variant::Map schemaId;
- Variant::Map values;
-
- map_["_schema_id"] = mapEncodeSchemaId(event.getPackageName(),
- event.getEventName(),
- event.getMd5Sum(),
- ManagementItem::CLASS_KIND_EVENT);
- event.mapEncode(values);
- map_["_values"] = values;
- map_["_timestamp"] = uint64_t(Duration(EPOCH, now()));
- map_["_severity"] = sev;
-
- headers["method"] = "indication";
- headers["qmf.opcode"] = "_data_indication";
- headers["qmf.content"] = "_event";
- headers["qmf.agent"] = name_address;
-
- Variant::List list;
- list.push_back(map_);
- ListCodec::encode(list, content);
- }
-
- connThreadBody.sendBuffer(content, "", headers, topicExchange, key.str(), "amqp/list");
-}
-
-uint32_t ManagementAgentImpl::pollCallbacks(uint32_t callLimit)
-{
- sys::Mutex::ScopedLock lock(agentLock);
-
- if (inCallback) {
- QPID_LOG(critical, "pollCallbacks invoked from the agent's thread!");
- return 0;
- }
-
- for (uint32_t idx = 0; callLimit == 0 || idx < callLimit; idx++) {
- if (methodQueue.empty())
- break;
-
- QueuedMethod* item = methodQueue.front();
- methodQueue.pop_front();
- {
- sys::Mutex::ScopedUnlock unlock(agentLock);
- invokeMethodRequest(item->body, item->cid, item->replyToExchange, item->replyToKey, item->userId);
- delete item;
- }
- }
-
- if (pipeHandle != 0) {
- char rbuf[100];
- while (pipeHandle->read(rbuf, 100) > 0) ; // Consume all signaling bytes
- }
- return methodQueue.size();
-}
-
-int ManagementAgentImpl::getSignalFd()
-{
- if (extThread) {
- if (pipeHandle == 0)
- pipeHandle = new PipeHandle(true);
- return pipeHandle->getReadHandle();
- }
-
- return -1;
-}
-
-void ManagementAgentImpl::setSignalCallback(cb_t callback, void* context)
-{
- sys::Mutex::ScopedLock lock(agentLock);
- notifyCallback = callback;
- notifyContext = context;
-}
-
-void ManagementAgentImpl::setSignalCallback(Notifyable& _notifyable)
-{
- sys::Mutex::ScopedLock lock(agentLock);
- notifyable = &_notifyable;
-}
-
-void ManagementAgentImpl::startProtocol()
-{
- sendHeartbeat();
- {
- sys::Mutex::ScopedLock lock(agentLock);
- publishAllData = true;
- }
-}
-
-void ManagementAgentImpl::storeData(bool requested)
-{
- if (!storeFile.empty()) {
- ofstream outFile(storeFile.c_str());
- uint32_t brokerBankToWrite = requested ? requestedBrokerBank : assignedBrokerBank;
- uint32_t agentBankToWrite = requested ? requestedAgentBank : assignedAgentBank;
-
- if (outFile.good()) {
- outFile << storeMagicNumber << " " << brokerBankToWrite << " " <<
- agentBankToWrite << " " << bootSequence << endl;
-
- if (attrMap.find("_vendor") != attrMap.end())
- outFile << "vendor=" << attrMap["_vendor"] << endl;
- if (attrMap.find("_product") != attrMap.end())
- outFile << "product=" << attrMap["_product"] << endl;
- if (attrMap.find("_instance") != attrMap.end())
- outFile << "instance=" << attrMap["_instance"] << endl;
-
- outFile.close();
- }
- }
-}
-
-void ManagementAgentImpl::retrieveData(std::string& vendor, std::string& product, std::string& inst)
-{
- vendor.clear();
- product.clear();
- inst.clear();
-
- if (!storeFile.empty()) {
- ifstream inFile(storeFile.c_str());
- string mn;
-
- if (inFile.good()) {
- inFile >> mn;
- if (mn == storeMagicNumber) {
- std::string inText;
-
- inFile >> requestedBrokerBank;
- inFile >> requestedAgentBank;
- inFile >> bootSequence;
-
- while (inFile.good()) {
- std::getline(inFile, inText);
- if (!inText.compare(0, 7, "vendor=")) {
- vendor = inText.substr(7);
- QPID_LOG(debug, "read vendor name [" << vendor << "] from configuration file.");
- } else if (!inText.compare(0, 8, "product=")) {
- product = inText.substr(8);
- QPID_LOG(debug, "read product name [" << product << "] from configuration file.");
- } else if (!inText.compare(0, 9, "instance=")) {
- inst = inText.substr(9);
- QPID_LOG(debug, "read instance name [" << inst << "] from configuration file.");
- }
- }
- }
- inFile.close();
- }
- }
-}
-
-void ManagementAgentImpl::sendHeartbeat()
-{
- static const string addr_key_base("agent.ind.heartbeat.");
-
- Variant::Map map;
- Variant::Map headers;
- string content;
- std::stringstream addr_key;
-
- addr_key << addr_key_base << vendorNameKey
- << "." << productNameKey
- << "." << instanceNameKey;
-
- headers["method"] = "indication";
- headers["qmf.opcode"] = "_agent_heartbeat_indication";
- headers["qmf.agent"] = name_address;
-
- getHeartbeatContent(map);
- MapCodec::encode(map, content);
-
- // Set TTL (in msecs) on outgoing heartbeat indications based on the interval
- // time to prevent stale heartbeats from getting to the consoles.
-
- connThreadBody.sendBuffer(content, "", headers, topicExchange, addr_key.str(),
- "amqp/map", interval * 2 * 1000);
-
- QPID_LOG(trace, "SENT AgentHeartbeat name=" << name_address);
-}
-
-void ManagementAgentImpl::sendException(const string& rte, const string& rtk, const string& cid,
- const string& text, uint32_t code)
-{
- Variant::Map map;
- Variant::Map headers;
- Variant::Map values;
- string content;
-
- headers["method"] = "indication";
- headers["qmf.opcode"] = "_exception";
- headers["qmf.agent"] = name_address;
-
- values["error_code"] = code;
- values["error_text"] = text;
- map["_values"] = values;
-
- MapCodec::encode(map, content);
- connThreadBody.sendBuffer(content, cid, headers, rte, rtk);
-
- QPID_LOG(trace, "SENT Exception code=" << code <<" text=" << text);
-}
-
-void ManagementAgentImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence, const string& rte, const string& rtk)
-{
- string packageName;
- SchemaClassKey key;
- uint32_t outLen(0);
- char localBuffer[MA_BUFFER_SIZE];
- Buffer outBuffer(localBuffer, MA_BUFFER_SIZE);
- bool found(false);
-
- inBuffer.getShortString(packageName);
- inBuffer.getShortString(key.name);
- inBuffer.getBin128(key.hash);
-
- QPID_LOG(trace, "RCVD SchemaRequest: package=" << packageName << " class=" << key.name);
-
- {
- sys::Mutex::ScopedLock lock(agentLock);
- PackageMap::iterator pIter = packages.find(packageName);
- if (pIter != packages.end()) {
- ClassMap& cMap = pIter->second;
- ClassMap::iterator cIter = cMap.find(key);
- if (cIter != cMap.end()) {
- SchemaClass& schema = cIter->second;
- string body;
-
- encodeHeader(outBuffer, 's', sequence);
- schema.writeSchemaCall(body);
- outBuffer.putRawData(body);
- outLen = MA_BUFFER_SIZE - outBuffer.available();
- outBuffer.reset();
- found = true;
- }
- }
- }
-
- if (found) {
- connThreadBody.sendBuffer(outBuffer, outLen, rte, rtk);
- QPID_LOG(trace, "SENT SchemaInd: package=" << packageName << " class=" << key.name);
- }
-}
-
-void ManagementAgentImpl::handleConsoleAddedIndication()
-{
- sys::Mutex::ScopedLock lock(agentLock);
- publishAllData = true;
-
- QPID_LOG(trace, "RCVD ConsoleAddedInd");
-}
-
-void ManagementAgentImpl::invokeMethodRequest(const string& body, const string& cid, const string& rte, const string& rtk, const string& userId)
-{
- string methodName;
- bool failed = false;
- Variant::Map inMap;
- Variant::Map outMap;
- Variant::Map::const_iterator oid, mid;
- string content;
-
- MapCodec::decode(body, inMap);
-
- if ((oid = inMap.find("_object_id")) == inMap.end() ||
- (mid = inMap.find("_method_name")) == inMap.end()) {
- sendException(rte, rtk, cid, Manageable::StatusText(Manageable::STATUS_PARAMETER_INVALID),
- Manageable::STATUS_PARAMETER_INVALID);
- failed = true;
- } else {
- string methodName;
- ObjectId objId;
- Variant::Map inArgs;
- Variant::Map callMap;
-
- try {
- // conversions will throw if input is invalid.
- objId = ObjectId(oid->second.asMap());
- methodName = mid->second.getString();
-
- mid = inMap.find("_arguments");
- if (mid != inMap.end()) {
- inArgs = (mid->second).asMap();
- }
-
- QPID_LOG(trace, "Invoking Method: name=" << methodName << " args=" << inArgs);
-
- boost::shared_ptr<ManagementObject> oPtr;
- {
- sys::Mutex::ScopedLock lock(agentLock);
- ObjectMap::iterator iter = managementObjects.find(objId);
- if (iter != managementObjects.end() && !iter->second->isDeleted())
- oPtr = iter->second;
- }
-
- if (oPtr.get() == 0) {
- sendException(rte, rtk, cid, Manageable::StatusText(Manageable::STATUS_UNKNOWN_OBJECT),
- Manageable::STATUS_UNKNOWN_OBJECT);
- failed = true;
- } else {
- oPtr->doMethod(methodName, inArgs, callMap, userId);
-
- if (callMap["_status_code"].asUint32() == 0) {
- outMap["_arguments"] = Variant::Map();
- for (Variant::Map::const_iterator iter = callMap.begin();
- iter != callMap.end(); iter++)
- if (iter->first != "_status_code" && iter->first != "_status_text")
- outMap["_arguments"].asMap()[iter->first] = iter->second;
- } else {
- sendException(rte, rtk, cid, callMap["_status_text"], callMap["_status_code"]);
- failed = true;
- }
- }
-
- } catch(types::InvalidConversion& e) {
- sendException(rte, rtk, cid, e.what(), Manageable::STATUS_EXCEPTION);
- failed = true;
- }
- }
-
- if (!failed) {
- Variant::Map headers;
- headers["method"] = "response";
- headers["qmf.agent"] = name_address;
- headers["qmf.opcode"] = "_method_response";
- QPID_LOG(trace, "SENT MethodResponse map=" << outMap);
- MapCodec::encode(outMap, content);
- connThreadBody.sendBuffer(content, cid, headers, rte, rtk);
- }
-}
-
-void ManagementAgentImpl::handleGetQuery(const string& body, const string& cid, const string& rte, const string& rtk)
-{
- {
- sys::Mutex::ScopedLock lock(agentLock);
- moveNewObjectsLH(lock);
- }
-
- Variant::Map inMap;
- Variant::Map::const_iterator i;
- Variant::Map headers;
-
- MapCodec::decode(body, inMap);
- QPID_LOG(trace, "RCVD GetQuery: map=" << inMap << " cid=" << cid);
-
- headers["method"] = "response";
- headers["qmf.opcode"] = "_query_response";
- headers["qmf.agent"] = name_address;
- headers["partial"] = Variant();
-
- Variant::List list_;
- Variant::Map map_;
- Variant::Map values;
- Variant::Map oidMap;
- string content;
-
- /*
- * Unpack the _what element of the query. Currently we only support OBJECT queries.
- */
- i = inMap.find("_what");
- if (i == inMap.end()) {
- sendException(rte, rtk, cid, "_what element missing in Query");
- return;
- }
-
- if (i->second.getType() != qpid::types::VAR_STRING) {
- sendException(rte, rtk, cid, "_what element is not a string");
- return;
- }
-
- if (i->second.asString() == "OBJECT") {
- headers["qmf.content"] = "_data";
- /*
- * Unpack the _object_id element of the query if it is present. If it is present, find that one
- * object and return it. If it is not present, send a class-based result.
- */
- i = inMap.find("_object_id");
- if (i != inMap.end() && i->second.getType() == qpid::types::VAR_MAP) {
- ObjectId objId(i->second.asMap());
- boost::shared_ptr<ManagementObject> object;
-
- {
- sys::Mutex::ScopedLock lock(agentLock);
- ObjectMap::iterator iter = managementObjects.find(objId);
- if (iter != managementObjects.end())
- object = iter->second;
- }
-
- if (object.get() != 0) {
- if (object->getConfigChanged() || object->getInstChanged())
- object->setUpdateTime();
-
- object->mapEncodeValues(values, true, true); // write both stats and properties
- objId.mapEncode(oidMap);
- map_["_values"] = values;
- map_["_object_id"] = oidMap;
- object->writeTimestamps(map_);
- map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(),
- object->getClassName(),
- object->getMd5Sum());
- list_.push_back(map_);
- headers.erase("partial");
-
- ListCodec::encode(list_, content);
- connThreadBody.sendBuffer(content, cid, headers, rte, rtk, "amqp/list");
- QPID_LOG(trace, "SENT QueryResponse (query by object_id) to=" << rte << "/" << rtk);
- return;
- }
- } else { // match using schema_id, if supplied
-
- string className;
- string packageName;
-
- i = inMap.find("_schema_id");
- if (i != inMap.end() && i->second.getType() == qpid::types::VAR_MAP) {
- const Variant::Map& schemaIdMap(i->second.asMap());
-
- Variant::Map::const_iterator s_iter = schemaIdMap.find("_class_name");
- if (s_iter != schemaIdMap.end() && s_iter->second.getType() == qpid::types::VAR_STRING)
- className = s_iter->second.asString();
-
- s_iter = schemaIdMap.find("_package_name");
- if (s_iter != schemaIdMap.end() && s_iter->second.getType() == qpid::types::VAR_STRING)
- packageName = s_iter->second.asString();
-
- typedef list<boost::shared_ptr<ManagementObject> > StageList;
- StageList staging;
-
- {
- sys::Mutex::ScopedLock lock(agentLock);
- for (ObjectMap::iterator iter = managementObjects.begin();
- iter != managementObjects.end();
- iter++) {
- ManagementObject* object = iter->second.get();
- if (object->getClassName() == className &&
- (packageName.empty() || object->getPackageName() == packageName))
- staging.push_back(iter->second);
- }
- }
-
- unsigned int objCount = 0;
- for (StageList::iterator iter = staging.begin(); iter != staging.end(); iter++) {
- ManagementObject* object = iter->get();
- if (object->getClassName() == className &&
- (packageName.empty() || object->getPackageName() == packageName)) {
-
- values.clear();
- oidMap.clear();
- map_.clear();
-
- if (object->getConfigChanged() || object->getInstChanged())
- object->setUpdateTime();
-
- object->mapEncodeValues(values, true, true); // write both stats and properties
- object->getObjectId().mapEncode(oidMap);
- map_["_values"] = values;
- map_["_object_id"] = oidMap;
- object->writeTimestamps(map_);
- map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(),
- object->getClassName(),
- object->getMd5Sum());
- list_.push_back(map_);
-
- if (++objCount >= maxV2ReplyObjs) {
- objCount = 0;
- ListCodec::encode(list_, content);
- connThreadBody.sendBuffer(content, cid, headers, rte, rtk, "amqp/list");
- QPID_LOG(trace, "SENT QueryResponse (query by schema_id) to=" << rte << "/" << rtk);
- content.clear();
- list_.clear();
- }
- }
- }
- }
- }
-
- // Send last "non-partial" message to indicate CommandComplete
- headers.erase("partial");
- ListCodec::encode(list_, content);
- connThreadBody.sendBuffer(content, cid, headers, rte, rtk, "amqp/list");
- QPID_LOG(trace, "SENT QueryResponse (last message, no 'partial' indicator) to=" << rte << "/" << rtk);
-
- } else if (i->second.asString() == "SCHEMA_ID") {
- headers["qmf.content"] = "_schema_id";
- /**
- * @todo - support for a predicate. For now, send a list of all known schema class keys.
- */
- for (PackageMap::iterator pIter = packages.begin();
- pIter != packages.end(); pIter++) {
- for (ClassMap::iterator cIter = pIter->second.begin();
- cIter != pIter->second.end(); cIter++) {
-
- list_.push_back(mapEncodeSchemaId( pIter->first,
- cIter->first.name,
- cIter->first.hash,
- cIter->second.kind ));
- }
- }
-
- headers.erase("partial");
- ListCodec::encode(list_, content);
- connThreadBody.sendBuffer(content, cid, headers, rte, rtk, "amqp/list");
- QPID_LOG(trace, "SENT QueryResponse (SchemaId) to=" << rte << "/" << rtk);
-
- } else {
- // Unknown query target
- sendException(rte, rtk, cid, "Query for _what => '" + i->second.asString() + "' not supported");
- }
-}
-
-void ManagementAgentImpl::handleLocateRequest(const string&, const string& cid, const string& rte, const string& rtk)
-{
- QPID_LOG(trace, "RCVD AgentLocateRequest");
-
- Variant::Map map;
- Variant::Map headers;
- string content;
-
- headers["method"] = "indication";
- headers["qmf.opcode"] = "_agent_locate_response";
- headers["qmf.agent"] = name_address;
-
- getHeartbeatContent(map);
- MapCodec::encode(map, content);
- connThreadBody.sendBuffer(content, cid, headers, rte, rtk);
-
- QPID_LOG(trace, "SENT AgentLocateResponse replyTo=" << rte << "/" << rtk);
-
- {
- sys::Mutex::ScopedLock lock(agentLock);
- publishAllData = true;
- }
-}
-
-void ManagementAgentImpl::handleMethodRequest(const string& body, const string& cid, const string& rte, const string& rtk, const string& userId)
-{
- if (extThread) {
- sys::Mutex::ScopedLock lock(agentLock);
-
- methodQueue.push_back(new QueuedMethod(cid, rte, rtk, body, userId));
- if (pipeHandle != 0) {
- pipeHandle->write("X", 1);
- } else if (notifyable != 0) {
- inCallback = true;
- {
- sys::Mutex::ScopedUnlock unlock(agentLock);
- notifyable->notify();
- }
- inCallback = false;
- } else if (notifyCallback != 0) {
- inCallback = true;
- {
- sys::Mutex::ScopedUnlock unlock(agentLock);
- notifyCallback(notifyContext);
- }
- inCallback = false;
- }
- } else {
- invokeMethodRequest(body, cid, rte, rtk, userId);
- }
-
- QPID_LOG(trace, "RCVD MethodRequest");
-}
-
-void ManagementAgentImpl::received(Message& msg)
-{
- string replyToExchange;
- string replyToKey;
- framing::MessageProperties mp = msg.getMessageProperties();
- if (mp.hasReplyTo()) {
- const framing::ReplyTo& rt = mp.getReplyTo();
- replyToExchange = rt.getExchange();
- replyToKey = rt.getRoutingKey();
- }
-
- string userId;
- if (mp.hasUserId())
- userId = mp.getUserId();
-
- if (mp.hasAppId() && mp.getAppId() == "qmf2")
- {
- string opcode = mp.getApplicationHeaders().getAsString("qmf.opcode");
- string cid = msg.getMessageProperties().getCorrelationId();
-
- if (opcode == "_agent_locate_request") handleLocateRequest(msg.getData(), cid, replyToExchange, replyToKey);
- else if (opcode == "_method_request") handleMethodRequest(msg.getData(), cid, replyToExchange, replyToKey, userId);
- else if (opcode == "_query_request") handleGetQuery(msg.getData(), cid, replyToExchange, replyToKey);
- else {
- QPID_LOG(warning, "Support for QMF V2 Opcode [" << opcode << "] TBD!!!");
- }
- return;
- }
-
- // old preV2 binary messages
-
- uint32_t sequence;
- string data = msg.getData();
- Buffer inBuffer(const_cast<char*>(data.c_str()), data.size());
- uint8_t opcode;
-
-
- if (checkHeader(inBuffer, &opcode, &sequence))
- {
- if (opcode == 'S') handleSchemaRequest(inBuffer, sequence, replyToExchange, replyToKey);
- else if (opcode == 'x') handleConsoleAddedIndication();
- else
- QPID_LOG(warning, "Ignoring old-format QMF Request! opcode=" << char(opcode));
- }
-}
-
-
-void ManagementAgentImpl::encodeHeader(Buffer& buf, uint8_t opcode, uint32_t seq)
-{
- buf.putOctet('A');
- buf.putOctet('M');
- buf.putOctet('2');
- buf.putOctet(opcode);
- buf.putLong (seq);
-}
-
-Variant::Map ManagementAgentImpl::mapEncodeSchemaId(const string& pname,
- const string& cname,
- const uint8_t *md5Sum,
- uint8_t type)
-{
- Variant::Map map_;
-
- map_["_package_name"] = pname;
- map_["_class_name"] = cname;
- map_["_hash"] = types::Uuid(md5Sum);
- if (type == ManagementItem::CLASS_KIND_EVENT)
- map_["_type"] = "_event";
- else
- map_["_type"] = "_data";
-
- return map_;
-}
-
-
-bool ManagementAgentImpl::checkHeader(Buffer& buf, uint8_t *opcode, uint32_t *seq)
-{
- if (buf.getSize() < 8)
- return false;
-
- uint8_t h1 = buf.getOctet();
- uint8_t h2 = buf.getOctet();
- uint8_t h3 = buf.getOctet();
-
- *opcode = buf.getOctet();
- *seq = buf.getLong();
-
- return h1 == 'A' && h2 == 'M' && h3 == '2';
-}
-
-ManagementAgentImpl::PackageMap::iterator ManagementAgentImpl::findOrAddPackage(const string& name)
-{
- PackageMap::iterator pIter = packages.find(name);
- if (pIter != packages.end())
- return pIter;
-
- // No such package found, create a new map entry.
- pair<PackageMap::iterator, bool> result =
- packages.insert(pair<string, ClassMap>(name, ClassMap()));
-
- return result.first;
-}
-
-// note well: caller must hold agentLock when calling this!
-void ManagementAgentImpl::moveNewObjectsLH(const sys::Mutex::ScopedLock& /*agentLock*/)
-{
- sys::Mutex::ScopedLock lock(addLock);
- ObjectMap::iterator newObj = newManagementObjects.begin();
- while (newObj != newManagementObjects.end()) {
- // before adding a new mgmt object, check for duplicates:
- ObjectMap::iterator oldObj = managementObjects.find(newObj->first);
- if (oldObj == managementObjects.end()) {
- managementObjects[newObj->first] = newObj->second;
- newManagementObjects.erase(newObj++); // post inc iterator safe!
- } else {
- // object exists with same object id. This may be legit, for example, when a
- // recently deleted object is re-added before the mgmt poll runs.
- if (newObj->second->isDeleted()) {
- // @TODO fixme: we missed an add-delete for the new object
- QPID_LOG(warning, "Mgmt Object deleted before update sent, oid=" << newObj->first);
- newManagementObjects.erase(newObj++); // post inc iterator safe!
- } else if (oldObj->second->isDeleted()) {
- // skip adding newObj, try again later once oldObj has been cleaned up by poll
- ++newObj;
- } else {
- // real bad - two objects exist with same OID. This is a bug in the application
- QPID_LOG(error, "Detected two Mgmt Objects using the same object id! oid=" << newObj->first
- << ", this is bad!");
- // what to do here? Can't erase an active obj - owner has a pointer to it.
- // for now I punt. Maybe the flood of log messages will get someone's attention :P
- ++newObj;
- }
- }
- }
-}
-
-void ManagementAgentImpl::addClassLocal(uint8_t classKind,
- PackageMap::iterator pIter,
- const string& className,
- uint8_t* md5Sum,
- ManagementObject::writeSchemaCall_t schemaCall)
-{
- SchemaClassKey key;
- ClassMap& cMap = pIter->second;
-
- key.name = className;
- memcpy(&key.hash, md5Sum, 16);
-
- ClassMap::iterator cIter = cMap.find(key);
- if (cIter != cMap.end())
- return;
-
- // No such class found, create a new class with local information.
- cMap.insert(pair<SchemaClassKey, SchemaClass>(key, SchemaClass(schemaCall, classKind)));
- schemaTimestamp = Duration(EPOCH, now());
- QPID_LOG(trace, "Updated schema timestamp, now=" << uint64_t(schemaTimestamp));
-}
-
-void ManagementAgentImpl::encodePackageIndication(Buffer& buf,
- PackageMap::iterator pIter)
-{
- buf.putShortString((*pIter).first);
-
- QPID_LOG(trace, "SENT PackageInd: package=" << (*pIter).first);
-}
-
-void ManagementAgentImpl::encodeClassIndication(Buffer& buf,
- PackageMap::iterator pIter,
- ClassMap::iterator cIter)
-{
- SchemaClassKey key = (*cIter).first;
-
- buf.putOctet((*cIter).second.kind);
- buf.putShortString((*pIter).first);
- buf.putShortString(key.name);
- buf.putBin128(key.hash);
-
- QPID_LOG(trace, "SENT ClassInd: package=" << (*pIter).first << " class=" << key.name);
-}
-
-struct MessageItem {
- string content;
- Variant::Map headers;
- string key;
- MessageItem(const Variant::Map& h, const string& k) : headers(h), key(k) {}
-};
-
-void ManagementAgentImpl::periodicProcessing()
-{
- string addr_key_base = "agent.ind.data.";
- list<ObjectId> deleteList;
- list<boost::shared_ptr<MessageItem> > message_list;
-
- sendHeartbeat();
-
- {
- sys::Mutex::ScopedLock lock(agentLock);
-
- if (!connected)
- return;
-
- moveNewObjectsLH(lock);
-
- //
- // Clear the been-here flag on all objects in the map.
- //
- for (ObjectMap::iterator iter = managementObjects.begin();
- iter != managementObjects.end();
- iter++) {
- ManagementObject* object = iter->second.get();
- object->setFlags(0);
- if (publishAllData) {
- object->setForcePublish(true);
- }
- }
-
- publishAllData = false;
-
- //
- // Process the entire object map.
- //
- uint32_t v2Objs = 0;
-
- for (ObjectMap::iterator baseIter = managementObjects.begin();
- baseIter != managementObjects.end();
- baseIter++) {
- ManagementObject* baseObject = baseIter->second.get();
-
- //
- // Skip until we find a base object requiring a sent message.
- //
- if (baseObject->getFlags() == 1 ||
- (!baseObject->getConfigChanged() &&
- !baseObject->getInstChanged() &&
- !baseObject->getForcePublish() &&
- !baseObject->isDeleted()))
- continue;
-
- std::string packageName = baseObject->getPackageName();
- std::string className = baseObject->getClassName();
-
- Variant::List list_;
- std::stringstream addr_key;
- Variant::Map headers;
-
- addr_key << addr_key_base;
- addr_key << keyifyNameStr(packageName)
- << "." << keyifyNameStr(className)
- << "." << vendorNameKey
- << "." << productNameKey
- << "." << instanceNameKey;
-
- headers["method"] = "indication";
- headers["qmf.opcode"] = "_data_indication";
- headers["qmf.content"] = "_data";
- headers["qmf.agent"] = name_address;
-
- for (ObjectMap::iterator iter = baseIter;
- iter != managementObjects.end();
- iter++) {
- ManagementObject* object = iter->second.get();
- bool send_stats, send_props;
- if (baseObject->isSameClass(*object) && object->getFlags() == 0) {
- object->setFlags(1);
- if (object->getConfigChanged() || object->getInstChanged())
- object->setUpdateTime();
-
- send_props = (object->getConfigChanged() || object->getForcePublish() || object->isDeleted());
- send_stats = (object->hasInst() && (object->getInstChanged() || object->getForcePublish()));
-
- if (send_stats || send_props) {
- Variant::Map map_;
- Variant::Map values;
- Variant::Map oid;
-
- object->getObjectId().mapEncode(oid);
- map_["_object_id"] = oid;
- map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(),
- object->getClassName(),
- object->getMd5Sum());
- object->writeTimestamps(map_);
- object->mapEncodeValues(values, send_props, send_stats);
- map_["_values"] = values;
- list_.push_back(map_);
-
- if (++v2Objs >= maxV2ReplyObjs) {
- v2Objs = 0;
- boost::shared_ptr<MessageItem> item(new MessageItem(headers, addr_key.str()));
- ListCodec::encode(list_, item->content);
- message_list.push_back(item);
- list_.clear();
- }
- }
-
- if (object->isDeleted())
- deleteList.push_back(iter->first);
- object->setForcePublish(false);
- }
- }
-
- if (!list_.empty()) {
- boost::shared_ptr<MessageItem> item(new MessageItem(headers, addr_key.str()));
- ListCodec::encode(list_, item->content);
- message_list.push_back(item);
- }
- }
-
- // Delete flagged objects
- for (list<ObjectId>::reverse_iterator iter = deleteList.rbegin();
- iter != deleteList.rend();
- iter++)
- managementObjects.erase(*iter);
- }
-
- while (!message_list.empty()) {
- boost::shared_ptr<MessageItem> item(message_list.front());
- message_list.pop_front();
- connThreadBody.sendBuffer(item->content, "", item->headers, topicExchange, item->key, "amqp/list");
- QPID_LOG(trace, "SENT DataIndication");
- }
-}
-
-
-void ManagementAgentImpl::getHeartbeatContent(qpid::types::Variant::Map& map)
-{
- map["_values"] = attrMap;
- map["_values"].asMap()["_timestamp"] = uint64_t(Duration(EPOCH, now()));
- map["_values"].asMap()["_heartbeat_interval"] = interval;
- map["_values"].asMap()["_epoch"] = bootSequence;
- map["_values"].asMap()["_schema_updated"] = uint64_t(schemaTimestamp);
-}
-
-void ManagementAgentImpl::ConnectionThread::run()
-{
- static const int delayMin(1);
- static const int delayMax(128);
- static const int delayFactor(2);
- int delay(delayMin);
- string dest("qmfagent");
- ConnectionThread::shared_ptr tmp;
-
- sessionId.generate();
- queueName << "qmfagent-" << sessionId;
-
- while (true) {
- try {
- if (agent.initialized) {
- QPID_LOG(debug, "QMF Agent attempting to connect to the broker...");
- connection.open(agent.connectionSettings);
- session = connection.newSession(queueName.str());
- subscriptions.reset(new client::SubscriptionManager(session));
-
- session.queueDeclare(arg::queue=queueName.str(), arg::autoDelete=true,
- arg::exclusive=true);
- session.exchangeBind(arg::exchange="amq.direct", arg::queue=queueName.str(),
- arg::bindingKey=queueName.str());
- session.exchangeBind(arg::exchange=agent.directExchange, arg::queue=queueName.str(),
- arg::bindingKey=agent.name_address);
- session.exchangeBind(arg::exchange=agent.topicExchange, arg::queue=queueName.str(),
- arg::bindingKey="console.#");
-
- subscriptions->subscribe(agent, queueName.str(), dest);
- QPID_LOG(info, "Connection established with broker");
- {
- sys::Mutex::ScopedLock _lock(connLock);
- if (shutdown)
- return;
- operational = true;
- agent.connected = true;
- agent.startProtocol();
- try {
- sys::Mutex::ScopedUnlock _unlock(connLock);
- subscriptions->run();
- } catch (exception) {}
-
- QPID_LOG(warning, "Connection to the broker has been lost");
-
- operational = false;
- agent.connected = false;
- tmp = subscriptions;
- subscriptions.reset();
- }
- tmp.reset(); // frees the subscription outside the lock
- delay = delayMin;
- connection.close();
- }
- } catch (exception &e) {
- if (delay < delayMax)
- delay *= delayFactor;
- QPID_LOG(debug, "Connection failed: exception=" << e.what());
- }
-
- {
- // sleep for "delay" seconds, but peridically check if the
- // agent is shutting down so we don't hang for up to delayMax
- // seconds during agent shutdown
- sys::Mutex::ScopedLock _lock(connLock);
- if (shutdown)
- return;
- sleeping = true;
- int totalSleep = 0;
- do {
- sys::Mutex::ScopedUnlock _unlock(connLock);
- qpid::sys::sleep(delayMin);
- totalSleep += delayMin;
- } while (totalSleep < delay && !shutdown);
- sleeping = false;
- if (shutdown)
- return;
- }
- }
-}
-
-ManagementAgentImpl::ConnectionThread::~ConnectionThread()
-{
-}
-
-void ManagementAgentImpl::ConnectionThread::sendBuffer(Buffer& buf,
- uint32_t length,
- const string& exchange,
- const string& routingKey)
-{
- Message msg;
- string data;
-
- buf.getRawData(data, length);
- msg.setData(data);
- sendMessage(msg, exchange, routingKey);
-}
-
-
-
-void ManagementAgentImpl::ConnectionThread::sendBuffer(const string& data,
- const string& cid,
- const Variant::Map headers,
- const string& exchange,
- const string& routingKey,
- const string& contentType,
- uint64_t ttl_msec)
-{
- Message msg;
- Variant::Map::const_iterator i;
-
- if (!cid.empty())
- msg.getMessageProperties().setCorrelationId(cid);
-
- if (!contentType.empty())
- msg.getMessageProperties().setContentType(contentType);
-
- if (ttl_msec)
- msg.getDeliveryProperties().setTtl(ttl_msec);
-
- for (i = headers.begin(); i != headers.end(); ++i) {
- msg.getHeaders().setString(i->first, i->second.asString());
- }
-
- msg.setData(data);
- sendMessage(msg, exchange, routingKey);
-}
-
-
-
-
-
-void ManagementAgentImpl::ConnectionThread::sendMessage(Message msg,
- const string& exchange,
- const string& routingKey)
-{
- ConnectionThread::shared_ptr s;
- {
- sys::Mutex::ScopedLock _lock(connLock);
- if (!operational)
- return;
- s = subscriptions;
- }
-
- msg.getDeliveryProperties().setRoutingKey(routingKey);
- msg.getMessageProperties().setReplyTo(ReplyTo("amq.direct", queueName.str()));
- msg.getMessageProperties().getApplicationHeaders().setString("qmf.agent", agent.name_address);
- msg.getMessageProperties().setAppId("qmf2");
- try {
- session.messageTransfer(arg::content=msg, arg::destination=exchange);
- } catch(exception& e) {
- QPID_LOG(error, "Exception caught in sendMessage: " << e.what());
- // Bounce the connection
- if (s)
- s->stop();
- }
-}
-
-
-
-void ManagementAgentImpl::ConnectionThread::bindToBank(uint32_t brokerBank, uint32_t agentBank)
-{
- stringstream key;
- key << "agent." << brokerBank << "." << agentBank;
- session.exchangeBind(arg::exchange="qpid.management", arg::queue=queueName.str(),
- arg::bindingKey=key.str());
-}
-
-void ManagementAgentImpl::ConnectionThread::close()
-{
- ConnectionThread::shared_ptr s;
- {
- sys::Mutex::ScopedLock _lock(connLock);
- shutdown = true;
- s = subscriptions;
- }
- if (s)
- s->stop();
-}
-
-bool ManagementAgentImpl::ConnectionThread::isSleeping() const
-{
- sys::Mutex::ScopedLock _lock(connLock);
- return sleeping;
-}
-
-
-void ManagementAgentImpl::PublishThread::run()
-{
- uint16_t totalSleep;
- uint16_t sleepTime;
-
- while (!shutdown) {
- agent.periodicProcessing();
- totalSleep = 0;
-
- //
- // Calculate a sleep time that is no greater than 5 seconds and
- // no less than 1 second.
- //
- sleepTime = agent.getInterval();
- if (sleepTime > 5)
- sleepTime = 5;
- else if (sleepTime == 0)
- sleepTime = 1;
-
- while (totalSleep < agent.getInterval() && !shutdown) {
- qpid::sys::sleep(sleepTime);
- totalSleep += sleepTime;
- }
- }
-}
-
-}}
-
diff --git a/qpid/cpp/src/qpid/agent/ManagementAgentImpl.h b/qpid/cpp/src/qpid/agent/ManagementAgentImpl.h
deleted file mode 100644
index 4c97bc89da..0000000000
--- a/qpid/cpp/src/qpid/agent/ManagementAgentImpl.h
+++ /dev/null
@@ -1,294 +0,0 @@
-#ifndef _qpid_agent_ManagementAgentImpl_
-#define _qpid_agent_ManagementAgentImpl_
-
-//
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-//
-
-#include "qpid/agent/ManagementAgent.h"
-#include "qpid/client/Connection.h"
-#include "qpid/client/ConnectionSettings.h"
-#include "qpid/client/SubscriptionManager.h"
-#include "qpid/client/Session.h"
-#include "qpid/client/AsyncSession.h"
-#include "qpid/client/Message.h"
-#include "qpid/client/MessageListener.h"
-#include "qpid/sys/Thread.h"
-#include "qpid/sys/Runnable.h"
-#include "qpid/sys/Mutex.h"
-#include "qpid/sys/PipeHandle.h"
-#include "qpid/sys/Time.h"
-#include "qpid/framing/Uuid.h"
-#include <iostream>
-#include <sstream>
-#include <deque>
-
-namespace qpid {
-namespace management {
-
-class ManagementAgentImpl : public ManagementAgent, public client::MessageListener
-{
- public:
-
- ManagementAgentImpl();
- virtual ~ManagementAgentImpl();
-
- //
- // Methods from ManagementAgent
- //
- int getMaxThreads() { return 1; }
- void setName(const std::string& vendor,
- const std::string& product,
- const std::string& instance="");
- void getName(std::string& vendor, std::string& product, std::string& instance);
- const std::string& getAddress();
- void init(const std::string& brokerHost = "localhost",
- uint16_t brokerPort = 5672,
- uint16_t intervalSeconds = 10,
- bool useExternalThread = false,
- const std::string& storeFile = "",
- const std::string& uid = "",
- const std::string& pwd = "",
- const std::string& mech = "PLAIN",
- const std::string& proto = "tcp");
- void init(const management::ConnectionSettings& settings,
- uint16_t intervalSeconds = 10,
- bool useExternalThread = false,
- const std::string& storeFile = "");
- bool isConnected() { return connected; }
- std::string& getLastFailure() { return lastFailure; }
- void registerClass(const std::string& packageName,
- const std::string& className,
- uint8_t* md5Sum,
- management::ManagementObject::writeSchemaCall_t schemaCall);
- void registerEvent(const std::string& packageName,
- const std::string& eventName,
- uint8_t* md5Sum,
- management::ManagementObject::writeSchemaCall_t schemaCall);
- ObjectId addObject(management::ManagementObject* objectPtr, uint64_t persistId = 0);
- ObjectId addObject(management::ManagementObject* objectPtr, const std::string& key,
- bool persistent);
- void raiseEvent(const management::ManagementEvent& event, severity_t severity = SEV_DEFAULT);
- uint32_t pollCallbacks(uint32_t callLimit = 0);
- int getSignalFd();
- void setSignalCallback(cb_t callback, void* context);
- void setSignalCallback(Notifyable& n);
-
- uint16_t getInterval() { return interval; }
- void periodicProcessing();
-
- uint16_t getBootSequence(void) { return bootSequence; }
- void setBootSequence(uint16_t b) { bootSequence = b; }
-
- private:
-
- struct SchemaClassKey {
- std::string name;
- uint8_t hash[16];
- };
-
- struct SchemaClassKeyComp {
- bool operator() (const SchemaClassKey& lhs, const SchemaClassKey& rhs) const
- {
- if (lhs.name != rhs.name)
- return lhs.name < rhs.name;
- else
- for (int i = 0; i < 16; i++)
- if (lhs.hash[i] != rhs.hash[i])
- return lhs.hash[i] < rhs.hash[i];
- return false;
- }
- };
-
- struct SchemaClass {
- management::ManagementObject::writeSchemaCall_t writeSchemaCall;
- uint8_t kind;
-
- SchemaClass(const management::ManagementObject::writeSchemaCall_t call,
- const uint8_t _kind) : writeSchemaCall(call), kind(_kind) {}
- };
-
- struct QueuedMethod {
- QueuedMethod(const std::string& _cid, const std::string& _rte, const std::string& _rtk, const std::string& _body, const std::string& _uid) :
- cid(_cid), replyToExchange(_rte), replyToKey(_rtk), body(_body), userId(_uid) {}
-
- std::string cid;
- std::string replyToExchange;
- std::string replyToKey;
- std::string body;
- std::string userId;
- };
-
- typedef std::deque<QueuedMethod*> MethodQueue;
- typedef std::map<SchemaClassKey, SchemaClass, SchemaClassKeyComp> ClassMap;
- typedef std::map<std::string, ClassMap> PackageMap;
-
- PackageMap packages;
- AgentAttachment attachment;
-
- typedef std::map<ObjectId, boost::shared_ptr<ManagementObject> > ObjectMap;
-
- ObjectMap managementObjects;
- ObjectMap newManagementObjects;
- MethodQueue methodQueue;
-
- void received (client::Message& msg);
-
- qpid::types::Variant::Map attrMap;
- std::string name_address;
- std::string vendorNameKey; // vendor name with "." --> "_"
- std::string productNameKey; // product name with "." --> "_"
- std::string instanceNameKey; // agent instance with "." --> "_"
- uint16_t interval;
- bool extThread;
- sys::PipeHandle* pipeHandle;
- uint64_t nextObjectId;
- cb_t notifyCallback;
- void* notifyContext;
- Notifyable* notifyable;
- bool inCallback;
- std::string storeFile;
- sys::Mutex agentLock;
- sys::Mutex addLock;
- framing::Uuid systemId;
- client::ConnectionSettings connectionSettings;
- bool initialized;
- bool connected;
- bool useMapMsg;
- std::string lastFailure;
- std::string topicExchange;
- std::string directExchange;
- qpid::sys::Duration schemaTimestamp;
-
- bool publishAllData;
- uint32_t requestedBrokerBank;
- uint32_t requestedAgentBank;
- uint32_t assignedBrokerBank;
- uint32_t assignedAgentBank;
- uint16_t bootSequence;
-
- // Maximum # of objects allowed in a single V2 response
- // message.
- uint32_t maxV2ReplyObjs;
-
- static const uint8_t DEBUG_OFF = 0;
- static const uint8_t DEBUG_CONN = 1;
- static const uint8_t DEBUG_PROTO = 2;
- static const uint8_t DEBUG_PUBLISH = 3;
-
-# define MA_BUFFER_SIZE 65536
- char outputBuffer[MA_BUFFER_SIZE];
- char eventBuffer[MA_BUFFER_SIZE];
-
- friend class ConnectionThread;
- class ConnectionThread : public sys::Runnable
- {
- typedef boost::shared_ptr<client::SubscriptionManager> shared_ptr;
-
- bool operational;
- ManagementAgentImpl& agent;
- framing::Uuid sessionId;
- client::Connection connection;
- client::Session session;
- ConnectionThread::shared_ptr subscriptions;
- std::stringstream queueName;
- mutable sys::Mutex connLock;
- bool shutdown;
- bool sleeping;
- void run();
- public:
- ConnectionThread(ManagementAgentImpl& _agent) :
- operational(false), agent(_agent),
- shutdown(false), sleeping(false) {}
- ~ConnectionThread();
- void sendBuffer(qpid::framing::Buffer& buf,
- uint32_t length,
- const std::string& exchange,
- const std::string& routingKey);
- void sendBuffer(const std::string& data,
- const std::string& cid,
- const qpid::types::Variant::Map headers,
- const std::string& exchange,
- const std::string& routingKey,
- const std::string& contentType="amqp/map",
- uint64_t ttl_msec=0);
- void sendMessage(qpid::client::Message msg,
- const std::string& exchange,
- const std::string& routingKey);
- void bindToBank(uint32_t brokerBank, uint32_t agentBank);
- void close();
- bool isSleeping() const;
- };
-
- class PublishThread : public sys::Runnable
- {
- ManagementAgentImpl& agent;
- void run();
- bool shutdown;
- public:
- PublishThread(ManagementAgentImpl& _agent) :
- agent(_agent), shutdown(false) {}
- void close() { shutdown = true; }
- };
-
- ConnectionThread connThreadBody;
- sys::Thread connThread;
- PublishThread pubThreadBody;
- sys::Thread pubThread;
-
- static const std::string storeMagicNumber;
-
- void startProtocol();
- void storeData(bool requested=false);
- void retrieveData(std::string& vendor, std::string& product, std::string& inst);
- PackageMap::iterator findOrAddPackage(const std::string& name);
- void moveNewObjectsLH(const sys::Mutex::ScopedLock& agentLock);
- void addClassLocal (uint8_t classKind,
- PackageMap::iterator pIter,
- const std::string& className,
- uint8_t* md5Sum,
- management::ManagementObject::writeSchemaCall_t schemaCall);
- void encodePackageIndication (framing::Buffer& buf,
- PackageMap::iterator pIter);
- void encodeClassIndication (framing::Buffer& buf,
- PackageMap::iterator pIter,
- ClassMap::iterator cIter);
- void encodeHeader (framing::Buffer& buf, uint8_t opcode, uint32_t seq = 0);
- qpid::types::Variant::Map mapEncodeSchemaId(const std::string& pname,
- const std::string& cname,
- const uint8_t *md5Sum,
- uint8_t type=ManagementItem::CLASS_KIND_TABLE);
- bool checkHeader (framing::Buffer& buf, uint8_t *opcode, uint32_t *seq);
- void sendHeartbeat();
- void sendException(const std::string& replyToExchange, const std::string& replyToKey, const std::string& cid,
- const std::string& text, uint32_t code=1);
- void handlePackageRequest (qpid::framing::Buffer& inBuffer);
- void handleClassQuery (qpid::framing::Buffer& inBuffer);
- void handleSchemaRequest (qpid::framing::Buffer& inBuffer, uint32_t sequence, const std::string& rte, const std::string& rtk);
- void invokeMethodRequest (const std::string& body, const std::string& cid, const std::string& rte, const std::string& rtk, const std::string& userId);
-
- void handleGetQuery (const std::string& body, const std::string& cid, const std::string& rte, const std::string& rtk);
- void handleLocateRequest (const std::string& body, const std::string& sequence, const std::string& rte, const std::string& rtk);
- void handleMethodRequest (const std::string& body, const std::string& sequence, const std::string& rte, const std::string& rtk, const std::string& userId);
- void handleConsoleAddedIndication();
- void getHeartbeatContent (qpid::types::Variant::Map& map);
-};
-
-}}
-
-#endif /*!_qpid_agent_ManagementAgentImpl_*/
diff --git a/qpid/cpp/src/qpid/amqp/DataBuilder.cpp b/qpid/cpp/src/qpid/amqp/DataBuilder.cpp
new file mode 100644
index 0000000000..91c9393457
--- /dev/null
+++ b/qpid/cpp/src/qpid/amqp/DataBuilder.cpp
@@ -0,0 +1,194 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "DataBuilder.h"
+#include "CharSequence.h"
+#include "qpid/log/Statement.h"
+#include "qpid/types/encodings.h"
+
+namespace qpid {
+namespace amqp {
+
+void DataBuilder::onNull(const Descriptor*)
+{
+ handle(qpid::types::Variant());
+}
+void DataBuilder::onBoolean(bool v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onUByte(uint8_t v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onUShort(uint16_t v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onUInt(uint32_t v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onULong(uint64_t v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onByte(int8_t v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onShort(int16_t v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onInt(int32_t v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onLong(int64_t v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onFloat(float v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onDouble(double v, const Descriptor*)
+{
+ handle(v);
+}
+void DataBuilder::onUuid(const CharSequence& v, const Descriptor*)
+{
+ if (v.size == qpid::types::Uuid::SIZE) {
+ handle(qpid::types::Uuid(v.data));
+ }
+}
+void DataBuilder::onTimestamp(int64_t v, const Descriptor*)
+{
+ handle(v);
+}
+
+void DataBuilder::handle(const qpid::types::Variant& v)
+{
+ switch (nested.top()->getType()) {
+ case qpid::types::VAR_MAP:
+ nested.push(&nested.top()->asMap()[v.asString()]);
+ break;
+ case qpid::types::VAR_LIST:
+ nested.top()->asList().push_back(v);
+ break;
+ default:
+ *(nested.top()) = v;
+ nested.pop();
+ break;
+ }
+}
+
+void DataBuilder::onBinary(const CharSequence& v, const Descriptor*)
+{
+ onString(std::string(v.data, v.size), qpid::types::encodings::BINARY);
+}
+void DataBuilder::onString(const CharSequence& v, const Descriptor*)
+{
+ onString(std::string(v.data, v.size), qpid::types::encodings::UTF8);
+}
+void DataBuilder::onSymbol(const CharSequence& v, const Descriptor*)
+{
+ onString(std::string(v.data, v.size), qpid::types::encodings::ASCII);
+}
+
+void DataBuilder::onString(const std::string& value, const std::string& encoding)
+{
+ switch (nested.top()->getType()) {
+ case qpid::types::VAR_MAP:
+ nested.push(&nested.top()->asMap()[value]);
+ break;
+ case qpid::types::VAR_LIST:
+ nested.top()->asList().push_back(qpid::types::Variant(value));
+ nested.top()->asList().back().setEncoding(encoding);
+ break;
+ default:
+ qpid::types::Variant& v = *(nested.top());
+ v = value;
+ v.setEncoding(encoding);
+ nested.pop();
+ break;
+ }
+}
+
+bool DataBuilder::proceed()
+{
+ return !nested.empty();
+}
+
+bool DataBuilder::nest(const qpid::types::Variant& n)
+{
+ switch (nested.top()->getType()) {
+ case qpid::types::VAR_MAP:
+ QPID_LOG(error, QPID_MSG("Expecting map key; got " << n));
+ break;
+ case qpid::types::VAR_LIST:
+ nested.top()->asList().push_back(n);
+ nested.push(&nested.top()->asList().back());
+ break;
+ default:
+ qpid::types::Variant& value = *(nested.top());
+ value = n;
+ nested.pop();
+ nested.push(&value);
+ break;
+ }
+ return true;
+}
+
+bool DataBuilder::onStartList(uint32_t, const CharSequence&, const CharSequence&, const Descriptor*)
+{
+ return nest(qpid::types::Variant::List());
+}
+void DataBuilder::onEndList(uint32_t /*count*/, const Descriptor*)
+{
+ nested.pop();
+}
+bool DataBuilder::onStartMap(uint32_t /*count*/, const CharSequence&, const CharSequence&, const Descriptor*)
+{
+ return nest(qpid::types::Variant::Map());
+}
+void DataBuilder::onEndMap(uint32_t /*count*/, const Descriptor*)
+{
+ nested.pop();
+}
+bool DataBuilder::onStartArray(uint32_t count, const CharSequence&, const Constructor&, const Descriptor*)
+{
+ return onStartList(count, CharSequence::create(), CharSequence::create(), 0);
+}
+void DataBuilder::onEndArray(uint32_t count, const Descriptor*)
+{
+ onEndList(count, 0);
+}
+qpid::types::Variant& DataBuilder::getValue()
+{
+ return base;
+}
+DataBuilder::DataBuilder(qpid::types::Variant v) : base(v)
+{
+ nested.push(&base);
+}
+DataBuilder::~DataBuilder() {}
+}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/DataBuilder.h b/qpid/cpp/src/qpid/amqp/DataBuilder.h
new file mode 100644
index 0000000000..51ee3da5f8
--- /dev/null
+++ b/qpid/cpp/src/qpid/amqp/DataBuilder.h
@@ -0,0 +1,79 @@
+#ifndef QPID_AMQP_DATABUILDER_H
+#define QPID_AMQP_DATABUILDER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "Reader.h"
+#include "qpid/types/Variant.h"
+#include "qpid/CommonImportExport.h"
+#include <stack>
+
+namespace qpid {
+namespace amqp {
+
+/**
+ * Utility to build a Variant based structure (or value) from a data stream
+ */
+class DataBuilder : public Reader
+{
+ public:
+ QPID_COMMON_EXTERN DataBuilder(qpid::types::Variant);
+ QPID_COMMON_EXTERN virtual ~DataBuilder();
+ QPID_COMMON_EXTERN void onNull(const Descriptor*);
+ QPID_COMMON_EXTERN void onBoolean(bool, const Descriptor*);
+ QPID_COMMON_EXTERN void onUByte(uint8_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onUShort(uint16_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onUInt(uint32_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onULong(uint64_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onByte(int8_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onShort(int16_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onInt(int32_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onLong(int64_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onFloat(float, const Descriptor*);
+ QPID_COMMON_EXTERN void onDouble(double, const Descriptor*);
+ QPID_COMMON_EXTERN void onUuid(const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN void onTimestamp(int64_t, const Descriptor*);
+
+ QPID_COMMON_EXTERN void onBinary(const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN void onString(const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN void onSymbol(const CharSequence&, const Descriptor*);
+
+ QPID_COMMON_EXTERN bool onStartList(uint32_t /*count*/, const CharSequence&, const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN bool onStartMap(uint32_t /*count*/, const CharSequence&, const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN bool onStartArray(uint32_t /*count*/, const CharSequence&, const Constructor&, const Descriptor*);
+ QPID_COMMON_EXTERN void onEndList(uint32_t /*count*/, const Descriptor*);
+ QPID_COMMON_EXTERN void onEndMap(uint32_t /*count*/, const Descriptor*);
+ QPID_COMMON_EXTERN void onEndArray(uint32_t /*count*/, const Descriptor*);
+
+ QPID_COMMON_EXTERN bool proceed();
+ QPID_COMMON_EXTERN qpid::types::Variant& getValue();
+ private:
+ qpid::types::Variant base;
+ std::stack<qpid::types::Variant*> nested;
+ std::string key;
+
+ void handle(const qpid::types::Variant& v);
+ bool nest(const qpid::types::Variant& v);
+ void onString(const std::string&, const std::string&);
+};
+}} // namespace qpid::amqp
+
+#endif /*!QPID_AMQP_DATABUILDER_H*/
diff --git a/qpid/cpp/src/qpid/amqp/Decoder.cpp b/qpid/cpp/src/qpid/amqp/Decoder.cpp
index 1d5abc99c7..1058f83e38 100644
--- a/qpid/cpp/src/qpid/amqp/Decoder.cpp
+++ b/qpid/cpp/src/qpid/amqp/Decoder.cpp
@@ -22,6 +22,7 @@
#include "qpid/amqp/CharSequence.h"
#include "qpid/amqp/Constructor.h"
#include "qpid/amqp/Descriptor.h"
+#include "qpid/amqp/MapBuilder.h"
#include "qpid/amqp/Reader.h"
#include "qpid/amqp/typecodes.h"
#include "qpid/types/Uuid.h"
@@ -34,121 +35,13 @@ namespace amqp {
using namespace qpid::amqp::typecodes;
-Decoder::Decoder(const char* d, size_t s) : start(d), size(s), position(0) {}
+Decoder::Decoder(const char* d, size_t s) : start(d), size(s), position(0), current(0) {}
-namespace {
-class MapBuilder : public Reader
-{
- public:
- void onNull(const Descriptor*)
- {
- qpid::types::Variant v;
- handle(v, NULL_NAME);
- }
- void onBoolean(bool v, const Descriptor*)
- {
- handle(v, BOOLEAN_NAME);
- }
- void onUByte(uint8_t v, const Descriptor*)
- {
- handle(v, UBYTE_NAME);
- }
- void onUShort(uint16_t v, const Descriptor*)
- {
- handle(v, USHORT_NAME);
- }
- void onUInt(uint32_t v, const Descriptor*)
- {
- handle(v, UINT_NAME);
- }
- void onULong(uint64_t v, const Descriptor*)
- {
- handle(v, ULONG_NAME);
- }
- void onByte(int8_t v, const Descriptor*)
- {
- handle(v, BYTE_NAME);
- }
- void onShort(int16_t v, const Descriptor*)
- {
- handle(v, SHORT_NAME);
- }
- void onInt(int32_t v, const Descriptor*)
- {
- handle(v, INT_NAME);
- }
- void onLong(int64_t v, const Descriptor*)
- {
- handle(v, LONG_NAME);
- }
- void onFloat(float v, const Descriptor*)
- {
- handle(v, FLOAT_NAME);
- }
- void onDouble(double v, const Descriptor*)
- {
- handle(v, DOUBLE_NAME);
- }
- void onUuid(const CharSequence& v, const Descriptor*)
- {
- handle(v, UUID_NAME);
- }
- void onTimestamp(int64_t v, const Descriptor*)
- {
- handle(v, TIMESTAMP_NAME);
- }
- void onBinary(const CharSequence& v, const Descriptor*)
- {
- handle(v);
- }
- void onString(const CharSequence& v, const Descriptor*)
- {
- handle(v);
- }
- void onSymbol(const CharSequence& v, const Descriptor*)
- {
- handle(v);
- }
- MapBuilder(qpid::types::Variant::Map& m) : map(m), state(KEY) {}
- private:
- qpid::types::Variant::Map& map;
- enum {KEY, SKIP, VALUE} state;
- std::string key;
-
- template <typename T> void handle(T value, const std::string& name)
- {
- switch (state) {
- case KEY:
- QPID_LOG(warning, "Ignoring key of type " << name);
- state = SKIP;
- break;
- case VALUE:
- map[key] = value;
- case SKIP:
- state = KEY;
- break;
- }
- }
- void handle(const CharSequence& value)
- {
- switch (state) {
- case KEY:
- key = value.str();
- state = VALUE;
- break;
- case VALUE:
- map[key] = value.str();
- case SKIP:
- state = KEY;
- break;
- }
- }
-};
-}
void Decoder::readMap(qpid::types::Variant::Map& map)
{
- MapBuilder builder(map);
+ MapBuilder builder;
read(builder);
+ map = builder.getMap();
}
qpid::types::Variant::Map Decoder::readMap()
@@ -168,6 +61,7 @@ void Decoder::read(Reader& reader)
void Decoder::readOne(Reader& reader)
{
const char* temp = start + position;
+ current = position;
Constructor c = readConstructor();
if (c.isDescribed) reader.onDescriptor(c.descriptor, temp);
readValue(reader, c.code, c.isDescribed ? &c.descriptor : 0);
@@ -263,7 +157,7 @@ void Decoder::readValue(Reader& reader, uint8_t code, const Descriptor* descript
break;
case LIST0:
- reader.onStartList(0, CharSequence::create(), descriptor);
+ reader.onStartList(0, CharSequence::create(), getCurrent(0), descriptor);
reader.onEndList(0, descriptor);
break;
case LIST8:
@@ -333,7 +227,7 @@ void Decoder::readArray32(Reader& reader, const Descriptor* descriptor)
void Decoder::readList(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor)
{
- if (reader.onStartList(count, CharSequence::create(data(), size), descriptor)) {
+ if (reader.onStartList(count, CharSequence::create(data(), size), getCurrent(size), descriptor)) {
for (uint32_t i = 0; i < count; ++i) {
readOne(reader);
}
@@ -345,7 +239,7 @@ void Decoder::readList(Reader& reader, uint32_t size, uint32_t count, const Desc
}
void Decoder::readMap(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor)
{
- if (reader.onStartMap(count, CharSequence::create(data(), size), descriptor)) {
+ if (reader.onStartMap(count, CharSequence::create(data(), size), getCurrent(size), descriptor)) {
for (uint32_t i = 0; i < count; ++i) {
readOne(reader);
}
@@ -401,7 +295,7 @@ Descriptor Decoder::readDescriptor()
case ULONG_ZERO:
return Descriptor((uint64_t) 0);
default:
- throw qpid::Exception(QPID_MSG("Expected descriptor of type ulong or symbol; found " << code));
+ throw qpid::Exception(QPID_MSG("Expected descriptor of type ulong or symbol; found " << (int)code));
}
}
@@ -542,4 +436,10 @@ CharSequence Decoder::readRawUuid()
size_t Decoder::getPosition() const { return position; }
size_t Decoder::getSize() const { return size; }
void Decoder::resetSize(size_t s) { size = s; }
+
+CharSequence Decoder::getCurrent(size_t remaining) const
+{
+ return CharSequence::create(start + current, (position-current)+remaining);
+}
+
}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/Decoder.h b/qpid/cpp/src/qpid/amqp/Decoder.h
index 7ddfe0f17f..a78518be2b 100644
--- a/qpid/cpp/src/qpid/amqp/Decoder.h
+++ b/qpid/cpp/src/qpid/amqp/Decoder.h
@@ -77,6 +77,7 @@ class Decoder
const char* const start;
size_t size;
size_t position;
+ size_t current;
void readOne(Reader& reader);
void readValue(Reader& reader, uint8_t code, const Descriptor* descriptor);
@@ -92,7 +93,7 @@ class Decoder
CharSequence readRawUuid();
Constructor readConstructor();
const char* data();
-
+ CharSequence getCurrent(size_t remaining) const;
};
}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/Descriptor.cpp b/qpid/cpp/src/qpid/amqp/Descriptor.cpp
index 1d2df01e6e..384eba15b0 100644
--- a/qpid/cpp/src/qpid/amqp/Descriptor.cpp
+++ b/qpid/cpp/src/qpid/amqp/Descriptor.cpp
@@ -59,7 +59,7 @@ std::ostream& operator<<(std::ostream& os, const Descriptor& d)
else os << "null";
break;
case Descriptor::NUMERIC:
- os << d.value.code;
+ os << "0x" << std::hex << d.value.code;
break;
}
return os;
diff --git a/qpid/cpp/src/qpid/amqp/Descriptor.h b/qpid/cpp/src/qpid/amqp/Descriptor.h
index 789f4dcc63..b9a83628e7 100644
--- a/qpid/cpp/src/qpid/amqp/Descriptor.h
+++ b/qpid/cpp/src/qpid/amqp/Descriptor.h
@@ -42,13 +42,13 @@ struct Descriptor
SYMBOLIC
} type;
- Descriptor(uint64_t code);
- Descriptor(const CharSequence& symbol);
- bool match(const std::string&, uint64_t) const;
- size_t getSize() const;
+ QPID_COMMON_EXTERN Descriptor(uint64_t code);
+ QPID_COMMON_EXTERN Descriptor(const CharSequence& symbol);
+ QPID_COMMON_EXTERN bool match(const std::string&, uint64_t) const;
+ QPID_COMMON_EXTERN size_t getSize() const;
};
-std::ostream& operator<<(std::ostream& os, const Descriptor& d);
+QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& os, const Descriptor& d);
}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/Encoder.cpp b/qpid/cpp/src/qpid/amqp/Encoder.cpp
index 549b6d1e4e..627cc4aed6 100644
--- a/qpid/cpp/src/qpid/amqp/Encoder.cpp
+++ b/qpid/cpp/src/qpid/amqp/Encoder.cpp
@@ -23,11 +23,15 @@
#include "qpid/amqp/Descriptor.h"
#include "qpid/amqp/typecodes.h"
#include "qpid/types/Uuid.h"
+#include "qpid/types/Variant.h"
+#include "qpid/types/encodings.h"
#include "qpid/log/Statement.h"
#include "qpid/Exception.h"
#include <assert.h>
#include <string.h>
+using namespace qpid::types::encodings;
+
namespace qpid {
namespace amqp {
@@ -373,6 +377,87 @@ void Encoder::endArray32(size_t count, void* token)
end<uint32_t>(count, token, data+position);
}
+void Encoder::writeMap(const std::map<std::string, qpid::types::Variant>& value, const Descriptor* d, bool large)
+{
+ void* token = large ? startMap32(d) : startMap8(d);
+ for (qpid::types::Variant::Map::const_iterator i = value.begin(); i != value.end(); ++i) {
+ writeString(i->first);
+ writeValue(i->second);
+ }
+ if (large) endMap32(value.size()*2, token);
+ else endMap8(value.size()*2, token);
+}
+
+void Encoder::writeList(const std::list<qpid::types::Variant>& value, const Descriptor* d, bool large)
+{
+ void* token = large ? startList32(d) : startList8(d);
+ for (qpid::types::Variant::List::const_iterator i = value.begin(); i != value.end(); ++i) {
+ writeValue(*i);
+ }
+ if (large) endList32(value.size(), token);
+ else endList8(value.size(), token);
+}
+
+void Encoder::writeValue(const qpid::types::Variant& value, const Descriptor* d)
+{
+ switch (value.getType()) {
+ case qpid::types::VAR_VOID:
+ writeNull(d);
+ break;
+ case qpid::types::VAR_BOOL:
+ writeBoolean(value.asBool(), d);
+ break;
+ case qpid::types::VAR_UINT8:
+ writeUByte(value.asUint8(), d);
+ break;
+ case qpid::types::VAR_UINT16:
+ writeUShort(value.asUint16(), d);
+ break;
+ case qpid::types::VAR_UINT32:
+ writeUInt(value.asUint32(), d);
+ break;
+ case qpid::types::VAR_UINT64:
+ writeULong(value.asUint64(), d);
+ break;
+ case qpid::types::VAR_INT8:
+ writeByte(value.asInt8(), d);
+ break;
+ case qpid::types::VAR_INT16:
+ writeShort(value.asInt16(), d);
+ break;
+ case qpid::types::VAR_INT32:
+ writeInt(value.asInt32(), d);
+ break;
+ case qpid::types::VAR_INT64:
+ writeLong(value.asInt64(), d);
+ break;
+ case qpid::types::VAR_FLOAT:
+ writeFloat(value.asFloat(), d);
+ break;
+ case qpid::types::VAR_DOUBLE:
+ writeDouble(value.asDouble(), d);
+ break;
+ case qpid::types::VAR_STRING:
+ if (value.getEncoding() == UTF8) {
+ writeString(value.getString(), d);
+ } else if (value.getEncoding() == ASCII) {
+ writeSymbol(value.getString(), d);
+ } else {
+ writeBinary(value.getString(), d);
+ }
+ break;
+ case qpid::types::VAR_MAP:
+ writeMap(value.asMap(), d);
+ break;
+ case qpid::types::VAR_LIST:
+ writeList(value.asList(), d);
+ break;
+ case qpid::types::VAR_UUID:
+ writeUuid(value.asUuid(), d);
+ break;
+ }
+
+}
void Encoder::writeDescriptor(const Descriptor& d)
{
diff --git a/qpid/cpp/src/qpid/amqp/Encoder.h b/qpid/cpp/src/qpid/amqp/Encoder.h
index c661e4ac5d..e79ed76726 100644
--- a/qpid/cpp/src/qpid/amqp/Encoder.h
+++ b/qpid/cpp/src/qpid/amqp/Encoder.h
@@ -23,12 +23,15 @@
*/
#include "qpid/sys/IntegerTypes.h"
#include "qpid/amqp/Constructor.h"
+#include <list>
+#include <map>
#include <stddef.h>
#include <string>
namespace qpid {
namespace types {
class Uuid;
+class Variant;
}
namespace amqp {
struct CharSequence;
@@ -74,7 +77,7 @@ class Encoder
void writeString(const CharSequence&, const Descriptor* d=0);
void writeString(const std::string&, const Descriptor* d=0);
void writeBinary(const CharSequence&, const Descriptor* d=0);
- void writeBinary(const std::string&, const Descriptor* d=0);
+ QPID_COMMON_EXTERN void writeBinary(const std::string&, const Descriptor* d=0);
void* startList8(const Descriptor* d=0);
void* startList32(const Descriptor* d=0);
@@ -91,9 +94,13 @@ class Encoder
void endArray8(size_t count, void*);
void endArray32(size_t count, void*);
+ QPID_COMMON_EXTERN void writeValue(const qpid::types::Variant&, const Descriptor* d=0);
+ QPID_COMMON_EXTERN void writeMap(const std::map<std::string, qpid::types::Variant>& value, const Descriptor* d=0, bool large=true);
+ QPID_COMMON_EXTERN void writeList(const std::list<qpid::types::Variant>& value, const Descriptor* d=0, bool large=true);
+
void writeDescriptor(const Descriptor&);
- Encoder(char* data, size_t size);
- size_t getPosition();
+ QPID_COMMON_EXTERN Encoder(char* data, size_t size);
+ QPID_COMMON_EXTERN size_t getPosition();
void resetPosition(size_t p);
char* skip(size_t);
void writeBytes(const char* bytes, size_t count);
diff --git a/qpid/cpp/src/qpid/console/Agent.cpp b/qpid/cpp/src/qpid/amqp/ListBuilder.cpp
index fa76a13583..f2ca8e8805 100644
--- a/qpid/cpp/src/qpid/console/Agent.cpp
+++ b/qpid/cpp/src/qpid/amqp/ListBuilder.cpp
@@ -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,13 +18,16 @@
* under the License.
*
*/
+#include "ListBuilder.h"
+
+namespace qpid {
+namespace amqp {
-#include "qpid/console/Agent.h"
+ListBuilder::ListBuilder() : DataBuilder(qpid::types::Variant::List()) {}
-std::ostream& qpid::console::operator<<(std::ostream& o, const Agent& agent)
+qpid::types::Variant::List& ListBuilder::getList()
{
- o << "Agent at bank " << agent.getBrokerBank() << "." << agent.getAgentBank() <<
- " (" << agent.getLabel() << ")";
- return o;
+ return getValue().asList();
}
+}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/ListBuilder.h b/qpid/cpp/src/qpid/amqp/ListBuilder.h
new file mode 100644
index 0000000000..825f384f56
--- /dev/null
+++ b/qpid/cpp/src/qpid/amqp/ListBuilder.h
@@ -0,0 +1,41 @@
+#ifndef QPID_AMQP_LISTBUILDER_H
+#define QPID_AMQP_LISTBUILDER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "DataBuilder.h"
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+namespace amqp {
+
+/**
+ * Utility to build a Variant::List from a data stream
+ */
+class ListBuilder : public DataBuilder
+{
+ public:
+ QPID_COMMON_EXTERN ListBuilder();
+ QPID_COMMON_EXTERN qpid::types::Variant::List& getList();
+};
+}} // namespace qpid::amqp
+
+#endif /*!QPID_AMQP_LISTBUILDER_H*/
diff --git a/qpid/cpp/src/qpid/amqp/ListReader.h b/qpid/cpp/src/qpid/amqp/ListReader.h
index dce874bf2f..fafe2a1f9c 100644
--- a/qpid/cpp/src/qpid/amqp/ListReader.h
+++ b/qpid/cpp/src/qpid/amqp/ListReader.h
@@ -53,10 +53,10 @@ class ListReader : public Reader
virtual void onString(const CharSequence& v, const Descriptor* descriptor) { getReader().onString(v, descriptor); }
virtual void onSymbol(const CharSequence& v, const Descriptor* descriptor) { getReader().onSymbol(v, descriptor); }
- virtual bool onStartList(uint32_t count, const CharSequence& v, const Descriptor* descriptor)
+ virtual bool onStartList(uint32_t count, const CharSequence& elements, const CharSequence& all, const Descriptor* descriptor)
{
++level;
- getReader().onStartList(count, v, descriptor);
+ getReader().onStartList(count, elements, all, descriptor);
return false;
}
virtual void onEndList(uint32_t count, const Descriptor* descriptor)
@@ -64,10 +64,10 @@ class ListReader : public Reader
--level;
getReader().onEndList(count, descriptor);
}
- virtual bool onStartMap(uint32_t count, const CharSequence& v, const Descriptor* descriptor)
+ virtual bool onStartMap(uint32_t count, const CharSequence& elements, const CharSequence& all, const Descriptor* descriptor)
{
++level;
- getReader().onStartMap(count, v, descriptor);
+ getReader().onStartMap(count, elements, all, descriptor);
return false;
}
virtual void onEndMap(uint32_t count, const Descriptor* descriptor)
diff --git a/qpid/cpp/src/qpid/amqp/MapBuilder.cpp b/qpid/cpp/src/qpid/amqp/MapBuilder.cpp
index a554497791..ce8eea038e 100644
--- a/qpid/cpp/src/qpid/amqp/MapBuilder.cpp
+++ b/qpid/cpp/src/qpid/amqp/MapBuilder.cpp
@@ -19,112 +19,12 @@
*
*/
#include "MapBuilder.h"
-#include <assert.h>
namespace qpid {
namespace amqp {
-namespace {
-const std::string BINARY("binary");
-const std::string UTF8("utf8");
-const std::string ASCII("ascii");
-}
-
+MapBuilder::MapBuilder() : DataBuilder(qpid::types::Variant::Map()) {}
qpid::types::Variant::Map MapBuilder::getMap()
{
- return map;
-}
-const qpid::types::Variant::Map MapBuilder::getMap() const
-{
- return map;
-}
-
-void MapBuilder::onNullValue(const CharSequence& key, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = qpid::types::Variant();
-}
-void MapBuilder::onBooleanValue(const CharSequence& key, bool value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-void MapBuilder::onUByteValue(const CharSequence& key, uint8_t value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onUShortValue(const CharSequence& key, uint16_t value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onUIntValue(const CharSequence& key, uint32_t value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onULongValue(const CharSequence& key, uint64_t value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onByteValue(const CharSequence& key, int8_t value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onShortValue(const CharSequence& key, int16_t value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onIntValue(const CharSequence& key, int32_t value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onLongValue(const CharSequence& key, int64_t value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onFloatValue(const CharSequence& key, float value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onDoubleValue(const CharSequence& key, double value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onUuidValue(const CharSequence& key, const CharSequence& value, const Descriptor*)
-{
- assert(value.size == 16);
- map[std::string(key.data, key.size)] = qpid::types::Uuid(value.data);
-}
-
-void MapBuilder::onTimestampValue(const CharSequence& key, int64_t value, const Descriptor*)
-{
- map[std::string(key.data, key.size)] = value;
-}
-
-void MapBuilder::onBinaryValue(const CharSequence& key, const CharSequence& value, const Descriptor*)
-{
- qpid::types::Variant& v = map[std::string(key.data, key.size)];
- v = std::string(value.data, value.size);
- v.setEncoding(BINARY);
-}
-
-void MapBuilder::onStringValue(const CharSequence& key, const CharSequence& value, const Descriptor*)
-{
- qpid::types::Variant& v = map[std::string(key.data, key.size)];
- v = std::string(value.data, value.size);
- v.setEncoding(UTF8);
-}
-
-void MapBuilder::onSymbolValue(const CharSequence& key, const CharSequence& value, const Descriptor*)
-{
- qpid::types::Variant& v = map[std::string(key.data, key.size)];
- v = std::string(value.data, value.size);
- v.setEncoding(ASCII);
+ return getValue().asMap();
}
}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/MapBuilder.h b/qpid/cpp/src/qpid/amqp/MapBuilder.h
index 0e3b95f633..fd94ae04af 100644
--- a/qpid/cpp/src/qpid/amqp/MapBuilder.h
+++ b/qpid/cpp/src/qpid/amqp/MapBuilder.h
@@ -21,42 +21,20 @@
* under the License.
*
*/
-#include "MapReader.h"
-#include "qpid/types/Variant.h"
+#include "DataBuilder.h"
+#include "qpid/CommonImportExport.h"
namespace qpid {
namespace amqp {
/**
- * Utility to build a Variant::Map from a data stream (doesn't handle
- * nested maps or lists yet)
+ * Utility to build a Variant::Map from a data stream
*/
-class MapBuilder : public MapReader
+class MapBuilder : public DataBuilder
{
public:
- void onNullValue(const CharSequence& /*key*/, const Descriptor*);
- void onBooleanValue(const CharSequence& /*key*/, bool, const Descriptor*);
- void onUByteValue(const CharSequence& /*key*/, uint8_t, const Descriptor*);
- void onUShortValue(const CharSequence& /*key*/, uint16_t, const Descriptor*);
- void onUIntValue(const CharSequence& /*key*/, uint32_t, const Descriptor*);
- void onULongValue(const CharSequence& /*key*/, uint64_t, const Descriptor*);
- void onByteValue(const CharSequence& /*key*/, int8_t, const Descriptor*);
- void onShortValue(const CharSequence& /*key*/, int16_t, const Descriptor*);
- void onIntValue(const CharSequence& /*key*/, int32_t, const Descriptor*);
- void onLongValue(const CharSequence& /*key*/, int64_t, const Descriptor*);
- void onFloatValue(const CharSequence& /*key*/, float, const Descriptor*);
- void onDoubleValue(const CharSequence& /*key*/, double, const Descriptor*);
- void onUuidValue(const CharSequence& /*key*/, const CharSequence&, const Descriptor*);
- void onTimestampValue(const CharSequence& /*key*/, int64_t, const Descriptor*);
-
- void onBinaryValue(const CharSequence& /*key*/, const CharSequence&, const Descriptor*);
- void onStringValue(const CharSequence& /*key*/, const CharSequence&, const Descriptor*);
- void onSymbolValue(const CharSequence& /*key*/, const CharSequence&, const Descriptor*);
-
- qpid::types::Variant::Map getMap();
- const qpid::types::Variant::Map getMap() const;
- private:
- qpid::types::Variant::Map map;
+ QPID_COMMON_EXTERN MapBuilder();
+ QPID_COMMON_EXTERN qpid::types::Variant::Map getMap();
};
}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/MapReader.cpp b/qpid/cpp/src/qpid/amqp/MapReader.cpp
index aff885c5d3..b6c31849f0 100644
--- a/qpid/cpp/src/qpid/amqp/MapReader.cpp
+++ b/qpid/cpp/src/qpid/amqp/MapReader.cpp
@@ -219,7 +219,7 @@ void MapReader::onSymbol(const CharSequence& v, const Descriptor* d)
}
}
-bool MapReader::onStartList(uint32_t count, const CharSequence&, const Descriptor* d)
+bool MapReader::onStartList(uint32_t count, const CharSequence&, const CharSequence&, const Descriptor* d)
{
if (!level) throw qpid::Exception(QPID_MSG("Expecting map as top level datum"));
if (key) {
@@ -232,7 +232,7 @@ bool MapReader::onStartList(uint32_t count, const CharSequence&, const Descripto
return true;
}
-bool MapReader::onStartMap(uint32_t count, const CharSequence&, const Descriptor* d)
+bool MapReader::onStartMap(uint32_t count, const CharSequence&, const CharSequence&, const Descriptor* d)
{
if (level++) {
if (key) {
diff --git a/qpid/cpp/src/qpid/amqp/MapReader.h b/qpid/cpp/src/qpid/amqp/MapReader.h
index cb977e1326..875f919d63 100644
--- a/qpid/cpp/src/qpid/amqp/MapReader.h
+++ b/qpid/cpp/src/qpid/amqp/MapReader.h
@@ -68,36 +68,36 @@ class MapReader : public Reader
//this class implements the Reader interface, thus acting as a transformer into a more map oriented scheme
- void onNull(const Descriptor*);
- void onBoolean(bool, const Descriptor*);
- void onUByte(uint8_t, const Descriptor*);
- void onUShort(uint16_t, const Descriptor*);
- void onUInt(uint32_t, const Descriptor*);
- void onULong(uint64_t, const Descriptor*);
- void onByte(int8_t, const Descriptor*);
- void onShort(int16_t, const Descriptor*);
- void onInt(int32_t, const Descriptor*);
- void onLong(int64_t, const Descriptor*);
- void onFloat(float, const Descriptor*);
- void onDouble(double, const Descriptor*);
- void onUuid(const CharSequence&, const Descriptor*);
- void onTimestamp(int64_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onNull(const Descriptor*);
+ QPID_COMMON_EXTERN void onBoolean(bool, const Descriptor*);
+ QPID_COMMON_EXTERN void onUByte(uint8_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onUShort(uint16_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onUInt(uint32_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onULong(uint64_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onByte(int8_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onShort(int16_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onInt(int32_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onLong(int64_t, const Descriptor*);
+ QPID_COMMON_EXTERN void onFloat(float, const Descriptor*);
+ QPID_COMMON_EXTERN void onDouble(double, const Descriptor*);
+ QPID_COMMON_EXTERN void onUuid(const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN void onTimestamp(int64_t, const Descriptor*);
- void onBinary(const CharSequence&, const Descriptor*);
- void onString(const CharSequence&, const Descriptor*);
- void onSymbol(const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN void onBinary(const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN void onString(const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN void onSymbol(const CharSequence&, const Descriptor*);
- bool onStartList(uint32_t /*count*/, const CharSequence&, const Descriptor*);
- bool onStartMap(uint32_t /*count*/, const CharSequence&, const Descriptor*);
- bool onStartArray(uint32_t /*count*/, const CharSequence&, const Constructor&, const Descriptor*);
- void onEndList(uint32_t /*count*/, const Descriptor*);
- void onEndMap(uint32_t /*count*/, const Descriptor*);
- void onEndArray(uint32_t /*count*/, const Descriptor*);
+ QPID_COMMON_EXTERN bool onStartList(uint32_t /*count*/, const CharSequence&, const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN bool onStartMap(uint32_t /*count*/, const CharSequence&, const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN bool onStartArray(uint32_t /*count*/, const CharSequence&, const Constructor&, const Descriptor*);
+ QPID_COMMON_EXTERN void onEndList(uint32_t /*count*/, const Descriptor*);
+ QPID_COMMON_EXTERN void onEndMap(uint32_t /*count*/, const Descriptor*);
+ QPID_COMMON_EXTERN void onEndArray(uint32_t /*count*/, const Descriptor*);
- MapReader();
- static const int SYMBOL_KEY;
- static const int STRING_KEY;
- void setAllowedKeyType(int);
+ QPID_COMMON_EXTERN MapReader();
+ QPID_COMMON_EXTERN static const int SYMBOL_KEY;
+ QPID_COMMON_EXTERN static const int STRING_KEY;
+ QPID_COMMON_EXTERN void setAllowedKeyType(int);
private:
CharSequence key;
size_t level;
diff --git a/qpid/cpp/src/qpid/amqp/MessageEncoder.cpp b/qpid/cpp/src/qpid/amqp/MessageEncoder.cpp
index 3b493d1de7..beaea2befd 100644
--- a/qpid/cpp/src/qpid/amqp/MessageEncoder.cpp
+++ b/qpid/cpp/src/qpid/amqp/MessageEncoder.cpp
@@ -156,68 +156,6 @@ void MessageEncoder::writeApplicationProperties(const qpid::types::Variant::Map&
writeMap(properties, &qpid::amqp::message::APPLICATION_PROPERTIES, large);
}
-void MessageEncoder::writeMap(const qpid::types::Variant::Map& properties, const Descriptor* d, bool large)
-{
- void* token = large ? startMap32(d) : startMap8(d);
- for (qpid::types::Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) {
- writeString(i->first);
- switch (i->second.getType()) {
- case qpid::types::VAR_MAP:
- case qpid::types::VAR_LIST:
- //not allowed (TODO: revise, only strictly true for application-properties) whereas this is now a more general method)
- QPID_LOG(warning, "Ignoring nested map/list; not allowed in application-properties for AMQP 1.0");
- case qpid::types::VAR_VOID:
- writeNull();
- break;
- case qpid::types::VAR_BOOL:
- writeBoolean(i->second);
- break;
- case qpid::types::VAR_UINT8:
- writeUByte(i->second);
- break;
- case qpid::types::VAR_UINT16:
- writeUShort(i->second);
- break;
- case qpid::types::VAR_UINT32:
- writeUInt(i->second);
- break;
- case qpid::types::VAR_UINT64:
- writeULong(i->second);
- break;
- case qpid::types::VAR_INT8:
- writeByte(i->second);
- break;
- case qpid::types::VAR_INT16:
- writeShort(i->second);
- break;
- case qpid::types::VAR_INT32:
- writeInt(i->second);
- break;
- case qpid::types::VAR_INT64:
- writeULong(i->second);
- break;
- case qpid::types::VAR_FLOAT:
- writeFloat(i->second);
- break;
- case qpid::types::VAR_DOUBLE:
- writeDouble(i->second);
- break;
- case qpid::types::VAR_STRING:
- if (i->second.getEncoding() == BINARY) {
- writeBinary(i->second);
- } else {
- writeString(i->second);
- }
- break;
- case qpid::types::VAR_UUID:
- writeUuid(i->second);
- break;
- }
- }
- if (large) endMap32(properties.size()*2, token);
- else endMap8(properties.size()*2, token);
-}
-
size_t MessageEncoder::getEncodedSize(const Header& h, const Properties& p, const qpid::types::Variant::Map& ap, const std::string& d)
{
return getEncodedSize(h) + getEncodedSize(p, ap, d);
@@ -288,46 +226,56 @@ size_t MessageEncoder::getEncodedSizeForElements(const qpid::types::Variant::Map
{
size_t total = 0;
for (qpid::types::Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) {
- total += 1/*code*/ + encodedSize(i->first);
-
- switch (i->second.getType()) {
- case qpid::types::VAR_MAP:
- case qpid::types::VAR_LIST:
- case qpid::types::VAR_VOID:
- case qpid::types::VAR_BOOL:
- total += 1;
- break;
-
- case qpid::types::VAR_UINT8:
- case qpid::types::VAR_INT8:
- total += 2;
- break;
-
- case qpid::types::VAR_UINT16:
- case qpid::types::VAR_INT16:
- total += 3;
- break;
-
- case qpid::types::VAR_UINT32:
- case qpid::types::VAR_INT32:
- case qpid::types::VAR_FLOAT:
- total += 5;
- break;
-
- case qpid::types::VAR_UINT64:
- case qpid::types::VAR_INT64:
- case qpid::types::VAR_DOUBLE:
- total += 9;
- break;
-
- case qpid::types::VAR_UUID:
- total += 17;
- break;
-
- case qpid::types::VAR_STRING:
- total += 1/*code*/ + encodedSize(i->second);
- break;
- }
+ total += 1/*code*/ + encodedSize(i->first) + getEncodedSizeForValue(i->second);
+ }
+ return total;
+}
+
+size_t MessageEncoder::getEncodedSizeForValue(const qpid::types::Variant& value)
+{
+ size_t total = 0;
+ switch (value.getType()) {
+ case qpid::types::VAR_MAP:
+ total += getEncodedSize(value.asMap(), true);
+ break;
+ case qpid::types::VAR_LIST:
+ total += getEncodedSize(value.asList(), true);
+ break;
+
+ case qpid::types::VAR_VOID:
+ case qpid::types::VAR_BOOL:
+ total += 1;
+ break;
+
+ case qpid::types::VAR_UINT8:
+ case qpid::types::VAR_INT8:
+ total += 2;
+ break;
+
+ case qpid::types::VAR_UINT16:
+ case qpid::types::VAR_INT16:
+ total += 3;
+ break;
+
+ case qpid::types::VAR_UINT32:
+ case qpid::types::VAR_INT32:
+ case qpid::types::VAR_FLOAT:
+ total += 5;
+ break;
+
+ case qpid::types::VAR_UINT64:
+ case qpid::types::VAR_INT64:
+ case qpid::types::VAR_DOUBLE:
+ total += 9;
+ break;
+
+ case qpid::types::VAR_UUID:
+ total += 17;
+ break;
+
+ case qpid::types::VAR_STRING:
+ total += 1/*code*/ + encodedSize(value.getString());
+ break;
}
return total;
}
@@ -345,4 +293,20 @@ size_t MessageEncoder::getEncodedSize(const qpid::types::Variant::Map& map, bool
return total;
}
+
+size_t MessageEncoder::getEncodedSize(const qpid::types::Variant::List& list, bool alwaysUseLargeList)
+{
+ size_t total(0);
+ for (qpid::types::Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) {
+ total += getEncodedSizeForValue(*i);
+ }
+
+ //its not just the count that determines whether we can use a small list, but the aggregate size:
+ if (alwaysUseLargeList || list.size()*2 > 255 || total > 255) total += 4/*size*/ + 4/*count*/;
+ else total += 1/*size*/ + 1/*count*/;
+
+ total += 1 /*code for list itself*/;
+
+ return total;
+}
}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/MessageEncoder.h b/qpid/cpp/src/qpid/amqp/MessageEncoder.h
index 1de3d47bb2..05e1714004 100644
--- a/qpid/cpp/src/qpid/amqp/MessageEncoder.h
+++ b/qpid/cpp/src/qpid/amqp/MessageEncoder.h
@@ -39,7 +39,7 @@ class MessageEncoder : public Encoder
virtual ~Header() {}
virtual bool isDurable() const = 0;
virtual uint8_t getPriority() const = 0;
- virtual bool hasTtl() const = 0;
+ QPID_COMMON_EXTERN virtual bool hasTtl() const = 0;
virtual uint32_t getTtl() const = 0;
virtual bool isFirstAcquirer() const = 0;
virtual uint32_t getDeliveryCount() const = 0;
@@ -84,29 +84,33 @@ class MessageEncoder : public Encoder
virtual void handle(MapHandler&) const = 0;
};
- MessageEncoder(char* d, size_t s, bool o=false) : Encoder(d, s), optimise(o) {}
- void writeHeader(const Header&);
- void writeProperties(const Properties&);
- void writeApplicationProperties(const ApplicationProperties&);
- void writeApplicationProperties(const qpid::types::Variant::Map& properties);
- void writeApplicationProperties(const qpid::types::Variant::Map& properties, bool useLargeMap);
+ QPID_COMMON_EXTERN MessageEncoder(char* d, size_t s) : Encoder(d, s), optimise(true) {}
+ QPID_COMMON_EXTERN void writeHeader(const Header&);
+ QPID_COMMON_EXTERN void writeProperties(const Properties&);
+ QPID_COMMON_EXTERN void writeApplicationProperties(const ApplicationProperties&);
+ QPID_COMMON_EXTERN void writeApplicationProperties(const qpid::types::Variant::Map& properties);
+ QPID_COMMON_EXTERN void writeApplicationProperties(const qpid::types::Variant::Map& properties, bool useLargeMap);
- void writeMap(const qpid::types::Variant::Map& map, const Descriptor*, bool useLargeMap);
+ QPID_COMMON_EXTERN static size_t getEncodedSize(const Header&);
+ QPID_COMMON_EXTERN static size_t getEncodedSize(const Properties&);
+ QPID_COMMON_EXTERN static size_t getEncodedSize(const ApplicationProperties&);
- static size_t getEncodedSize(const Header&);
- static size_t getEncodedSize(const Properties&);
- static size_t getEncodedSize(const ApplicationProperties&);
- static size_t getEncodedSize(const Header&, const Properties&, const ApplicationProperties&, const std::string&);
+ QPID_COMMON_EXTERN static size_t getEncodedSize(const qpid::types::Variant::List&, bool useLargeList);
+ QPID_COMMON_EXTERN static size_t getEncodedSize(const qpid::types::Variant::Map&, bool useLargeMap);
+
+ QPID_COMMON_EXTERN static size_t getEncodedSizeForValue(const qpid::types::Variant& value);
+ QPID_COMMON_EXTERN static size_t getEncodedSizeForContent(const std::string&);
+
+ //used in translating 0-10 content to 1.0, to determine buffer space needed
+ QPID_COMMON_EXTERN static size_t getEncodedSize(const Properties&, const qpid::types::Variant::Map&, const std::string&);
- static size_t getEncodedSize(const qpid::types::Variant::Map&, bool useLargeMap);
- static size_t getEncodedSize(const qpid::types::Variant::Map&);
- static size_t getEncodedSize(const Header&, const Properties&, const qpid::types::Variant::Map&, const std::string&);
- static size_t getEncodedSize(const Properties&, const qpid::types::Variant::Map&, const std::string&);
private:
bool optimise;
+ static size_t getEncodedSize(const Header&, const Properties&, const ApplicationProperties&, const std::string&);
+ static size_t getEncodedSize(const Header&, const Properties&, const qpid::types::Variant::Map&, const std::string&);
+
static size_t getEncodedSizeForElements(const qpid::types::Variant::Map&);
- static size_t getEncodedSizeForContent(const std::string&);
};
}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/MessageReader.cpp b/qpid/cpp/src/qpid/amqp/MessageReader.cpp
index 1550fa1977..70374f4cd6 100644
--- a/qpid/cpp/src/qpid/amqp/MessageReader.cpp
+++ b/qpid/cpp/src/qpid/amqp/MessageReader.cpp
@@ -21,6 +21,7 @@
#include "qpid/amqp/MessageReader.h"
#include "qpid/amqp/Descriptor.h"
#include "qpid/amqp/descriptors.h"
+#include "qpid/amqp/typecodes.h"
#include "qpid/types/Uuid.h"
#include "qpid/types/Variant.h"
#include "qpid/log/Statement.h"
@@ -55,40 +56,6 @@ const size_t REPLY_TO_GROUP_ID(12);
}
-/*
-Reader& MessageReader::HeaderReader::getReader(size_t index)
-{
- switch (index) {
- case DURABLE: return durableReader;
- case PRIORITY: return priorityReader;
- case TTL: return ttlReader;
- case FIRST_ACQUIRER: return firstAcquirerReader;
- case DELIVERY_COUNT: return deliveryCountReader;
- default: return noSuchFieldReader;
- }
-}
-
-Reader& MessageReader::PropertiesReader::getReader(size_t index)
-{
- switch (index) {
- case MESSAGE_ID: return messageIdReader;
- case USER_ID: return userIdReader;
- case TO: return toReader;
- case SUBJECT: return subjectReader;
- case REPLY_TO: return replyToReader;
- case CORRELATION_ID: return correlationIdReader;
- case CONTENT_TYPE: return contentTypeReader;
- case CONTENT_ENCODING: return contentEncodingReader;
- case ABSOLUTE_EXPIRY_TIME: return absoluteExpiryTimeReader;
- case CREATION_TIME: return creationTimeReader;
- case GROUP_ID: return groupIdReader;
- case GROUP_SEQUENCE: return groupSequenceReader;
- case REPLY_TO_GROUP_ID: return replyToGroupIdReader;
- default: return noSuchFieldReader;
- }
-}
-*/
-
MessageReader::HeaderReader::HeaderReader(MessageReader& p) : parent(p), index(0) {}
void MessageReader::HeaderReader::onBoolean(bool v, const Descriptor*) // durable, first-acquirer
{
@@ -132,7 +99,7 @@ void MessageReader::PropertiesReader::onUuid(const CharSequence& v, const Descri
if (index == MESSAGE_ID) {
parent.onMessageId(v, qpid::types::VAR_UUID);
} else if (index == CORRELATION_ID) {
- parent.onCorrelationId(v);
+ parent.onCorrelationId(v, qpid::types::VAR_UUID);
} else {
QPID_LOG(warning, "Unexpected message format, got uuid at index " << index << " of properties");
}
@@ -154,7 +121,7 @@ void MessageReader::PropertiesReader::onBinary(const CharSequence& v, const Desc
if (index == MESSAGE_ID) {
parent.onMessageId(v, qpid::types::VAR_STRING);
} else if (index == CORRELATION_ID) {
- parent.onCorrelationId(v);
+ parent.onCorrelationId(v, qpid::types::VAR_STRING);
} else if (index == USER_ID) {
parent.onUserId(v);
} else {
@@ -165,9 +132,9 @@ void MessageReader::PropertiesReader::onBinary(const CharSequence& v, const Desc
void MessageReader::PropertiesReader::onString(const CharSequence& v, const Descriptor*) // message-id, correlation-id, group-id, reply-to-group-id, subject, to, reply-to
{
if (index == MESSAGE_ID) {
- parent.onMessageId(v);
+ parent.onMessageId(v, qpid::types::VAR_STRING);
} else if (index == CORRELATION_ID) {
- parent.onCorrelationId(v);
+ parent.onCorrelationId(v, qpid::types::VAR_STRING);
} else if (index == GROUP_ID) {
parent.onGroupId(v);
} else if (index == REPLY_TO_GROUP_ID) {
@@ -218,129 +185,76 @@ void MessageReader::PropertiesReader::onNull(const Descriptor*)
{
++index;
}
-
-/*
-MessageReader::DurableReader::DurableReader(MessageReader& p) : parent(p) {}
-void MessageReader::DurableReader::onBoolean(bool v, const Descriptor*)
-{
- parent.onDurable(v);
-}
-MessageReader::PriorityReader::PriorityReader(MessageReader& p) : parent(p) {}
-void MessageReader::PriorityReader::onUByte(uint8_t v, const Descriptor*)
-{
- parent.onPriority(v);
-}
-MessageReader::TtlReader::TtlReader(MessageReader& p) : parent(p) {}
-void MessageReader::TtlReader::onUInt(uint32_t v, const Descriptor*)
-{
- parent.onTtl(v);
-}
-MessageReader::FirstAcquirerReader::FirstAcquirerReader(MessageReader& p) : parent(p) {}
-void MessageReader::FirstAcquirerReader::onBoolean(bool v, const Descriptor*)
-{
- parent.onFirstAcquirer(v);
-}
-MessageReader::DeliveryCountReader::DeliveryCountReader(MessageReader& p) : parent(p) {}
-void MessageReader::DeliveryCountReader::onUInt(uint32_t v, const Descriptor*)
-{
- parent.onDeliveryCount(v);
-}
-MessageReader::MessageIdReader::MessageIdReader(MessageReader& p) : parent(p) {}
-void MessageReader::MessageIdReader::onUuid(const qpid::types::Uuid& v, const Descriptor*)
-{
- parent.onMessageId(v);
-}
-void MessageReader::MessageIdReader::onULong(uint64_t v, const Descriptor*)
+void MessageReader::PropertiesReader::onBoolean(bool, const Descriptor*)
{
- parent.onMessageId(v);
-}
-void MessageReader::MessageIdReader::onString(const CharSequence& v, const Descriptor*)
-{
- parent.onMessageId(v);
-}
-void MessageReader::MessageIdReader::onBinary(const CharSequence& v, const Descriptor*)
-{
- parent.onMessageId(v);
-}
-MessageReader::UserIdReader::UserIdReader(MessageReader& p) : parent(p) {}
-void MessageReader::UserIdReader::onBinary(const CharSequence& v, const Descriptor*)
-{
- parent.onUserId(v);
-}
-MessageReader::ToReader::ToReader(MessageReader& p) : parent(p) {}
-void MessageReader::ToReader::onString(const CharSequence& v, const Descriptor*)
-{
- parent.onTo(v);
-}
-MessageReader::SubjectReader::SubjectReader(MessageReader& p) : parent(p) {}
-void MessageReader::SubjectReader::onString(const CharSequence& v, const Descriptor*)
-{
- parent.onSubject(v);
-}
-MessageReader::ReplyToReader::ReplyToReader(MessageReader& p) : parent(p) {}
-void MessageReader::ReplyToReader::onString(const CharSequence& v, const Descriptor*)
-{
- parent.onReplyTo(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (boolean)");
+ ++index;
}
-MessageReader::CorrelationIdReader::CorrelationIdReader(MessageReader& p) : parent(p) {}
-void MessageReader::CorrelationIdReader::onUuid(const qpid::types::Uuid& v, const Descriptor*)
+void MessageReader::PropertiesReader::onUByte(uint8_t, const Descriptor*)
{
- parent.onCorrelationId(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (ubyte)");
+ ++index;
}
-void MessageReader::CorrelationIdReader::onULong(uint64_t v, const Descriptor*)
+void MessageReader::PropertiesReader::onUShort(uint16_t, const Descriptor*)
{
- parent.onCorrelationId(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (ushort)");
+ ++index;
}
-void MessageReader::CorrelationIdReader::onString(const CharSequence& v, const Descriptor*)
+void MessageReader::PropertiesReader::onByte(int8_t, const Descriptor*)
{
- parent.onCorrelationId(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (byte)");
+ ++index;
}
-void MessageReader::CorrelationIdReader::onBinary(const CharSequence& v, const Descriptor*)
+void MessageReader::PropertiesReader::onShort(int16_t, const Descriptor*)
{
- parent.onCorrelationId(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (short)");
+ ++index;
}
-MessageReader::ContentTypeReader::ContentTypeReader(MessageReader& p) : parent(p) {}
-void MessageReader::ContentTypeReader::onString(const CharSequence& v, const Descriptor*)
+void MessageReader::PropertiesReader::onInt(int32_t, const Descriptor*)
{
- parent.onContentType(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (int)");
+ ++index;
}
-MessageReader::ContentEncodingReader::ContentEncodingReader(MessageReader& p) : parent(p) {}
-void MessageReader::ContentEncodingReader::onString(const CharSequence& v, const Descriptor*)
+void MessageReader::PropertiesReader::onLong(int64_t, const Descriptor*)
{
- parent.onContentEncoding(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (long)");
+ ++index;
}
-MessageReader::AbsoluteExpiryTimeReader::AbsoluteExpiryTimeReader(MessageReader& p) : parent(p) {}
-void MessageReader::AbsoluteExpiryTimeReader::onTimestamp(int64_t v, const Descriptor*)
+void MessageReader::PropertiesReader::onFloat(float, const Descriptor*)
{
- parent.onAbsoluteExpiryTime(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (float)");
+ ++index;
}
-MessageReader::CreationTimeReader::CreationTimeReader(MessageReader& p) : parent(p) {}
-void MessageReader::CreationTimeReader::onTimestamp(int64_t v, const Descriptor*)
+void MessageReader::PropertiesReader::onDouble(double, const Descriptor*)
{
- parent.onCreationTime(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (double)");
+ ++index;
}
-MessageReader::GroupIdReader::GroupIdReader(MessageReader& p) : parent(p) {}
-void MessageReader::GroupIdReader::onString(const CharSequence& v, const Descriptor*)
+bool MessageReader::PropertiesReader::onStartList(uint32_t /*count*/, const CharSequence& /*elements*/, const CharSequence& /*complete*/, const Descriptor*)
{
- parent.onGroupId(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (list)");
+ ++index;
+ return false;
}
-MessageReader::GroupSequenceReader::GroupSequenceReader(MessageReader& p) : parent(p) {}
-void MessageReader::GroupSequenceReader::onUInt(uint32_t v, const Descriptor*)
+bool MessageReader::PropertiesReader::onStartMap(uint32_t /*count*/, const CharSequence& /*elements*/, const CharSequence& /*complete*/, const Descriptor*)
{
- parent.onGroupSequence(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (map)");
+ ++index;
+ return false;
}
-MessageReader::ReplyToGroupIdReader::ReplyToGroupIdReader(MessageReader& p) : parent(p) {}
-void MessageReader::ReplyToGroupIdReader::onString(const CharSequence& v, const Descriptor*)
+bool MessageReader::PropertiesReader::onStartArray(uint32_t /*count*/, const CharSequence&, const Constructor&, const Descriptor*)
{
- parent.onReplyToGroupId(v);
+ QPID_LOG(info, "skipping message property at index " << index << " unexpected type (array)");
+ ++index;
+ return false;
}
-*/
+
//header, properties, amqp-sequence, amqp-value
-bool MessageReader::onStartList(uint32_t count, const CharSequence& raw, const Descriptor* descriptor)
+bool MessageReader::onStartList(uint32_t count, const CharSequence& elements, const CharSequence& raw, const Descriptor* descriptor)
{
if (delegate) {
- return delegate->onStartList(count, raw, descriptor);
+ return delegate->onStartList(count, elements, raw, descriptor);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got no descriptor for list.");
@@ -351,8 +265,11 @@ bool MessageReader::onStartList(uint32_t count, const CharSequence& raw, const D
} else if (descriptor->match(PROPERTIES_SYMBOL, PROPERTIES_CODE)) {
delegate = &propertiesReader;
return true;
- } else if (descriptor->match(AMQP_SEQUENCE_SYMBOL, AMQP_SEQUENCE_CODE) || descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
- onBody(raw, *descriptor);
+ } else if (descriptor->match(AMQP_SEQUENCE_SYMBOL, AMQP_SEQUENCE_CODE)) {
+ onAmqpSequence(raw);
+ return false;
+ } else if (descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
+ onAmqpValue(elements, qpid::amqp::typecodes::LIST_NAME);
return false;
} else {
QPID_LOG(warning, "Unexpected described list: " << *descriptor);
@@ -372,28 +289,28 @@ void MessageReader::onEndList(uint32_t count, const Descriptor* descriptor)
}
//delivery-annotations, message-annotations, application-properties, amqp-value
-bool MessageReader::onStartMap(uint32_t count, const CharSequence& raw, const Descriptor* descriptor)
+bool MessageReader::onStartMap(uint32_t count, const CharSequence& elements, const CharSequence& raw, const Descriptor* descriptor)
{
if (delegate) {
- return delegate->onStartMap(count, raw, descriptor);
+ return delegate->onStartMap(count, elements, raw, descriptor);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got no descriptor for map.");
return false;
} else if (descriptor->match(DELIVERY_ANNOTATIONS_SYMBOL, DELIVERY_ANNOTATIONS_CODE)) {
- onDeliveryAnnotations(raw);
+ onDeliveryAnnotations(elements, raw);
return false;
} else if (descriptor->match(MESSAGE_ANNOTATIONS_SYMBOL, MESSAGE_ANNOTATIONS_CODE)) {
- onMessageAnnotations(raw);
+ onMessageAnnotations(elements, raw);
return false;
} else if (descriptor->match(FOOTER_SYMBOL, FOOTER_CODE)) {
- onFooter(raw);
+ onFooter(elements, raw);
return false;
} else if (descriptor->match(APPLICATION_PROPERTIES_SYMBOL, APPLICATION_PROPERTIES_CODE)) {
- onApplicationProperties(raw);
+ onApplicationProperties(elements, raw);
return false;
} else if (descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
- onBody(raw, *descriptor);
+ onAmqpValue(elements, qpid::amqp::typecodes::MAP_NAME);
return false;
} else {
QPID_LOG(warning, "Unexpected described map: " << *descriptor);
@@ -417,8 +334,10 @@ void MessageReader::onBinary(const CharSequence& bytes, const Descriptor* descri
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got binary value with no descriptor.");
- } else if (descriptor->match(DATA_SYMBOL, DATA_CODE) || descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
- onBody(bytes, *descriptor);
+ } else if (descriptor->match(DATA_SYMBOL, DATA_CODE)) {
+ onData(bytes);
+ } else if (descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
+ onAmqpValue(bytes, qpid::amqp::typecodes::BINARY_NAME);
} else {
QPID_LOG(warning, "Unexpected binary value with descriptor: " << *descriptor);
}
@@ -434,7 +353,7 @@ void MessageReader::onNull(const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant v;
- onBody(v, *descriptor);
+ onAmqpValue(v);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got null value with no descriptor.");
@@ -450,7 +369,7 @@ void MessageReader::onString(const CharSequence& v, const Descriptor* descriptor
delegate->onString(v, descriptor);
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
- onBody(v, *descriptor);
+ onAmqpValue(v, qpid::amqp::typecodes::STRING_NAME);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got string value with no descriptor.");
@@ -466,7 +385,7 @@ void MessageReader::onSymbol(const CharSequence& v, const Descriptor* descriptor
delegate->onSymbol(v, descriptor);
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
- onBody(v, *descriptor);
+ onAmqpValue(v, qpid::amqp::typecodes::SYMBOL_NAME);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got symbol value with no descriptor.");
@@ -484,7 +403,7 @@ void MessageReader::onBoolean(bool v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got boolean value with no descriptor.");
@@ -502,7 +421,7 @@ void MessageReader::onUByte(uint8_t v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got ubyte value with no descriptor.");
@@ -520,7 +439,7 @@ void MessageReader::onUShort(uint16_t v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got ushort value with no descriptor.");
@@ -538,7 +457,7 @@ void MessageReader::onUInt(uint32_t v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got uint value with no descriptor.");
@@ -556,7 +475,7 @@ void MessageReader::onULong(uint64_t v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got ulong value with no descriptor.");
@@ -574,7 +493,7 @@ void MessageReader::onByte(int8_t v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got byte value with no descriptor.");
@@ -592,7 +511,7 @@ void MessageReader::onShort(int16_t v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got short value with no descriptor.");
@@ -610,7 +529,7 @@ void MessageReader::onInt(int32_t v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got int value with no descriptor.");
@@ -628,7 +547,7 @@ void MessageReader::onLong(int64_t v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got long value with no descriptor.");
@@ -646,7 +565,7 @@ void MessageReader::onFloat(float v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got float value with no descriptor.");
@@ -664,7 +583,7 @@ void MessageReader::onDouble(double v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got double value with no descriptor.");
@@ -681,7 +600,7 @@ void MessageReader::onUuid(const CharSequence& v, const Descriptor* descriptor)
delegate->onUuid(v, descriptor);
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
- onBody(v, *descriptor);
+ onAmqpValue(v, qpid::amqp::typecodes::UUID_NAME);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got uuid value with no descriptor.");
@@ -699,7 +618,7 @@ void MessageReader::onTimestamp(int64_t v, const Descriptor* descriptor)
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
qpid::types::Variant body = v;
- onBody(body, *descriptor);
+ onAmqpValue(body);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got timestamp value with no descriptor.");
@@ -716,7 +635,8 @@ bool MessageReader::onStartArray(uint32_t count, const CharSequence& raw, const
return delegate->onStartArray(count, raw, constructor, descriptor);
} else {
if (descriptor && descriptor->match(AMQP_VALUE_SYMBOL, AMQP_VALUE_CODE)) {
- onBody(raw, *descriptor);
+ //TODO: might be better to decode this here
+ onAmqpValue(raw, qpid::amqp::typecodes::ARRAY_NAME);
} else {
if (!descriptor) {
QPID_LOG(warning, "Expected described type but got array with no descriptor.");
diff --git a/qpid/cpp/src/qpid/amqp/MessageReader.h b/qpid/cpp/src/qpid/amqp/MessageReader.h
index 5d26b288f5..4e2248070b 100644
--- a/qpid/cpp/src/qpid/amqp/MessageReader.h
+++ b/qpid/cpp/src/qpid/amqp/MessageReader.h
@@ -24,7 +24,6 @@
#include "qpid/amqp/CharSequence.h"
#include "qpid/amqp/Reader.h"
-#include "qpid/amqp/ListReader.h"
#include "qpid/types/Variant.h"
#include "qpid/CommonImportExport.h"
@@ -40,11 +39,11 @@ class MessageReader : public Reader
QPID_COMMON_EXTERN MessageReader();
//header, properties, amqp-sequence, amqp-value
- QPID_COMMON_EXTERN bool onStartList(uint32_t, const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN bool onStartList(uint32_t, const CharSequence&, const CharSequence&, const Descriptor*);
QPID_COMMON_EXTERN void onEndList(uint32_t, const Descriptor*);
//delivery-annotations, message-annotations, application-headers, amqp-value
- QPID_COMMON_EXTERN bool onStartMap(uint32_t, const CharSequence&, const Descriptor*);
+ QPID_COMMON_EXTERN bool onStartMap(uint32_t, const CharSequence&, const CharSequence&, const Descriptor*);
QPID_COMMON_EXTERN void onEndMap(uint32_t, const Descriptor*);
//data, amqp-value
@@ -95,175 +94,24 @@ class MessageReader : public Reader
virtual void onGroupSequence(uint32_t) = 0;
virtual void onReplyToGroupId(const CharSequence&) = 0;
- virtual void onApplicationProperties(const CharSequence&) = 0;
- virtual void onDeliveryAnnotations(const CharSequence&) = 0;
- virtual void onMessageAnnotations(const CharSequence&) = 0;
- virtual void onBody(const CharSequence&, const Descriptor&) = 0;
- virtual void onBody(const qpid::types::Variant&, const Descriptor&) = 0;
- virtual void onFooter(const CharSequence&) = 0;
+ virtual void onApplicationProperties(const CharSequence& /*values*/, const CharSequence& /*full*/) = 0;
+ virtual void onDeliveryAnnotations(const CharSequence& /*values*/, const CharSequence& /*full*/) = 0;
+ virtual void onMessageAnnotations(const CharSequence& /*values*/, const CharSequence& /*full*/) = 0;
+
+ virtual void onData(const CharSequence&) = 0;
+ virtual void onAmqpSequence(const CharSequence&) = 0;
+ virtual void onAmqpValue(const CharSequence&, const std::string& type) = 0;
+ virtual void onAmqpValue(const qpid::types::Variant&) = 0;
+
+ virtual void onFooter(const CharSequence& /*values*/, const CharSequence& /*full*/) = 0;
QPID_COMMON_EXTERN CharSequence getBareMessage() const;
private:
- /*
- class DurableReader : public Reader
- {
- public:
- DurableReader(MessageReader&);
- void onBoolean(bool v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class PriorityReader : public Reader
- {
- public:
- PriorityReader(MessageReader&);
- void onUByte(uint8_t v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class TtlReader : public Reader
- {
- public:
- TtlReader(MessageReader&);
- void onUInt(uint32_t v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class FirstAcquirerReader : public Reader
- {
- public:
- FirstAcquirerReader(MessageReader&);
- void onBoolean(bool v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class DeliveryCountReader : public Reader
- {
- public:
- DeliveryCountReader(MessageReader&);
- void onUInt(uint32_t v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class MessageIdReader : public Reader
- {
- public:
- MessageIdReader(MessageReader&);
- void onUuid(const qpid::types::Uuid& v, const Descriptor*);
- void onULong(uint64_t v, const Descriptor*);
- void onString(const CharSequence& v, const Descriptor*);
- void onBinary(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class UserIdReader : public Reader
- {
- public:
- UserIdReader(MessageReader&);
- void onBinary(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class ToReader : public Reader
+ class HeaderReader : public Reader
{
public:
- ToReader(MessageReader&);
- void onString(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class SubjectReader : public Reader
- {
- public:
- SubjectReader(MessageReader&);
- void onString(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class ReplyToReader : public Reader
- {
- public:
- ReplyToReader(MessageReader&);
- void onString(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class CorrelationIdReader : public Reader
- {
- public:
- CorrelationIdReader(MessageReader&);
- void onUuid(const qpid::types::Uuid& v, const Descriptor*);
- void onULong(uint64_t v, const Descriptor*);
- void onString(const CharSequence& v, const Descriptor*);
- void onBinary(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class ContentTypeReader : public Reader
- {
- public:
- ContentTypeReader(MessageReader&);
- void onString(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class ContentEncodingReader : public Reader
- {
- public:
- ContentEncodingReader(MessageReader&);
- void onString(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class AbsoluteExpiryTimeReader : public Reader
- {
- public:
- AbsoluteExpiryTimeReader(MessageReader&);
- void onTimestamp(int64_t v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class CreationTimeReader : public Reader
- {
- public:
- CreationTimeReader(MessageReader&);
- void onTimestamp(int64_t v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class GroupIdReader : public Reader
- {
- public:
- GroupIdReader(MessageReader&);
- void onString(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class GroupSequenceReader : public Reader
- {
- public:
- GroupSequenceReader(MessageReader&);
- void onUInt(uint32_t v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- class ReplyToGroupIdReader : public Reader
- {
- public:
- ReplyToGroupIdReader(MessageReader&);
- void onString(const CharSequence& v, const Descriptor*);
- private:
- MessageReader& parent;
- };
- */
-
- class HeaderReader : public Reader //public ListReader
- {
- public:
- //Reader& getReader(size_t index);
-
HeaderReader(MessageReader&);
void onBoolean(bool v, const Descriptor*); // durable, first-acquirer
void onUByte(uint8_t v, const Descriptor*); // priority
@@ -273,11 +121,9 @@ class MessageReader : public Reader
MessageReader& parent;
size_t index;
};
- class PropertiesReader : public Reader //public ListReader
+ class PropertiesReader : public Reader
{
public:
- //Reader& getReader(size_t index);
-
PropertiesReader(MessageReader&);
void onUuid(const CharSequence& v, const Descriptor*); // message-id, correlation-id
void onULong(uint64_t v, const Descriptor*); // message-id, correlation-id
@@ -287,6 +133,20 @@ class MessageReader : public Reader
void onTimestamp(int64_t v, const Descriptor*); // absolute-expiry-time, creation-time
void onUInt(uint32_t v, const Descriptor*); // group-sequence
void onNull(const Descriptor*);
+
+ void onBoolean(bool, const Descriptor*);
+ void onUByte(uint8_t, const Descriptor*);
+ void onUShort(uint16_t, const Descriptor*);
+ void onByte(int8_t, const Descriptor*);
+ void onShort(int16_t, const Descriptor*);
+ void onInt(int32_t, const Descriptor*);
+ void onLong(int64_t, const Descriptor*);
+ void onFloat(float, const Descriptor*);
+ void onDouble(double, const Descriptor*);
+ bool onStartList(uint32_t /*count*/, const CharSequence& /*elements*/, const CharSequence& /*complete*/, const Descriptor*);
+ bool onStartMap(uint32_t /*count*/, const CharSequence& /*elements*/, const CharSequence& /*complete*/, const Descriptor*);
+ bool onStartArray(uint32_t /*count*/, const CharSequence&, const Constructor&, const Descriptor*);
+
private:
MessageReader& parent;
size_t index;
diff --git a/qpid/cpp/src/qpid/amqp/Reader.h b/qpid/cpp/src/qpid/amqp/Reader.h
index 64019d1521..32f33dc33f 100644
--- a/qpid/cpp/src/qpid/amqp/Reader.h
+++ b/qpid/cpp/src/qpid/amqp/Reader.h
@@ -63,8 +63,8 @@ class Reader
* @return true to get elements of the compound value, false
* to skip over it
*/
- virtual bool onStartList(uint32_t /*count*/, const CharSequence&, const Descriptor*) { return true; }
- virtual bool onStartMap(uint32_t /*count*/, const CharSequence&, const Descriptor*) { return true; }
+ virtual bool onStartList(uint32_t /*count*/, const CharSequence& /*elements*/, const CharSequence& /*complete*/, const Descriptor*) { return true; }
+ virtual bool onStartMap(uint32_t /*count*/, const CharSequence& /*elements*/, const CharSequence& /*complete*/, const Descriptor*) { return true; }
virtual bool onStartArray(uint32_t /*count*/, const CharSequence&, const Constructor&, const Descriptor*) { return true; }
virtual void onEndList(uint32_t /*count*/, const Descriptor*) {}
virtual void onEndMap(uint32_t /*count*/, const Descriptor*) {}
diff --git a/qpid/cpp/src/qpid/amqp/Sasl.h b/qpid/cpp/src/qpid/amqp/Sasl.h
index 558f6071fc..8235a9b9ed 100644
--- a/qpid/cpp/src/qpid/amqp/Sasl.h
+++ b/qpid/cpp/src/qpid/amqp/Sasl.h
@@ -35,12 +35,12 @@ namespace amqp {
class Sasl : protected Reader
{
public:
- Sasl(const std::string& id);
- virtual ~Sasl();
- std::size_t read(const char* data, size_t available);
- std::size_t write(char* data, size_t available);
- std::size_t readProtocolHeader(const char* buffer, std::size_t size);
- std::size_t writeProtocolHeader(char* buffer, std::size_t size);
+ QPID_COMMON_EXTERN Sasl(const std::string& id);
+ QPID_COMMON_EXTERN virtual ~Sasl();
+ QPID_COMMON_EXTERN std::size_t read(const char* data, size_t available);
+ QPID_COMMON_EXTERN std::size_t write(char* data, size_t available);
+ QPID_COMMON_EXTERN std::size_t readProtocolHeader(const char* buffer, std::size_t size);
+ QPID_COMMON_EXTERN std::size_t writeProtocolHeader(char* buffer, std::size_t size);
protected:
const std::string id;
std::vector<char> buffer;
diff --git a/qpid/cpp/src/qpid/amqp/SaslClient.cpp b/qpid/cpp/src/qpid/amqp/SaslClient.cpp
index 69660e9294..d8a38750c5 100644
--- a/qpid/cpp/src/qpid/amqp/SaslClient.cpp
+++ b/qpid/cpp/src/qpid/amqp/SaslClient.cpp
@@ -116,7 +116,7 @@ class SaslOutcomeReader : public Reader
};
}
-bool SaslClient::onStartList(uint32_t count, const CharSequence& arguments, const Descriptor* descriptor)
+bool SaslClient::onStartList(uint32_t count, const CharSequence& arguments, const CharSequence& /*full raw data*/, const Descriptor* descriptor)
{
if (!descriptor) {
QPID_LOG(error, "Expected described type in SASL negotiation but got no descriptor");
diff --git a/qpid/cpp/src/qpid/amqp/SaslClient.h b/qpid/cpp/src/qpid/amqp/SaslClient.h
index 9f3eefadc2..d22887de1a 100644
--- a/qpid/cpp/src/qpid/amqp/SaslClient.h
+++ b/qpid/cpp/src/qpid/amqp/SaslClient.h
@@ -21,6 +21,7 @@
* under the License.
*
*/
+#include <qpid/CommonImportExport.h>
#include "qpid/amqp/Sasl.h"
namespace qpid {
@@ -33,19 +34,19 @@ namespace amqp {
class SaslClient : public Sasl
{
public:
- SaslClient(const std::string& id);
- virtual ~SaslClient();
- virtual void mechanisms(const std::string&) = 0;
- virtual void challenge(const std::string&) = 0;
- virtual void challenge() = 0; //null != empty string
- virtual void outcome(uint8_t result, const std::string&) = 0;
- virtual void outcome(uint8_t result) = 0;
+ QPID_COMMON_EXTERN SaslClient(const std::string& id);
+ QPID_COMMON_EXTERN virtual ~SaslClient();
+ QPID_COMMON_EXTERN virtual void mechanisms(const std::string&) = 0;
+ QPID_COMMON_EXTERN virtual void challenge(const std::string&) = 0;
+ QPID_COMMON_EXTERN virtual void challenge() = 0; //null != empty string
+ QPID_COMMON_EXTERN virtual void outcome(uint8_t result, const std::string&) = 0;
+ QPID_COMMON_EXTERN virtual void outcome(uint8_t result) = 0;
- void init(const std::string& mechanism, const std::string* response, const std::string* hostname);
- void response(const std::string*);
+ QPID_COMMON_EXTERN void init(const std::string& mechanism, const std::string* response, const std::string* hostname);
+ QPID_COMMON_EXTERN void response(const std::string*);
private:
- bool onStartList(uint32_t count, const CharSequence& arguments, const Descriptor* descriptor);
+ QPID_COMMON_EXTERN bool onStartList(uint32_t count, const CharSequence& arguments, const CharSequence&, const Descriptor* descriptor);
};
diff --git a/qpid/cpp/src/qpid/amqp/SaslServer.cpp b/qpid/cpp/src/qpid/amqp/SaslServer.cpp
index 403730ad69..250858bda0 100644
--- a/qpid/cpp/src/qpid/amqp/SaslServer.cpp
+++ b/qpid/cpp/src/qpid/amqp/SaslServer.cpp
@@ -158,7 +158,7 @@ class SaslResponseReader : public Reader
};
}
-bool SaslServer::onStartList(uint32_t count, const CharSequence& arguments, const Descriptor* descriptor)
+bool SaslServer::onStartList(uint32_t count, const CharSequence& arguments, const CharSequence& /*full raw data*/, const Descriptor* descriptor)
{
if (!descriptor) {
QPID_LOG(error, "Expected described type in SASL negotiation but got no descriptor");
diff --git a/qpid/cpp/src/qpid/amqp/SaslServer.h b/qpid/cpp/src/qpid/amqp/SaslServer.h
index 43b960454f..68d0854488 100644
--- a/qpid/cpp/src/qpid/amqp/SaslServer.h
+++ b/qpid/cpp/src/qpid/amqp/SaslServer.h
@@ -33,17 +33,17 @@ namespace amqp {
class SaslServer : public Sasl
{
public:
- SaslServer(const std::string& id);
- virtual ~SaslServer();
+ QPID_COMMON_EXTERN SaslServer(const std::string& id);
+ QPID_COMMON_EXTERN virtual ~SaslServer();
virtual void init(const std::string& mechanism, const std::string* response, const std::string* hostname) = 0;
virtual void response(const std::string*) = 0;
- void mechanisms(const std::string& mechanisms);
- void challenge(const std::string*);
- void completed(bool succeeded);
+ QPID_COMMON_EXTERN void mechanisms(const std::string& mechanisms);
+ QPID_COMMON_EXTERN void challenge(const std::string*);
+ QPID_COMMON_EXTERN void completed(bool succeeded);
private:
- bool onStartList(uint32_t count, const CharSequence& arguments, const Descriptor* descriptor);
+ QPID_COMMON_EXTERN bool onStartList(uint32_t count, const CharSequence& arguments, const CharSequence&, const Descriptor* descriptor);
};
}} // namespace qpid::amqp
diff --git a/qpid/cpp/src/qpid/amqp/descriptors.h b/qpid/cpp/src/qpid/amqp/descriptors.h
index 248d6df2df..e395fc25d7 100644
--- a/qpid/cpp/src/qpid/amqp/descriptors.h
+++ b/qpid/cpp/src/qpid/amqp/descriptors.h
@@ -52,6 +52,7 @@ const Descriptor DELIVERY_ANNOTATIONS(DELIVERY_ANNOTATIONS_CODE);
const Descriptor MESSAGE_ANNOTATIONS(MESSAGE_ANNOTATIONS_CODE);
const Descriptor PROPERTIES(PROPERTIES_CODE);
const Descriptor APPLICATION_PROPERTIES(APPLICATION_PROPERTIES_CODE);
+const Descriptor AMQP_VALUE(AMQP_VALUE_CODE);
const Descriptor DATA(DATA_CODE);
}
diff --git a/qpid/cpp/src/qpid/amqp/typecodes.h b/qpid/cpp/src/qpid/amqp/typecodes.h
index 3c6bd17b97..915b75ca3f 100644
--- a/qpid/cpp/src/qpid/amqp/typecodes.h
+++ b/qpid/cpp/src/qpid/amqp/typecodes.h
@@ -83,7 +83,7 @@ const uint8_t ARRAY32(0xf0);
const std::string NULL_NAME("null");
-const std::string BOOLEAN_NAME("name");
+const std::string BOOLEAN_NAME("bool");
const std::string UBYTE_NAME("ubyte");
const std::string USHORT_NAME("ushort");
diff --git a/qpid/cpp/src/qpid/amqp_0_10/Codecs.h b/qpid/cpp/src/qpid/amqp_0_10/Codecs.h
new file mode 100644
index 0000000000..408307eb7a
--- /dev/null
+++ b/qpid/cpp/src/qpid/amqp_0_10/Codecs.h
@@ -0,0 +1,86 @@
+#ifndef QPID_AMQP_0_10_CODECS_H
+#define QPID_AMQP_0_10_CODECS_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/CommonImportExport.h"
+#include "qpid/types/Variant.h"
+#include "boost/shared_ptr.hpp"
+
+namespace qpid {
+namespace framing {
+class FieldTable;
+class FieldValue;
+}
+namespace amqp_0_10 {
+/**
+ * Codec for encoding/decoding a map of Variants using the AMQP 0-10
+ * map encoding.
+ */
+class QPID_COMMON_CLASS_EXTERN MapCodec
+{
+ public:
+ typedef qpid::types::Variant::Map ObjectType;
+ static void QPID_COMMON_EXTERN encode(const ObjectType&, std::string&);
+ static void QPID_COMMON_EXTERN decode(const std::string&, ObjectType&);
+ static size_t QPID_COMMON_EXTERN encodedSize(const ObjectType&);
+ static const QPID_COMMON_EXTERN std::string contentType;
+ private:
+};
+
+/**
+ * Codec for encoding/decoding a list of Variants using the AMQP 0-10
+ * list encoding.
+ */
+class QPID_COMMON_CLASS_EXTERN ListCodec
+{
+ public:
+ typedef qpid::types::Variant::List ObjectType;
+ static void QPID_COMMON_EXTERN encode(const ObjectType&, std::string&);
+ static void QPID_COMMON_EXTERN decode(const std::string&, ObjectType&);
+ static size_t QPID_COMMON_EXTERN encodedSize(const ObjectType&);
+ static const QPID_COMMON_EXTERN std::string contentType;
+ private:
+};
+
+/**
+ * @internal
+ *
+ * Conversion functions between qpid::types:Variant::Map and the
+ * deprecated qpid::framing::FieldTable.
+ *
+ */
+QPID_COMMON_EXTERN void translate(const qpid::types::Variant::Map& from,
+ qpid::framing::FieldTable& to);
+QPID_COMMON_EXTERN void translate(const qpid::types::Variant::Map& from, const std::string& efield, const qpid::types::Variant& evalue,
+ qpid::framing::FieldTable& to);
+QPID_COMMON_EXTERN void translate(const qpid::framing::FieldTable& from,
+ qpid::types::Variant::Map& to);
+
+QPID_COMMON_EXTERN void translate(const boost::shared_ptr<qpid::framing::FieldValue> from,
+ qpid::types::Variant& to);
+QPID_COMMON_EXTERN void translate(const types::Variant& from,
+ boost::shared_ptr<qpid::framing::FieldValue> to);
+
+}} // namespace qpid::amqp_0_10
+
+#endif /*!QPID_AMQP_0_10_CODECS_H*/
diff --git a/qpid/cpp/src/qpid/broker/Broker.cpp b/qpid/cpp/src/qpid/broker/Broker.cpp
index 69894e1633..85900f8061 100644
--- a/qpid/cpp/src/qpid/broker/Broker.cpp
+++ b/qpid/cpp/src/qpid/broker/Broker.cpp
@@ -38,6 +38,7 @@
#include "qpid/broker/PersistableObject.h"
#include "qpid/broker/QueueFlowLimit.h"
#include "qpid/broker/QueueSettings.h"
+#include "qpid/broker/TransactionObserver.h"
#include "qpid/broker/MessageGroupManager.h"
#include "qmf/org/apache/qpid/broker/Package.h"
@@ -139,7 +140,7 @@ Broker::Options::Options(const std::string& name) :
requireEncrypted(false),
knownHosts(knownHostsNone),
qmf2Support(true),
- qmf1Support(true),
+ qmf1Support(false),
queueFlowStopRatio(80),
queueFlowResumeRatio(70),
queueThresholdEventRatio(80),
@@ -399,7 +400,7 @@ boost::intrusive_ptr<Broker> Broker::create(const Options& opts)
return boost::intrusive_ptr<Broker>(new Broker(opts));
}
-void Broker::setStore (boost::shared_ptr<MessageStore>& _store)
+void Broker::setStore (const boost::shared_ptr<MessageStore>& _store)
{
store.reset(new MessageStoreModule (_store));
setStore();
@@ -442,6 +443,8 @@ void Broker::shutdown() {
}
Broker::~Broker() {
+ if (mgmtObject != 0)
+ mgmtObject->debugStats("destroying");
shutdown();
finalize(); // Finalize any plugins.
if (config.auth)
@@ -1446,7 +1449,7 @@ void Broker::bind(const std::string& queueName,
throw framing::NotFoundException(QPID_MSG("Bind failed. No such exchange: " << exchangeName));
} else {
if (queue->bind(exchange, key, arguments)) {
- getConfigurationObservers().bind(exchange, queue, key, arguments);
+ getBrokerObservers().bind(exchange, queue, key, arguments);
if (managementAgent.get()) {
managementAgent->raiseEvent(_qmf::EventBind(connectionId, userId, exchangeName,
queueName, key, ManagementAgent::toMap(arguments)));
@@ -1488,7 +1491,7 @@ void Broker::unbind(const std::string& queueName,
if (exchange->isDurable() && queue->isDurable()) {
store->unbind(*exchange, *queue, key, qpid::framing::FieldTable());
}
- getConfigurationObservers().unbind(
+ getBrokerObservers().unbind(
exchange, queue, key, framing::FieldTable());
if (managementAgent.get()) {
managementAgent->raiseEvent(_qmf::EventUnbind(connectionId, userId, exchangeName, queueName, key));
diff --git a/qpid/cpp/src/qpid/broker/Broker.h b/qpid/cpp/src/qpid/broker/Broker.h
index 52b79a0944..3e22fb491b 100644
--- a/qpid/cpp/src/qpid/broker/Broker.h
+++ b/qpid/cpp/src/qpid/broker/Broker.h
@@ -38,7 +38,7 @@
#include "qpid/broker/System.h"
#include "qpid/broker/ConsumerFactory.h"
#include "qpid/broker/ConnectionObservers.h"
-#include "qpid/broker/ConfigurationObservers.h"
+#include "qpid/broker/BrokerObservers.h"
#include "qpid/management/Manageable.h"
#include "qpid/sys/ConnectionCodec.h"
#include "qpid/sys/Mutex.h"
@@ -65,6 +65,7 @@ class AclModule;
class ExpiryPolicy;
class Message;
struct QueueSettings;
+
static const uint16_t DEFAULT_PORT=5672;
struct NoSuchTransportException : qpid::Exception
@@ -175,7 +176,7 @@ class Broker : public sys::Runnable, public Plugin::Target,
AclModule* acl;
DataDir dataDir;
ConnectionObservers connectionObservers;
- ConfigurationObservers configurationObservers;
+ BrokerObservers brokerObservers;
QueueRegistry queues;
ExchangeRegistry exchanges;
@@ -225,7 +226,8 @@ class Broker : public sys::Runnable, public Plugin::Target,
/** Shut down the broker */
QPID_BROKER_EXTERN virtual void shutdown();
- QPID_BROKER_EXTERN void setStore (boost::shared_ptr<MessageStore>& store);
+ QPID_BROKER_EXTERN void setStore (const boost::shared_ptr<MessageStore>& store);
+ bool hasStore() const { return store.get(); }
MessageStore& getStore() { return *store; }
void setAcl (AclModule* _acl) {acl = _acl;}
AclModule* getAcl() { return acl; }
@@ -352,7 +354,7 @@ class Broker : public sys::Runnable, public Plugin::Target,
ConsumerFactories& getConsumerFactories() { return consumerFactories; }
ConnectionObservers& getConnectionObservers() { return connectionObservers; }
- ConfigurationObservers& getConfigurationObservers() { return configurationObservers; }
+ BrokerObservers& getBrokerObservers() { return brokerObservers; }
/** Properties to be set on outgoing link connections */
QPID_BROKER_EXTERN framing::FieldTable getLinkClientProperties() const;
diff --git a/qpid/cpp/src/qpid/broker/ConfigurationObserver.h b/qpid/cpp/src/qpid/broker/BrokerObserver.h
index 789490e08c..2249d33e64 100644
--- a/qpid/cpp/src/qpid/broker/ConfigurationObserver.h
+++ b/qpid/cpp/src/qpid/broker/BrokerObserver.h
@@ -1,5 +1,5 @@
-#ifndef QPID_BROKER_CONFIGURATIONOBSERVER_H
-#define QPID_BROKER_CONFIGURATIONOBSERVER_H
+#ifndef QPID_BROKER_BROKEROBSERVER_H
+#define QPID_BROKER_BROKEROBSERVER_H
/*
*
@@ -34,7 +34,8 @@ class FieldTable;
namespace broker {
class Queue;
class Exchange;
-
+class TxBuffer;
+class DtxBuffer;
/**
* Observer for changes to configuration (aka wiring)
@@ -43,10 +44,10 @@ class Exchange;
* the registry lock held. This is necessary to ensure
* they are called in the correct sequence.
*/
-class ConfigurationObserver
+class BrokerObserver
{
public:
- virtual ~ConfigurationObserver() {}
+ virtual ~BrokerObserver() {}
virtual void queueCreate(const boost::shared_ptr<Queue>&) {}
virtual void queueDestroy(const boost::shared_ptr<Queue>&) {}
virtual void exchangeCreate(const boost::shared_ptr<Exchange>&) {}
@@ -59,7 +60,9 @@ class ConfigurationObserver
const boost::shared_ptr<Queue>& ,
const std::string& /*key*/,
const framing::FieldTable& /*args*/) {}
+ virtual void startTx(const boost::shared_ptr<TxBuffer>&) {}
+ virtual void startDtx(const boost::shared_ptr<DtxBuffer>&) {}
};
}} // namespace qpid::broker
-#endif /*!QPID_BROKER_CONFIGURATIONOBSERVER_H*/
+#endif /*!QPID_BROKER_BROKEROBSERVER_H*/
diff --git a/qpid/cpp/src/qpid/broker/ConfigurationObservers.h b/qpid/cpp/src/qpid/broker/BrokerObservers.h
index 4c1159747d..5ba7bac890 100644
--- a/qpid/cpp/src/qpid/broker/ConfigurationObservers.h
+++ b/qpid/cpp/src/qpid/broker/BrokerObservers.h
@@ -1,5 +1,5 @@
-#ifndef QPID_BROKER_CONFIGURATIONOBSERVERS_H
-#define QPID_BROKER_CONFIGURATIONOBSERVERS_H
+#ifndef QPID_BROKER_BROKEROBSERVERS_H
+#define QPID_BROKER_BROKEROBSERVERS_H
/*
*
@@ -22,7 +22,7 @@
*
*/
-#include "ConfigurationObserver.h"
+#include "BrokerObserver.h"
#include "Observers.h"
#include "qpid/sys/Mutex.h"
@@ -30,43 +30,48 @@ namespace qpid {
namespace broker {
/**
- * A configuration observer that delegates to a collection of
- * configuration observers.
+ * A broker observer that delegates to a collection of broker observers.
*
* THREAD SAFE
*/
-class ConfigurationObservers : public ConfigurationObserver,
- public Observers<ConfigurationObserver>
+class BrokerObservers : public BrokerObserver,
+ public Observers<BrokerObserver>
{
public:
void queueCreate(const boost::shared_ptr<Queue>& q) {
- each(boost::bind(&ConfigurationObserver::queueCreate, _1, q));
+ each(boost::bind(&BrokerObserver::queueCreate, _1, q));
}
void queueDestroy(const boost::shared_ptr<Queue>& q) {
- each(boost::bind(&ConfigurationObserver::queueDestroy, _1, q));
+ each(boost::bind(&BrokerObserver::queueDestroy, _1, q));
}
void exchangeCreate(const boost::shared_ptr<Exchange>& e) {
- each(boost::bind(&ConfigurationObserver::exchangeCreate, _1, e));
+ each(boost::bind(&BrokerObserver::exchangeCreate, _1, e));
}
void exchangeDestroy(const boost::shared_ptr<Exchange>& e) {
- each(boost::bind(&ConfigurationObserver::exchangeDestroy, _1, e));
+ each(boost::bind(&BrokerObserver::exchangeDestroy, _1, e));
}
void bind(const boost::shared_ptr<Exchange>& exchange,
const boost::shared_ptr<Queue>& queue,
const std::string& key,
const framing::FieldTable& args) {
each(boost::bind(
- &ConfigurationObserver::bind, _1, exchange, queue, key, args));
+ &BrokerObserver::bind, _1, exchange, queue, key, args));
}
void unbind(const boost::shared_ptr<Exchange>& exchange,
const boost::shared_ptr<Queue>& queue,
const std::string& key,
const framing::FieldTable& args) {
each(boost::bind(
- &ConfigurationObserver::unbind, _1, exchange, queue, key, args));
+ &BrokerObserver::unbind, _1, exchange, queue, key, args));
+ }
+ void startTx(const boost::shared_ptr<TxBuffer>& tx) {
+ each(boost::bind(&BrokerObserver::startTx, _1, tx));
+ }
+ void startDtx(const boost::shared_ptr<DtxBuffer>& dtx) {
+ each(boost::bind(&BrokerObserver::startDtx, _1, dtx));
}
};
}} // namespace qpid::broker
-#endif /*!QPID_BROKER_CONFIGURATIONOBSERVERS_H*/
+#endif /*!QPID_BROKER_BROKEROBSERVERS_H*/
diff --git a/qpid/cpp/src/qpid/broker/DeliveryRecord.cpp b/qpid/cpp/src/qpid/broker/DeliveryRecord.cpp
index 14a2e94571..06ecf62ed4 100644
--- a/qpid/cpp/src/qpid/broker/DeliveryRecord.cpp
+++ b/qpid/cpp/src/qpid/broker/DeliveryRecord.cpp
@@ -106,7 +106,9 @@ void DeliveryRecord::dequeue(TransactionContext* ctxt) const
void DeliveryRecord::committed() const
{
- queue->dequeueCommitted(msg);
+ if (acquired && !ended) {
+ queue->dequeueCommitted(msg);
+ }
}
void DeliveryRecord::reject()
diff --git a/qpid/cpp/src/qpid/broker/DirectExchange.cpp b/qpid/cpp/src/qpid/broker/DirectExchange.cpp
index 773a99d2c9..8ab7b59ed1 100644
--- a/qpid/cpp/src/qpid/broker/DirectExchange.cpp
+++ b/qpid/cpp/src/qpid/broker/DirectExchange.cpp
@@ -196,6 +196,9 @@ bool DirectExchange::isBound(Queue::shared_ptr queue, const string* const routin
return false;
}
-DirectExchange::~DirectExchange() {}
+DirectExchange::~DirectExchange() {
+ if (mgmtExchange != 0)
+ mgmtExchange->debugStats("destroying");
+}
const std::string DirectExchange::typeName("direct");
diff --git a/qpid/cpp/src/qpid/broker/DirectExchange.h b/qpid/cpp/src/qpid/broker/DirectExchange.h
index 833be52c1c..cfefef54e8 100644
--- a/qpid/cpp/src/qpid/broker/DirectExchange.h
+++ b/qpid/cpp/src/qpid/broker/DirectExchange.h
@@ -42,7 +42,7 @@ class DirectExchange : public virtual Exchange {
qpid::sys::Mutex lock;
public:
- static const std::string typeName;
+ QPID_BROKER_EXTERN static const std::string typeName;
QPID_BROKER_EXTERN DirectExchange(const std::string& name,
management::Manageable* parent = 0, Broker* broker = 0);
diff --git a/qpid/cpp/src/qpid/broker/DtxAck.h b/qpid/cpp/src/qpid/broker/DtxAck.h
index 10d63f5b0c..5775edf5de 100644
--- a/qpid/cpp/src/qpid/broker/DtxAck.h
+++ b/qpid/cpp/src/qpid/broker/DtxAck.h
@@ -39,6 +39,9 @@ class DtxAck : public TxOp{
virtual bool prepare(TransactionContext* ctxt) throw();
virtual void commit() throw();
virtual void rollback() throw();
+ // TODO aconway 2013-07-08:
+ virtual void callObserver(const boost::shared_ptr<TransactionObserver>&) {}
+
virtual ~DtxAck(){}
const DeliveryRecords& getPending() const { return pending; }
};
diff --git a/qpid/cpp/src/qpid/broker/Exchange.cpp b/qpid/cpp/src/qpid/broker/Exchange.cpp
index b9080cdda5..0a25d57cd8 100644
--- a/qpid/cpp/src/qpid/broker/Exchange.cpp
+++ b/qpid/cpp/src/qpid/broker/Exchange.cpp
@@ -353,6 +353,7 @@ Exchange::Binding::Binding(const string& _key, Queue::shared_ptr _queue, Exchang
Exchange::Binding::~Binding ()
{
if (mgmtBinding != 0) {
+ mgmtBinding->debugStats("destroying");
_qmf::Queue::shared_ptr mo = boost::dynamic_pointer_cast<_qmf::Queue>(queue->GetManagementObject());
if (mo != 0)
mo->dec_bindingCount();
diff --git a/qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp b/qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp
index 645918d526..9eeffadb90 100644
--- a/qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp
+++ b/qpid/cpp/src/qpid/broker/ExchangeRegistry.cpp
@@ -81,7 +81,7 @@ pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(
result = std::pair<Exchange::shared_ptr, bool>(exchange, true);
if (alternate) exchange->setAlternate(alternate);
// Call exchangeCreate inside the lock to ensure correct ordering.
- if (broker) broker->getConfigurationObservers().exchangeCreate(exchange);
+ if (broker) broker->getBrokerObservers().exchangeCreate(exchange);
} else {
result = std::pair<Exchange::shared_ptr, bool>(i->second, false);
}
@@ -118,7 +118,7 @@ void ExchangeRegistry::destroy(
if (broker) {
// Call exchangeDestroy and raiseEvent inside the lock to ensure
// correct ordering.
- broker->getConfigurationObservers().exchangeDestroy(i->second);
+ broker->getBrokerObservers().exchangeDestroy(i->second);
if (broker->getManagementAgent())
broker->getManagementAgent()->raiseEvent(
_qmf::EventExchangeDelete(connectionId, userId, name));
diff --git a/qpid/cpp/src/qpid/broker/FanOutExchange.cpp b/qpid/cpp/src/qpid/broker/FanOutExchange.cpp
index 43c67af810..20ca06e048 100644
--- a/qpid/cpp/src/qpid/broker/FanOutExchange.cpp
+++ b/qpid/cpp/src/qpid/broker/FanOutExchange.cpp
@@ -117,6 +117,9 @@ bool FanOutExchange::isBound(Queue::shared_ptr queue, const string* const, const
}
-FanOutExchange::~FanOutExchange() {}
+FanOutExchange::~FanOutExchange() {
+ if (mgmtExchange != 0)
+ mgmtExchange->debugStats("destroying");
+}
const std::string FanOutExchange::typeName("fanout");
diff --git a/qpid/cpp/src/qpid/broker/HeadersExchange.cpp b/qpid/cpp/src/qpid/broker/HeadersExchange.cpp
index 82284feaeb..4e86b09565 100644
--- a/qpid/cpp/src/qpid/broker/HeadersExchange.cpp
+++ b/qpid/cpp/src/qpid/broker/HeadersExchange.cpp
@@ -339,7 +339,10 @@ void HeadersExchange::getNonFedArgs(const FieldTable* args, FieldTable& nonFedAr
}
}
-HeadersExchange::~HeadersExchange() {}
+HeadersExchange::~HeadersExchange() {
+ if (mgmtExchange != 0)
+ mgmtExchange->debugStats("destroying");
+}
const std::string HeadersExchange::typeName("headers");
diff --git a/qpid/cpp/src/qpid/broker/HeadersExchange.h b/qpid/cpp/src/qpid/broker/HeadersExchange.h
index b5b10350d2..e51478d365 100644
--- a/qpid/cpp/src/qpid/broker/HeadersExchange.h
+++ b/qpid/cpp/src/qpid/broker/HeadersExchange.h
@@ -79,7 +79,7 @@ class HeadersExchange : public virtual Exchange {
framing::FieldTable& nonFedArgs);
public:
- static const std::string typeName;
+ QPID_BROKER_EXTERN static const std::string typeName;
QPID_BROKER_EXTERN HeadersExchange(const std::string& name,
management::Manageable* parent = 0, Broker* broker = 0);
diff --git a/qpid/cpp/src/qpid/broker/IngressCompletion.h b/qpid/cpp/src/qpid/broker/IngressCompletion.h
index 28bb9cf03d..ca21ec9837 100644
--- a/qpid/cpp/src/qpid/broker/IngressCompletion.h
+++ b/qpid/cpp/src/qpid/broker/IngressCompletion.h
@@ -38,7 +38,7 @@ class Queue;
class IngressCompletion : public AsyncCompletion
{
public:
- virtual ~IngressCompletion();
+ QPID_BROKER_EXTERN virtual ~IngressCompletion();
void enqueueAsync(boost::shared_ptr<Queue>);
void flush();
diff --git a/qpid/cpp/src/qpid/broker/Link.cpp b/qpid/cpp/src/qpid/broker/Link.cpp
index 31685eb1de..cd7ba35dd8 100644
--- a/qpid/cpp/src/qpid/broker/Link.cpp
+++ b/qpid/cpp/src/qpid/broker/Link.cpp
@@ -536,7 +536,7 @@ bool Link::tryFailoverLH() {
if (url.empty()) return false;
Address next = url[reconnectNext++];
if (next.host != host || next.port != port || next.protocol != transport) {
- QPID_LOG(notice, "Inter-broker link '" << name << "' failing over to " << next);
+ QPID_LOG(info, "Inter-broker link '" << name << "' failing over to " << next);
reconnectLH(next);
return true;
}
diff --git a/qpid/cpp/src/qpid/broker/Link.h b/qpid/cpp/src/qpid/broker/Link.h
index d9924feec3..ceee0186f3 100644
--- a/qpid/cpp/src/qpid/broker/Link.h
+++ b/qpid/cpp/src/qpid/broker/Link.h
@@ -151,8 +151,8 @@ class Link : public PersistableConfig, public management::Manageable {
bool isDurable() { return durable; }
void maintenanceVisit ();
- framing::ChannelId nextChannel(); // allocate channel from link free pool
- void returnChannel(framing::ChannelId); // return channel to link free pool
+ QPID_BROKER_EXTERN framing::ChannelId nextChannel(); // allocate channel from link free pool
+ QPID_BROKER_EXTERN void returnChannel(framing::ChannelId); // return channel to link free pool
void add(Bridge::shared_ptr);
void cancel(Bridge::shared_ptr);
diff --git a/qpid/cpp/src/qpid/broker/LossyQueue.cpp b/qpid/cpp/src/qpid/broker/LossyQueue.cpp
index 4104503dac..ba7dfd11a1 100644
--- a/qpid/cpp/src/qpid/broker/LossyQueue.cpp
+++ b/qpid/cpp/src/qpid/broker/LossyQueue.cpp
@@ -52,7 +52,7 @@ bool LossyQueue::checkDepth(const QueueDepth& increment, const Message& message)
QPID_LOG(debug, "purging " << name << ": current depth is [" << current << "], max depth is [" << settings.maxDepth << "], new message has size " << increment.getSize());
qpid::sys::Mutex::ScopedUnlock u(messageLock);
//TODO: arguably we should try and purge expired messages first but that is potentially expensive
- if (remove(1, settings.priorities ? boost::bind(&isLowerPriorityThan, message.getPriority(), _1) : MessagePredicate(), MessageFunctor(), PURGE, false)) {
+ if (remove(1, settings.priorities ? boost::bind(&isLowerPriorityThan, message.getPriority(), _1) : MessagePredicate(), boost::bind(&reroute, alternateExchange, _1), PURGE, false)) {
if (mgmtObject) {
mgmtObject->inc_discardsRing(1);
if (brokerMgmtObject)
diff --git a/qpid/cpp/src/qpid/broker/Lvq.cpp b/qpid/cpp/src/qpid/broker/Lvq.cpp
index ff13b97dbd..34f080c57f 100644
--- a/qpid/cpp/src/qpid/broker/Lvq.cpp
+++ b/qpid/cpp/src/qpid/broker/Lvq.cpp
@@ -57,7 +57,8 @@ void Lvq::push(Message& message, bool isRecovery)
copy.notify();
if (removed) {
if (isRecovery) pendingDequeues.push_back(old);
- else dequeueFromStore(old.getPersistentContext());//do outside of lock
+ else if (old.isPersistent())
+ dequeueFromStore(old.getPersistentContext());//do outside of lock
}
}
}} // namespace qpid::broker
diff --git a/qpid/cpp/src/qpid/broker/Message.cpp b/qpid/cpp/src/qpid/broker/Message.cpp
index ec44404793..e71125b4ab 100644
--- a/qpid/cpp/src/qpid/broker/Message.cpp
+++ b/qpid/cpp/src/qpid/broker/Message.cpp
@@ -145,7 +145,7 @@ uint64_t Message::getTtl() const
}
}
-bool Message::getTtl(uint64_t ttl) const
+bool Message::getTtl(uint64_t& ttl) const
{
if (encoding->getTtl(ttl) && expiration < FAR_FUTURE) {
sys::Duration remaining(sys::AbsTime::now(), getExpiration());
@@ -182,8 +182,10 @@ void Message::addAnnotation(const std::string& key, const qpid::types::Variant&
void Message::annotationsChanged()
{
if (persistentContext) {
+ uint64_t id = persistentContext->getPersistenceId();
persistentContext = persistentContext->merge(annotations);
persistentContext->setIngressCompletion(encoding);
+ persistentContext->setPersistenceId(id);
}
}
diff --git a/qpid/cpp/src/qpid/broker/Message.h b/qpid/cpp/src/qpid/broker/Message.h
index 03ef21e77a..84f62a771d 100644
--- a/qpid/cpp/src/qpid/broker/Message.h
+++ b/qpid/cpp/src/qpid/broker/Message.h
@@ -39,7 +39,7 @@
namespace qpid {
namespace amqp {
class MapHandler;
-class MessageId;
+struct MessageId;
}
namespace management {
@@ -104,7 +104,7 @@ public:
sys::AbsTime getExpiration() const { return expiration; }
void setExpiration(sys::AbsTime exp) { expiration = exp; }
uint64_t getTtl() const;
- bool getTtl(uint64_t) const;
+ QPID_BROKER_EXTERN bool getTtl(uint64_t&) const;
/** set the timestamp delivery property to the current time-of-day */
QPID_BROKER_EXTERN void setTimestamp();
@@ -136,7 +136,7 @@ public:
QPID_BROKER_EXTERN qpid::types::Variant getAnnotation(const std::string& key) const;
QPID_BROKER_EXTERN const qpid::types::Variant::Map& getAnnotations() const;
- std::string getUserId() const;
+ QPID_BROKER_EXTERN std::string getUserId() const;
QPID_BROKER_EXTERN std::string getContent() const;//Used for ha, management, when content needs to be decoded
diff --git a/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp b/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp
index f19b31fa76..edfe6e7819 100644
--- a/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp
+++ b/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp
@@ -33,7 +33,7 @@ using std::string;
namespace qpid {
namespace broker {
-MessageStoreModule::MessageStoreModule(boost::shared_ptr<MessageStore>& _store)
+MessageStoreModule::MessageStoreModule(const boost::shared_ptr<MessageStore>& _store)
: store(_store) {}
MessageStoreModule::~MessageStoreModule()
diff --git a/qpid/cpp/src/qpid/broker/MessageStoreModule.h b/qpid/cpp/src/qpid/broker/MessageStoreModule.h
index 82308db84c..a71e8cc9b6 100644
--- a/qpid/cpp/src/qpid/broker/MessageStoreModule.h
+++ b/qpid/cpp/src/qpid/broker/MessageStoreModule.h
@@ -38,7 +38,7 @@ class MessageStoreModule : public MessageStore
{
boost::shared_ptr<MessageStore> store;
public:
- MessageStoreModule(boost::shared_ptr<MessageStore>& store);
+ MessageStoreModule(const boost::shared_ptr<MessageStore>& store);
bool init(const Options* options);
std::auto_ptr<TransactionContext> begin();
diff --git a/qpid/cpp/src/qpid/broker/ObjectFactory.h b/qpid/cpp/src/qpid/broker/ObjectFactory.h
index 1b8f0356d6..d1b570da2f 100644
--- a/qpid/cpp/src/qpid/broker/ObjectFactory.h
+++ b/qpid/cpp/src/qpid/broker/ObjectFactory.h
@@ -21,6 +21,7 @@
* under the License.
*
*/
+#include "qpid/broker/BrokerImportExport.h"
#include "qpid/types/Variant.h"
#include <vector>
@@ -56,7 +57,7 @@ class ObjectFactoryRegistry : public ObjectFactory
bool recoverObject(Broker&, const std::string& type, const std::string& name, const qpid::types::Variant::Map& properties, uint64_t persistenceId);
~ObjectFactoryRegistry();
- void add(ObjectFactory*);
+ QPID_BROKER_EXTERN void add(ObjectFactory*);
private:
typedef std::vector<ObjectFactory*> Factories;
Factories factories;
diff --git a/qpid/cpp/src/qpid/broker/PagedQueue.cpp b/qpid/cpp/src/qpid/broker/PagedQueue.cpp
index 9bce28061a..862e9c0d48 100644
--- a/qpid/cpp/src/qpid/broker/PagedQueue.cpp
+++ b/qpid/cpp/src/qpid/broker/PagedQueue.cpp
@@ -64,7 +64,7 @@ size_t decode(ProtocolRegistry& protocols, Message& msg, const char* data, size_
}
PagedQueue::PagedQueue(const std::string& name, const std::string& directory, uint m, uint factor, ProtocolRegistry& p)
- : pageSize(file.getPageSize()*factor), maxLoaded(m), protocols(p), offset(0)
+ : pageSize(file.getPageSize()*factor), maxLoaded(m), protocols(p), offset(0), loaded(0), version(0)
{
path = file.open(name, directory);
QPID_LOG(debug, "PagedQueue[" << path << "]");
@@ -295,7 +295,8 @@ void PagedQueue::Page::load(MemoryMappedFile& file, ProtocolRegistry& protocols)
bool haveData = used > 0;
used = 4;//first 4 bytes are the count
if (haveData) {
- uint32_t count = *(reinterpret_cast<uint32_t*>(region));
+ qpid::framing::Buffer buffer(region, sizeof(uint32_t));
+ uint32_t count = buffer.getLong();
//decode messages into Page::messages
for (size_t i = 0; i < count; ++i) {
Message message;
@@ -331,7 +332,8 @@ void PagedQueue::Page::unload(MemoryMappedFile& file)
if (i->getState() == ACQUIRED) acquired.add(i->getSequence());
}
uint32_t count = messages.size();
- ::memcpy(region, &count, sizeof(count));
+ qpid::framing::Buffer buffer(region, sizeof(uint32_t));
+ buffer.putLong(count);
file.flush(region, size);
file.unmap(region, size);
//remove messages from memory
diff --git a/qpid/cpp/src/qpid/broker/PersistableMessage.h b/qpid/cpp/src/qpid/broker/PersistableMessage.h
index 85ac4a3b85..cfcf8f0afc 100644
--- a/qpid/cpp/src/qpid/broker/PersistableMessage.h
+++ b/qpid/cpp/src/qpid/broker/PersistableMessage.h
@@ -62,8 +62,8 @@ class PersistableMessage : public Persistable
mutable uint64_t persistenceId;
public:
- virtual ~PersistableMessage();
- PersistableMessage();
+ QPID_BROKER_EXTERN virtual ~PersistableMessage();
+ QPID_BROKER_EXTERN PersistableMessage();
virtual QPID_BROKER_EXTERN bool isPersistent() const = 0;
diff --git a/qpid/cpp/src/qpid/broker/PersistableObject.h b/qpid/cpp/src/qpid/broker/PersistableObject.h
index c6aff466f7..4d7e5e4498 100644
--- a/qpid/cpp/src/qpid/broker/PersistableObject.h
+++ b/qpid/cpp/src/qpid/broker/PersistableObject.h
@@ -21,6 +21,7 @@
* under the License.
*
*/
+#include "qpid/broker/BrokerImportExport.h"
#include "PersistableConfig.h"
#include "qpid/types/Variant.h"
#include <vector>
@@ -37,13 +38,13 @@ class RecoverableConfig;
class PersistableObject : public PersistableConfig
{
public:
- PersistableObject(const std::string& name, const std::string& type, const qpid::types::Variant::Map properties);
- virtual ~PersistableObject();
- const std::string& getName() const;
- void setPersistenceId(uint64_t id) const;
- uint64_t getPersistenceId() const;
- void encode(framing::Buffer& buffer) const;
- uint32_t encodedSize() const;
+ QPID_BROKER_EXTERN PersistableObject(const std::string& name, const std::string& type, const qpid::types::Variant::Map properties);
+ QPID_BROKER_EXTERN virtual ~PersistableObject();
+ QPID_BROKER_EXTERN const std::string& getName() const;
+ QPID_BROKER_EXTERN void setPersistenceId(uint64_t id) const;
+ QPID_BROKER_EXTERN uint64_t getPersistenceId() const;
+ QPID_BROKER_EXTERN void encode(framing::Buffer& buffer) const;
+ QPID_BROKER_EXTERN uint32_t encodedSize() const;
friend class RecoveredObjects;
private:
std::string name;
diff --git a/qpid/cpp/src/qpid/broker/PriorityQueue.cpp b/qpid/cpp/src/qpid/broker/PriorityQueue.cpp
index 99488ded13..5e60fe5cce 100644
--- a/qpid/cpp/src/qpid/broker/PriorityQueue.cpp
+++ b/qpid/cpp/src/qpid/broker/PriorityQueue.cpp
@@ -135,7 +135,12 @@ void PriorityQueue::publish(const Message& published)
Message* PriorityQueue::release(const QueueCursor& cursor)
{
MessagePointer* ptr = fifo.release(cursor);
- return ptr ? &(ptr->holder->message) : 0;
+ if (ptr) {
+ messages[ptr->holder->priority].resetCursors();
+ return &(ptr->holder->message);
+ } else {
+ return 0;
+ }
}
void PriorityQueue::foreach(Functor f)
diff --git a/qpid/cpp/src/qpid/broker/Protocol.h b/qpid/cpp/src/qpid/broker/Protocol.h
index 282e4bd83d..e736e4b367 100644
--- a/qpid/cpp/src/qpid/broker/Protocol.h
+++ b/qpid/cpp/src/qpid/broker/Protocol.h
@@ -72,7 +72,7 @@ class ProtocolRegistry : public Protocol
QPID_BROKER_EXTERN Message decode(qpid::framing::Buffer&);
QPID_BROKER_EXTERN ~ProtocolRegistry();
- void add(const std::string&, Protocol*);
+ QPID_BROKER_EXTERN void add(const std::string&, Protocol*);
private:
//name may be useful for descriptive purposes or even for some
//limited manipulation of ordering
diff --git a/qpid/cpp/src/qpid/broker/Queue.cpp b/qpid/cpp/src/qpid/broker/Queue.cpp
index 1d0a8017ef..5a43df44a4 100644
--- a/qpid/cpp/src/qpid/broker/Queue.cpp
+++ b/qpid/cpp/src/qpid/broker/Queue.cpp
@@ -34,6 +34,7 @@
#include "qpid/broker/NullMessageStore.h"
#include "qpid/broker/QueueRegistry.h"
#include "qpid/broker/Selector.h"
+#include "qpid/broker/TransactionObserver.h"
//TODO: get rid of this
#include "qpid/broker/amqp_0_10/MessageTransfer.h"
@@ -167,6 +168,12 @@ void Queue::TxPublish::rollback() throw()
}
}
+void Queue::TxPublish::callObserver(
+ const boost::shared_ptr<TransactionObserver>& observer)
+{
+ observer->enqueue(queue, message);
+}
+
Queue::Queue(const string& _name, const QueueSettings& _settings,
MessageStore* const _store,
Manageable* parent,
@@ -216,6 +223,8 @@ Queue::Queue(const string& _name, const QueueSettings& _settings,
Queue::~Queue()
{
+ if (mgmtObject != 0)
+ mgmtObject->debugStats("destroying");
}
bool Queue::isLocal(const Message& msg)
@@ -270,6 +279,7 @@ void Queue::deliver(Message msg, TxBuffer* txn)
void Queue::deliverTo(Message msg, TxBuffer* txn)
{
if (accept(msg)) {
+ interceptors.record(msg);
if (txn) {
TxOp::shared_ptr op(new TxPublish(msg, shared_from_this()));
txn->enlist(op);
@@ -385,6 +395,7 @@ bool Queue::getNextMessage(Message& m, Consumer::shared_ptr& c)
if (!checkNotDeleted(c)) return false;
QueueListeners::NotificationSet set;
ScopedAutoDelete autodelete(*this);
+ bool messageFound(false);
while (true) {
//TODO: reduce lock scope
Mutex::ScopedLock locker(messageLock);
@@ -426,7 +437,8 @@ bool Queue::getNextMessage(Message& m, Consumer::shared_ptr& c)
QPID_LOG(debug, "Message " << msg->getSequence() << " retrieved from '"
<< name << "'");
m = *msg;
- return true;
+ messageFound = true;
+ break;
} else {
//message(s) are available but consumer hasn't got enough credit
QPID_LOG(debug, "Consumer can't currently accept message from '" << name << "'");
@@ -448,11 +460,12 @@ bool Queue::getNextMessage(Message& m, Consumer::shared_ptr& c)
} else {
QPID_LOG(debug, "No messages to dispatch on queue '" << name << "'");
listeners.addListener(c);
- return false;
+ break;
}
+
}
set.notify();
- return false;
+ return messageFound;
}
void Queue::removeListener(Consumer::shared_ptr c)
@@ -677,17 +690,6 @@ namespace {
return new MessageFilter();
}
- bool reroute(boost::shared_ptr<Exchange> e, const Message& m)
- {
- if (e) {
- DeliverableMessage d(m, 0);
- d.getMessage().clearTrace();
- e->routeWithAlternate(d);
- return true;
- } else {
- return false;
- }
- }
void moveTo(boost::shared_ptr<Queue> q, Message& m)
{
if (q) {
@@ -846,7 +848,6 @@ bool Queue::isEmpty(const Mutex::ScopedLock&) const
*/
bool Queue::enqueue(TransactionContext* ctxt, Message& msg)
{
- interceptors.record(msg);
ScopedUse u(barrier);
if (!u.acquired) return false;
@@ -1684,6 +1685,19 @@ void Queue::setMgmtRedirectState( std::string peer, bool enabled, bool isSrc ) {
mgmtObject->set_redirectSource(isSrc);
}
}
+
+bool Queue::reroute(boost::shared_ptr<Exchange> e, const Message& m)
+{
+ if (e) {
+ DeliverableMessage d(m, 0);
+ d.getMessage().clearTrace();
+ e->routeWithAlternate(d);
+ return true;
+ } else {
+ return false;
+ }
+}
+
Queue::QueueUsers::QueueUsers() : consumers(0), browsers(0), others(0), controller(false) {}
void Queue::QueueUsers::addConsumer() { ++consumers; }
void Queue::QueueUsers::addBrowser() { ++browsers; }
diff --git a/qpid/cpp/src/qpid/broker/Queue.h b/qpid/cpp/src/qpid/broker/Queue.h
index 5598ee5d13..a832b95feb 100644
--- a/qpid/cpp/src/qpid/broker/Queue.h
+++ b/qpid/cpp/src/qpid/broker/Queue.h
@@ -118,6 +118,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
bool prepare(TransactionContext* ctxt) throw();
void commit() throw();
void rollback() throw();
+ void callObserver(const boost::shared_ptr<TransactionObserver>&);
};
/**
@@ -501,6 +502,9 @@ class Queue : public boost::enable_shared_from_this<Queue>,
QPID_BROKER_EXTERN bool isRedirectSource() const { return redirectSource; }
QPID_BROKER_EXTERN void setMgmtRedirectState( std::string peer, bool enabled, bool isSrc );
+ //utility function
+ static bool reroute(boost::shared_ptr<Exchange> e, const Message& m);
+
friend class QueueFactory;
};
}
diff --git a/qpid/cpp/src/qpid/broker/QueueFactory.cpp b/qpid/cpp/src/qpid/broker/QueueFactory.cpp
index 67499c9985..807026ef0d 100644
--- a/qpid/cpp/src/qpid/broker/QueueFactory.cpp
+++ b/qpid/cpp/src/qpid/broker/QueueFactory.cpp
@@ -33,6 +33,7 @@
#include "qpid/broker/PagedQueue.h"
#include "qpid/broker/PriorityQueue.h"
#include "qpid/broker/QueueFlowLimit.h"
+#include "qpid/broker/SelfDestructQueue.h"
#include "qpid/broker/ThresholdAlerts.h"
#include "qpid/broker/FifoDistributor.h"
#include "qpid/log/Statement.h"
@@ -53,6 +54,8 @@ boost::shared_ptr<Queue> QueueFactory::create(const std::string& name, const Que
boost::shared_ptr<Queue> queue;
if (settings.dropMessagesAtLimit) {
queue = boost::shared_ptr<Queue>(new LossyQueue(name, settings, settings.durable ? store : 0, parent, broker));
+ } else if (settings.selfDestructAtLimit) {
+ queue = boost::shared_ptr<Queue>(new SelfDestructQueue(name, settings, settings.durable ? store : 0, parent, broker));
} else if (settings.lvqKey.size()) {
std::auto_ptr<MessageMap> map(new MessageMap(settings.lvqKey));
queue = boost::shared_ptr<Queue>(new Lvq(name, map, settings, settings.durable ? store : 0, parent, broker));
diff --git a/qpid/cpp/src/qpid/broker/QueueRegistry.cpp b/qpid/cpp/src/qpid/broker/QueueRegistry.cpp
index 13f9bbe23c..606a8cceae 100644
--- a/qpid/cpp/src/qpid/broker/QueueRegistry.cpp
+++ b/qpid/cpp/src/qpid/broker/QueueRegistry.cpp
@@ -59,8 +59,8 @@ QueueRegistry::declare(const string& name, const QueueSettings& settings,
QueueMap::iterator i = queues.find(name);
if (i == queues.end()) {
Queue::shared_ptr queue = create(name, settings);
- // Allow ConfigurationObserver to modify settings before storing the message.
- if (getBroker()) getBroker()->getConfigurationObservers().queueCreate(queue);
+ // Allow BrokerObserver to modify settings before storing the message.
+ if (getBroker()) getBroker()->getBrokerObservers().queueCreate(queue);
//Move this to factory also?
if (alternate)
queue->setAlternateExchange(alternate);//need to do this *before* create
@@ -100,7 +100,7 @@ void QueueRegistry::destroy(
// NOTE: queueDestroy and raiseEvent must be called with the
// lock held in order to ensure events are generated
// in the correct order.
- getBroker()->getConfigurationObservers().queueDestroy(q);
+ getBroker()->getBrokerObservers().queueDestroy(q);
if (getBroker()->getManagementAgent())
getBroker()->getManagementAgent()->raiseEvent(
_qmf::EventQueueDelete(connectionId, userId, name));
@@ -121,7 +121,9 @@ Queue::shared_ptr QueueRegistry::find(const string& name){
Queue::shared_ptr QueueRegistry::get(const string& name) {
Queue::shared_ptr q = find(name);
- if (!q) throw framing::NotFoundException(QPID_MSG("Queue not found: "<<name));
+ if (!q) {
+ throw framing::NotFoundException(QPID_MSG("Queue not found: "<<name));
+ }
return q;
}
diff --git a/qpid/cpp/src/qpid/broker/QueueSettings.cpp b/qpid/cpp/src/qpid/broker/QueueSettings.cpp
index fd90d11d76..c505217dbb 100644
--- a/qpid/cpp/src/qpid/broker/QueueSettings.cpp
+++ b/qpid/cpp/src/qpid/broker/QueueSettings.cpp
@@ -38,6 +38,7 @@ const std::string MAX_FILE_SIZE("qpid.file_size");
const std::string POLICY_TYPE("qpid.policy_type");
const std::string POLICY_TYPE_REJECT("reject");
const std::string POLICY_TYPE_RING("ring");
+const std::string POLICY_TYPE_SELF_DESTRUCT("self-destruct");
const std::string NO_LOCAL("no-local");
const std::string BROWSE_ONLY("qpid.browse-only");
const std::string TRACE_ID("qpid.trace.id");
@@ -96,6 +97,7 @@ QueueSettings::QueueSettings(bool d, bool a) :
shareGroups(false),
addTimestamp(false),
dropMessagesAtLimit(false),
+ selfDestructAtLimit(false),
paging(false),
maxPages(0),
pageFactor(0),
@@ -120,6 +122,9 @@ bool QueueSettings::handle(const std::string& key, const qpid::types::Variant& v
if (value.getString() == POLICY_TYPE_RING) {
dropMessagesAtLimit = true;
return true;
+ } else if (value.getString() == POLICY_TYPE_SELF_DESTRUCT) {
+ selfDestructAtLimit = true;
+ return true;
} else if (value.getString() == POLICY_TYPE_REJECT) {
//do nothing, thats the default
return true;
@@ -168,6 +173,7 @@ bool QueueSettings::handle(const std::string& key, const qpid::types::Variant& v
return true;
} else if (key == AUTO_DELETE_TIMEOUT) {
autoDeleteDelay = value;
+ if (autoDeleteDelay) autodelete = true;
return true;
} else if (key == QueueFlowLimit::flowStopCountKey) {
flowStop.setCount(value);
diff --git a/qpid/cpp/src/qpid/broker/QueueSettings.h b/qpid/cpp/src/qpid/broker/QueueSettings.h
index 166445be18..8d72115e18 100644
--- a/qpid/cpp/src/qpid/broker/QueueSettings.h
+++ b/qpid/cpp/src/qpid/broker/QueueSettings.h
@@ -70,6 +70,7 @@ struct QueueSettings
QueueDepth maxDepth;
bool dropMessagesAtLimit;//aka ring queue policy
+ bool selfDestructAtLimit;
//PagedQueue:
bool paging;
diff --git a/qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h b/qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h
index 7cef5fd265..900eae4e1e 100644
--- a/qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h
+++ b/qpid/cpp/src/qpid/broker/RecoverableMessageImpl.h
@@ -33,7 +33,7 @@ class RecoverableMessageImpl : public RecoverableMessage
{
Message msg;
public:
- RecoverableMessageImpl(const Message& _msg);
+ QPID_BROKER_EXTERN RecoverableMessageImpl(const Message& _msg);
~RecoverableMessageImpl() {};
void setPersistenceId(uint64_t id);
void setRedelivered();
diff --git a/qpid/cpp/src/qpid/broker/RecoveredDequeue.h b/qpid/cpp/src/qpid/broker/RecoveredDequeue.h
index 87f768eefd..b85919975c 100644
--- a/qpid/cpp/src/qpid/broker/RecoveredDequeue.h
+++ b/qpid/cpp/src/qpid/broker/RecoveredDequeue.h
@@ -41,6 +41,8 @@ namespace qpid {
virtual bool prepare(TransactionContext* ctxt) throw();
virtual void commit() throw();
virtual void rollback() throw();
+ // TODO aconway 2013-07-08: revisit
+ virtual void callObserver(const boost::shared_ptr<TransactionObserver>&) {}
virtual ~RecoveredDequeue(){}
boost::shared_ptr<Queue> getQueue() const { return queue; }
diff --git a/qpid/cpp/src/qpid/broker/RecoveredEnqueue.h b/qpid/cpp/src/qpid/broker/RecoveredEnqueue.h
index d1f8e1106c..01c350af92 100644
--- a/qpid/cpp/src/qpid/broker/RecoveredEnqueue.h
+++ b/qpid/cpp/src/qpid/broker/RecoveredEnqueue.h
@@ -41,6 +41,8 @@ class RecoveredEnqueue : public TxOp{
virtual bool prepare(TransactionContext* ctxt) throw();
virtual void commit() throw();
virtual void rollback() throw();
+ // TODO aconway 2013-07-08: revisit
+ virtual void callObserver(const boost::shared_ptr<TransactionObserver>&) {}
virtual ~RecoveredEnqueue(){}
boost::shared_ptr<Queue> getQueue() const { return queue; }
diff --git a/qpid/cpp/src/qpid/broker/Selector.h b/qpid/cpp/src/qpid/broker/Selector.h
index 1d98f6ea8f..0e151ecd0e 100644
--- a/qpid/cpp/src/qpid/broker/Selector.h
+++ b/qpid/cpp/src/qpid/broker/Selector.h
@@ -64,7 +64,7 @@ public:
* @param msg message to filter against selector
* @return true if msg meets the selector specification
*/
- bool filter(const Message& msg);
+ QPID_BROKER_EXTERN bool filter(const Message& msg);
};
/**
diff --git a/qpid/cpp/src/qpid/broker/SelfDestructQueue.cpp b/qpid/cpp/src/qpid/broker/SelfDestructQueue.cpp
new file mode 100644
index 0000000000..f8b26a62ad
--- /dev/null
+++ b/qpid/cpp/src/qpid/broker/SelfDestructQueue.cpp
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "SelfDestructQueue.h"
+#include "AclModule.h"
+#include "Broker.h"
+#include "QueueDepth.h"
+#include "qpid/log/Statement.h"
+
+namespace qpid {
+namespace broker {
+SelfDestructQueue::SelfDestructQueue(const std::string& n, const QueueSettings& s, MessageStore* const ms, management::Manageable* p, Broker* b) : Queue(n, s, ms, p, b)
+{
+ QPID_LOG_CAT(debug, model, "Self-destruct queue created: " << name);
+}
+bool SelfDestructQueue::checkDepth(const QueueDepth& increment, const Message&)
+{
+ if (settings.maxDepth && (settings.maxDepth - current < increment)) {
+ broker->getQueues().destroy(name);
+ if (broker->getAcl())
+ broker->getAcl()->recordDestroyQueue(name);
+ QPID_LOG_CAT(debug, model, "Queue " << name << " deleted itself due to reaching limit: " << current << " (policy is " << settings.maxDepth << ")");
+ destroyed();
+ }
+ current += increment;
+ return true;
+}
+}} // namespace qpid::broker
diff --git a/qpid/cpp/src/qpid/console/SequenceManager.cpp b/qpid/cpp/src/qpid/broker/SelfDestructQueue.h
index 86ea829749..110eb1dcf7 100644
--- a/qpid/cpp/src/qpid/console/SequenceManager.cpp
+++ b/qpid/cpp/src/qpid/broker/SelfDestructQueue.h
@@ -1,3 +1,6 @@
+#ifndef QPID_BROKER_SELFDESTRUCTQUEUE_H
+#define QPID_BROKER_SELFDESTRUCTQUEUE_H
+
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -7,9 +10,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,31 +21,25 @@
* under the License.
*
*/
+#include "qpid/broker/Queue.h"
-#include "qpid/console/SequenceManager.h"
-
-using namespace qpid::console;
-using namespace qpid::sys;
-using std::string;
-using std::cout;
-using std::endl;
+namespace qpid {
+namespace broker {
-uint32_t SequenceManager::reserve(const std::string& context)
-{
- Mutex::ScopedLock l(lock);
- uint32_t result = sequence++;
- pending[result] = context;
- return result;
-}
-
-std::string SequenceManager::release(uint32_t seq)
+/**
+ * Deletes itself when breaching specified maximum depth (useful as
+ * subscription queue for consumers that should be ejecetd from topic
+ * when they can't keep up).
+ */
+class SelfDestructQueue : public Queue
{
- Mutex::ScopedLock l(lock);
- std::map<uint32_t, string>::iterator iter = pending.find(seq);
- if (iter == pending.end())
- return string();
- string result(iter->second);
- pending.erase(iter);
- return result;
-}
+ public:
+ public:
+ SelfDestructQueue(const std::string&, const QueueSettings&, MessageStore* const, management::Manageable*, Broker*);
+ bool checkDepth(const QueueDepth& increment, const Message&);
+ private:
+ private:
+};
+}} // namespace qpid::broker
+#endif /*!QPID_BROKER_SELFDESTRUCTQUEUE_H*/
diff --git a/qpid/cpp/src/qpid/broker/SemanticState.cpp b/qpid/cpp/src/qpid/broker/SemanticState.cpp
index 4570e3bd87..18c29c09f9 100644
--- a/qpid/cpp/src/qpid/broker/SemanticState.cpp
+++ b/qpid/cpp/src/qpid/broker/SemanticState.cpp
@@ -31,6 +31,7 @@
#include "qpid/broker/Selector.h"
#include "qpid/broker/SessionContext.h"
#include "qpid/broker/SessionOutputException.h"
+#include "qpid/broker/TransactionObserver.h"
#include "qpid/broker/TxAccept.h"
#include "qpid/broker/amqp_0_10/MessageTransfer.h"
#include "qpid/framing/reply_exceptions.h"
@@ -65,6 +66,7 @@ namespace broker {
using namespace std;
using boost::intrusive_ptr;
+using boost::shared_ptr;
using boost::bind;
using namespace qpid::broker;
using namespace qpid::framing;
@@ -165,13 +167,15 @@ bool SemanticState::cancel(const string& tag)
void SemanticState::startTx()
{
txBuffer = TxBuffer::shared_ptr(new TxBuffer());
+ session.getBroker().getBrokerObservers().startTx(txBuffer);
+ session.startTx(); //just to update statistics
}
void SemanticState::commit(MessageStore* const store)
{
if (!txBuffer) throw
CommandInvalidException(QPID_MSG("Session has not been selected for use with transactions"));
-
+ session.commitTx(); //just to update statistics
TxOp::shared_ptr txAck(static_cast<TxOp*>(new TxAccept(accumulatedAck, unacked)));
txBuffer->enlist(txAck);
if (txBuffer->commitLocal(store)) {
@@ -185,7 +189,7 @@ void SemanticState::rollback()
{
if (!txBuffer)
throw CommandInvalidException(QPID_MSG("Session has not been selected for use with transactions"));
-
+ session.rollbackTx(); //just to update statistics
txBuffer->rollback();
accumulatedAck.clear();
}
@@ -202,6 +206,7 @@ void SemanticState::startDtx(const std::string& xid, DtxManager& mgr, bool join)
}
dtxBuffer.reset(new DtxBuffer(xid));
txBuffer = dtxBuffer;
+ session.getBroker().getBrokerObservers().startDtx(dtxBuffer);
if (join) {
mgr.join(xid, dtxBuffer);
} else {
@@ -432,8 +437,10 @@ bool SemanticStateConsumerImpl::checkCredit(const Message& msg)
SemanticStateConsumerImpl::~SemanticStateConsumerImpl()
{
- if (mgmtObject != 0)
+ if (mgmtObject != 0) {
+ mgmtObject->debugStats("destroying");
mgmtObject->resourceDestroy ();
+ }
}
void SemanticState::disable(ConsumerImpl::shared_ptr c)
@@ -658,9 +665,7 @@ Queue::shared_ptr SemanticState::getQueue(const string& name) const {
if (name.empty()) {
throw NotAllowedException(QPID_MSG("No queue name specified."));
} else {
- queue = session.getBroker().getQueues().find(name);
- if (!queue)
- throw NotFoundException(QPID_MSG("Queue not found: "<<name));
+ queue = session.getBroker().getQueues().get(name);
}
return queue;
}
@@ -767,7 +772,6 @@ void SemanticState::accepted(const SequenceSet& commands) {
TxOp::shared_ptr txAck(new DtxAck(accumulatedAck, unacked));
accumulatedAck.clear();
dtxBuffer->enlist(txAck);
-
//mark the relevant messages as 'ended' in unacked
//if the messages are already completed, they can be
//removed from the record
diff --git a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp b/qpid/cpp/src/qpid/broker/SessionAdapter.cpp
index 0124e88832..64e3fe1b8a 100644
--- a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp
+++ b/qpid/cpp/src/qpid/broker/SessionAdapter.cpp
@@ -685,9 +685,7 @@ Queue::shared_ptr SessionAdapter::HandlerHelper::getQueue(const string& name) co
if (name.empty()) {
throw framing::IllegalArgumentException(QPID_MSG("No queue name specified."));
} else {
- queue = session.getBroker().getQueues().find(name);
- if (!queue)
- throw framing::NotFoundException(QPID_MSG("Queue not found: "<<name));
+ queue = session.getBroker().getQueues().get(name);
}
return queue;
}
diff --git a/qpid/cpp/src/qpid/broker/SessionHandler.cpp b/qpid/cpp/src/qpid/broker/SessionHandler.cpp
index 93977c8a6e..ff7693e93a 100644
--- a/qpid/cpp/src/qpid/broker/SessionHandler.cpp
+++ b/qpid/cpp/src/qpid/broker/SessionHandler.cpp
@@ -39,7 +39,11 @@ SessionHandler::SessionHandler(amqp_0_10::Connection& c, ChannelId ch)
proxy(out)
{}
-SessionHandler::~SessionHandler() {}
+SessionHandler::~SessionHandler()
+{
+ if (session.get())
+ connection.getBroker().getSessionManager().forget(session->getId());
+}
void SessionHandler::connectionException(
framing::connection::CloseCode code, const std::string& msg)
diff --git a/qpid/cpp/src/qpid/broker/SessionState.cpp b/qpid/cpp/src/qpid/broker/SessionState.cpp
index 421dc008a9..3995eb85dc 100644
--- a/qpid/cpp/src/qpid/broker/SessionState.cpp
+++ b/qpid/cpp/src/qpid/broker/SessionState.cpp
@@ -79,7 +79,27 @@ void SessionState::addManagementObject() {
}
}
+void SessionState::startTx() {
+ if (mgmtObject) { mgmtObject->inc_TxnStarts(); }
+}
+
+void SessionState::commitTx() {
+ if (mgmtObject) {
+ mgmtObject->inc_TxnCommits();
+ mgmtObject->inc_TxnCount();
+ }
+}
+
+void SessionState::rollbackTx() {
+ if (mgmtObject) {
+ mgmtObject->inc_TxnRejects();
+ mgmtObject->inc_TxnCount();
+ }
+}
+
SessionState::~SessionState() {
+ if (mgmtObject != 0)
+ mgmtObject->debugStats("destroying");
asyncCommandCompleter->cancel();
semanticState.closed();
if (mgmtObject != 0)
diff --git a/qpid/cpp/src/qpid/broker/SessionState.h b/qpid/cpp/src/qpid/broker/SessionState.h
index daf3767969..500a211a6f 100644
--- a/qpid/cpp/src/qpid/broker/SessionState.h
+++ b/qpid/cpp/src/qpid/broker/SessionState.h
@@ -127,6 +127,11 @@ class SessionState : public qpid::SessionState,
// belonging to inter-broker bridges
void addManagementObject();
+ // transaction-related methods just to update statistics
+ void startTx();
+ void commitTx();
+ void rollbackTx();
+
private:
void handleCommand(framing::AMQMethodBody* method, const framing::SequenceNumber& id);
void handleContent(framing::AMQFrame& frame, const framing::SequenceNumber& id);
diff --git a/qpid/cpp/src/qpid/broker/System.cpp b/qpid/cpp/src/qpid/broker/System.cpp
index 8d54427fdc..f3b6f96d0c 100644
--- a/qpid/cpp/src/qpid/broker/System.cpp
+++ b/qpid/cpp/src/qpid/broker/System.cpp
@@ -80,3 +80,9 @@ System::System (string _dataDir, Broker* broker)
}
}
+System::~System ()
+{
+ if (mgmtObject != 0)
+ mgmtObject->debugStats("destroying");
+}
+
diff --git a/qpid/cpp/src/qpid/broker/System.h b/qpid/cpp/src/qpid/broker/System.h
index 52643fb2d5..4a4af275c4 100644
--- a/qpid/cpp/src/qpid/broker/System.h
+++ b/qpid/cpp/src/qpid/broker/System.h
@@ -45,6 +45,8 @@ class System : public management::Manageable
System (std::string _dataDir, Broker* broker = 0);
+ ~System ();
+
management::ManagementObject::shared_ptr GetManagementObject(void) const
{ return mgmtObject; }
diff --git a/qpid/cpp/src/qpid/broker/TopicExchange.cpp b/qpid/cpp/src/qpid/broker/TopicExchange.cpp
index d49464b4e1..6a081bf65f 100644
--- a/qpid/cpp/src/qpid/broker/TopicExchange.cpp
+++ b/qpid/cpp/src/qpid/broker/TopicExchange.cpp
@@ -333,7 +333,10 @@ bool TopicExchange::isBound(Queue::shared_ptr queue, const string* const routing
return false;
}
-TopicExchange::~TopicExchange() {}
+TopicExchange::~TopicExchange() {
+ if (mgmtExchange != 0)
+ mgmtExchange->debugStats("destroying");
+}
const std::string TopicExchange::typeName("topic");
diff --git a/qpid/cpp/src/qpid/broker/TopicExchange.h b/qpid/cpp/src/qpid/broker/TopicExchange.h
index 46871a1c6b..b8b67bdafa 100644
--- a/qpid/cpp/src/qpid/broker/TopicExchange.h
+++ b/qpid/cpp/src/qpid/broker/TopicExchange.h
@@ -81,7 +81,7 @@ class TopicExchange : public virtual Exchange {
};
public:
- static const std::string typeName;
+ QPID_BROKER_EXTERN static const std::string typeName;
static QPID_BROKER_EXTERN std::string normalize(const std::string& pattern);
diff --git a/qpid/cpp/src/qpid/broker/TransactionObserver.h b/qpid/cpp/src/qpid/broker/TransactionObserver.h
new file mode 100644
index 0000000000..5333d7b8d6
--- /dev/null
+++ b/qpid/cpp/src/qpid/broker/TransactionObserver.h
@@ -0,0 +1,82 @@
+#ifndef QPID_BROKER_TRANSACTIONOBSERVER_H
+#define QPID_BROKER_TRANSACTIONOBSERVER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+
+#include "DeliveryRecord.h"
+#include <boost/shared_ptr.hpp>
+
+namespace qpid {
+
+namespace framing {
+class SequenceSet;
+}
+
+namespace broker {
+class Queue;
+class Message;
+class TxBuffer;
+class DtxBuffer;
+
+/**
+ * Interface for intercepting events in a transaction.
+ */
+class TransactionObserver {
+ public:
+ typedef boost::shared_ptr<Queue> QueuePtr;
+ typedef framing::SequenceNumber SequenceNumber;
+
+ virtual ~TransactionObserver() {}
+
+ /** Message enqueued in the transaction. */
+ virtual void enqueue(const QueuePtr&, const Message&) = 0;
+
+ /**
+ * Message is dequeued in the transaction (it was accepted by a consumer.)
+ *@param queuePosition: Sequence number of message on queue.
+ *@param replicationId: Replication sequence number, may be different.
+ */
+ virtual void dequeue(const QueuePtr& queue,
+ SequenceNumber queueSeq,
+ SequenceNumber replicationSeq) = 0;
+
+ virtual bool prepare() = 0;
+ virtual void commit() = 0;
+ virtual void rollback() = 0;
+};
+
+/**
+ * No-op TransactionObserver.
+ */
+class NullTransactionObserver : public TransactionObserver {
+ public:
+ void enqueue(const QueuePtr&, const Message&) {}
+ void dequeue(const QueuePtr&, SequenceNumber, SequenceNumber) {}
+ bool prepare() { return true; }
+ void commit() {}
+ void rollback() {}
+};
+
+}} // namespace qpid::broker
+
+#endif /*!QPID_BROKER_TRANSACTIONOBSERVER_H*/
diff --git a/qpid/cpp/src/qpid/broker/TxAccept.cpp b/qpid/cpp/src/qpid/broker/TxAccept.cpp
index 928ac12c10..ee30dff957 100644
--- a/qpid/cpp/src/qpid/broker/TxAccept.cpp
+++ b/qpid/cpp/src/qpid/broker/TxAccept.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -19,6 +19,8 @@
*
*/
#include "qpid/broker/TxAccept.h"
+#include "qpid/broker/TransactionObserver.h"
+#include "qpid/broker/Queue.h"
#include "qpid/log/Statement.h"
using std::bind1st;
@@ -28,54 +30,23 @@ using namespace qpid::broker;
using qpid::framing::SequenceSet;
using qpid::framing::SequenceNumber;
-TxAccept::RangeOp::RangeOp(const AckRange& r) : range(r) {}
-void TxAccept::RangeOp::prepare(TransactionContext* ctxt)
+TxAccept::TxAccept(const SequenceSet& _acked, DeliveryRecords& _unacked) :
+ acked(_acked), unacked(_unacked)
{
- for_each(range.start, range.end, bind(&DeliveryRecord::dequeue, _1, ctxt));
+ for(SequenceSet::RangeIterator i = acked.rangesBegin(); i != acked.rangesEnd(); ++i)
+ ranges.push_back(DeliveryRecord::findRange(unacked, i->first(), i->last()));
}
-void TxAccept::RangeOp::commit()
-{
- for_each(range.start, range.end, bind(&DeliveryRecord::committed, _1));
- for_each(range.start, range.end, bind(&DeliveryRecord::setEnded, _1));
-}
-
-TxAccept::RangeOps::RangeOps(DeliveryRecords& u) : unacked(u) {}
-
-void TxAccept::RangeOps::operator()(SequenceNumber start, SequenceNumber end)
-{
- ranges.push_back(RangeOp(DeliveryRecord::findRange(unacked, start, end)));
-}
-
-void TxAccept::RangeOps::prepare(TransactionContext* ctxt)
-{
- std::for_each(ranges.begin(), ranges.end(), bind(&RangeOp::prepare, _1, ctxt));
-}
-
-void TxAccept::RangeOps::commit()
-{
- std::for_each(ranges.begin(), ranges.end(), bind(&RangeOp::commit, _1));
- //now remove if isRedundant():
- if (!ranges.empty()) {
- DeliveryRecords::iterator begin = ranges.front().range.start;
- DeliveryRecords::iterator end = ranges.back().range.end;
- DeliveryRecords::iterator removed = remove_if(begin, end, mem_fun_ref(&DeliveryRecord::isRedundant));
- unacked.erase(removed, end);
- }
-}
-
-TxAccept::TxAccept(const SequenceSet& _acked, DeliveryRecords& _unacked) :
- acked(_acked), unacked(_unacked), ops(unacked)
-{
- //populate the ops
- acked.for_each(ops);
+void TxAccept::each(boost::function<void(DeliveryRecord&)> f) {
+ for(AckRanges::iterator i = ranges.begin(); i != ranges.end(); ++i)
+ for_each(i->start, i->end, f);
}
bool TxAccept::prepare(TransactionContext* ctxt) throw()
{
try{
- ops.prepare(ctxt);
+ each(bind(&DeliveryRecord::dequeue, _1, ctxt));
return true;
}catch(const std::exception& e){
QPID_LOG(error, "Failed to prepare: " << e.what());
@@ -86,10 +57,19 @@ bool TxAccept::prepare(TransactionContext* ctxt) throw()
}
}
-void TxAccept::commit() throw()
+void TxAccept::commit() throw()
{
try {
- ops.commit();
+ each(bind(&DeliveryRecord::committed, _1));
+ each(bind(&DeliveryRecord::setEnded, _1));
+ //now remove if isRedundant():
+ if (!ranges.empty()) {
+ DeliveryRecords::iterator begin = ranges.front().start;
+ DeliveryRecords::iterator end = ranges.back().end;
+ DeliveryRecords::iterator removed =
+ remove_if(begin, end, mem_fun_ref(&DeliveryRecord::isRedundant));
+ unacked.erase(removed, end);
+ }
} catch (const std::exception& e) {
QPID_LOG(error, "Failed to commit: " << e.what());
} catch(...) {
@@ -98,3 +78,13 @@ void TxAccept::commit() throw()
}
void TxAccept::rollback() throw() {}
+
+namespace {
+void callObserverDR(boost::shared_ptr<TransactionObserver> observer, DeliveryRecord& dr) {
+ observer->dequeue(dr.getQueue(), dr.getMessageId(), dr.getReplicationId());
+}
+} // namespace
+
+void TxAccept::callObserver(const ObserverPtr& observer) {
+ each(boost::bind(&callObserverDR, observer, _1));
+}
diff --git a/qpid/cpp/src/qpid/broker/TxAccept.h b/qpid/cpp/src/qpid/broker/TxAccept.h
index daf192285a..b4d55155a8 100644
--- a/qpid/cpp/src/qpid/broker/TxAccept.h
+++ b/qpid/cpp/src/qpid/broker/TxAccept.h
@@ -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,58 +21,45 @@
#ifndef _TxAccept_
#define _TxAccept_
-#include <algorithm>
-#include <functional>
-#include <list>
#include "qpid/framing/SequenceSet.h"
+#include "qpid/broker/BrokerImportExport.h"
#include "qpid/broker/DeliveryRecord.h"
#include "qpid/broker/TxOp.h"
+#include <boost/function.hpp>
+#include <algorithm>
+#include <functional>
+#include <list>
namespace qpid {
- namespace broker {
- /**
- * Defines the transactional behaviour for accepts received by
- * a transactional channel.
- */
- class TxAccept : public TxOp {
- struct RangeOp
- {
- AckRange range;
-
- RangeOp(const AckRange& r);
- void prepare(TransactionContext* ctxt);
- void commit();
- };
-
- struct RangeOps
- {
- std::vector<RangeOp> ranges;
- DeliveryRecords& unacked;
-
- RangeOps(DeliveryRecords& u);
+namespace broker {
+/**
+ * Defines the transactional behaviour for accepts received by
+ * a transactional channel.
+ */
+class TxAccept : public TxOp {
+ typedef std::vector<AckRange> AckRanges;
+ typedef boost::shared_ptr<TransactionObserver> ObserverPtr;
- void operator()(framing::SequenceNumber start, framing::SequenceNumber end);
- void prepare(TransactionContext* ctxt);
- void commit();
- };
+ void each(boost::function<void(DeliveryRecord&)>);
- framing::SequenceSet acked;
- DeliveryRecords& unacked;
- RangeOps ops;
+ framing::SequenceSet acked;
+ DeliveryRecords& unacked;
+ AckRanges ranges;
- public:
- /**
- * @param acked a representation of the accumulation of
- * acks received
- * @param unacked the record of delivered messages
- */
- TxAccept(const framing::SequenceSet& acked, DeliveryRecords& unacked);
- virtual bool prepare(TransactionContext* ctxt) throw();
- virtual void commit() throw();
- virtual void rollback() throw();
- virtual ~TxAccept(){}
- };
- }
+ public:
+ /**
+ * @param acked a representation of the accumulation of
+ * acks received
+ * @param unacked the record of delivered messages
+ */
+ QPID_BROKER_EXTERN TxAccept(const framing::SequenceSet& acked, DeliveryRecords& unacked);
+ virtual bool prepare(TransactionContext* ctxt) throw();
+ virtual void commit() throw();
+ virtual void rollback() throw();
+ virtual void callObserver(const ObserverPtr&);
+ virtual ~TxAccept(){}
+};
+}
}
diff --git a/qpid/cpp/src/qpid/broker/TxBuffer.cpp b/qpid/cpp/src/qpid/broker/TxBuffer.cpp
index 7663cc525f..a8df4fb214 100644
--- a/qpid/cpp/src/qpid/broker/TxBuffer.cpp
+++ b/qpid/cpp/src/qpid/broker/TxBuffer.cpp
@@ -19,6 +19,7 @@
*
*/
#include "qpid/broker/TxBuffer.h"
+#include "qpid/broker/TransactionObserver.h"
#include "qpid/log/Statement.h"
#include <boost/mem_fn.hpp>
@@ -26,8 +27,11 @@
using boost::mem_fn;
using namespace qpid::broker;
+TxBuffer::TxBuffer() : observer(new NullTransactionObserver) {}
+
bool TxBuffer::prepare(TransactionContext* const ctxt)
{
+ if (!observer->prepare()) return false;
for(op_iterator i = ops.begin(); i != ops.end(); i++){
if(!(*i)->prepare(ctxt)){
return false;
@@ -38,18 +42,21 @@ bool TxBuffer::prepare(TransactionContext* const ctxt)
void TxBuffer::commit()
{
+ observer->commit();
std::for_each(ops.begin(), ops.end(), mem_fn(&TxOp::commit));
ops.clear();
}
void TxBuffer::rollback()
{
+ observer->rollback();
std::for_each(ops.begin(), ops.end(), mem_fn(&TxOp::rollback));
ops.clear();
}
void TxBuffer::enlist(TxOp::shared_ptr op)
{
+ op->callObserver(observer);
ops.push_back(op);
}
diff --git a/qpid/cpp/src/qpid/broker/TxBuffer.h b/qpid/cpp/src/qpid/broker/TxBuffer.h
index 22e2f06be1..4570c570a2 100644
--- a/qpid/cpp/src/qpid/broker/TxBuffer.h
+++ b/qpid/cpp/src/qpid/broker/TxBuffer.h
@@ -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,21 +34,21 @@
* transaction. This work can be committed or rolled back. Committing
* is a two-stage process: first all the operations should be
* prepared, then if that succeeds they can be committed.
- *
+ *
* In the 2pc case, a successful prepare may be followed by either a
* commit or a rollback.
- *
+ *
* Atomicity of prepare is ensured by using a lower level
* transactional facility. This saves explicitly rolling back all the
* successfully prepared ops when one of them fails. i.e. we do not
* use 2pc internally, we instead ensure that prepare is atomic at a
* lower level. This makes individual prepare operations easier to
* code.
- *
+ *
* Transactions on a messaging broker effect three types of 'action':
* (1) updates to persistent storage (2) updates to transient storage
* or cached data (3) network writes.
- *
+ *
* Of these, (1) should always occur atomically during prepare to
* ensure that if the broker crashes while a transaction is being
* completed the persistent state (which is all that then remains) is
@@ -58,59 +58,74 @@
* TransactionalStore in use.
*/
namespace qpid {
- namespace broker {
- class TxBuffer{
- typedef std::vector<TxOp::shared_ptr>::iterator op_iterator;
- std::vector<TxOp::shared_ptr> ops;
- protected:
-
- public:
- typedef boost::shared_ptr<TxBuffer> shared_ptr;
- /**
- * Adds an operation to the transaction.
- */
- QPID_BROKER_EXTERN void enlist(TxOp::shared_ptr op);
-
- /**
- * Requests that all ops are prepared. This should
- * primarily involve making sure that a persistent record
- * of the operations is stored where necessary.
- *
- * Once prepared, a transaction can be committed (or in
- * the 2pc case, rolled back).
- *
- * @returns true if all the operations prepared
- * successfully, false if not.
- */
- QPID_BROKER_EXTERN bool prepare(TransactionContext* const ctxt);
-
- /**
- * Signals that the ops all prepared successfully and can
- * now commit, i.e. the operation can now be fully carried
- * out.
- *
- * Should only be called after a call to prepare() returns
- * true.
- */
- QPID_BROKER_EXTERN void commit();
-
- /**
- * Signals that all ops can be rolled back.
- *
- * Should only be called either after a call to prepare()
- * returns true (2pc) or instead of a prepare call
- * ('server-local')
- */
- QPID_BROKER_EXTERN void rollback();
-
- /**
- * Helper method for managing the process of server local
- * commit
- */
- QPID_BROKER_EXTERN bool commitLocal(TransactionalStore* const store);
- };
+
+namespace broker {
+class TransactionObserver;
+
+class TxBuffer {
+ private:
+ typedef std::vector<TxOp::shared_ptr>::iterator op_iterator;
+ std::vector<TxOp::shared_ptr> ops;
+ boost::shared_ptr<TransactionObserver> observer;
+
+ public:
+ typedef boost::shared_ptr<TxBuffer> shared_ptr;
+
+ QPID_BROKER_EXTERN TxBuffer();
+
+ /**
+ * Adds an operation to the transaction.
+ */
+ QPID_BROKER_EXTERN void enlist(TxOp::shared_ptr op);
+
+ /**
+ * Requests that all ops are prepared. This should
+ * primarily involve making sure that a persistent record
+ * of the operations is stored where necessary.
+ *
+ * Once prepared, a transaction can be committed (or in
+ * the 2pc case, rolled back).
+ *
+ * @returns true if all the operations prepared
+ * successfully, false if not.
+ */
+ QPID_BROKER_EXTERN bool prepare(TransactionContext* const ctxt);
+
+ /**
+ * Signals that the ops all prepared successfully and can
+ * now commit, i.e. the operation can now be fully carried
+ * out.
+ *
+ * Should only be called after a call to prepare() returns
+ * true.
+ */
+ QPID_BROKER_EXTERN void commit();
+
+ /**
+ * Signals that all ops can be rolled back.
+ *
+ * Should only be called either after a call to prepare()
+ * returns true (2pc) or instead of a prepare call
+ * ('server-local')
+ */
+ QPID_BROKER_EXTERN void rollback();
+
+ /**
+ * Helper method for managing the process of server local
+ * commit
+ */
+ QPID_BROKER_EXTERN bool commitLocal(TransactionalStore* const store);
+
+
+ QPID_BROKER_EXTERN void setObserver(boost::shared_ptr<TransactionObserver> o) {
+ observer = o;
+ }
+
+ QPID_BROKER_EXTERN boost::shared_ptr<TransactionObserver> getObserver() const {
+ return observer;
}
-}
+};
+}} // namespace qpid::broker
#endif
diff --git a/qpid/cpp/src/qpid/broker/TxOp.h b/qpid/cpp/src/qpid/broker/TxOp.h
index 775efc92f7..00303eb27c 100644
--- a/qpid/cpp/src/qpid/broker/TxOp.h
+++ b/qpid/cpp/src/qpid/broker/TxOp.h
@@ -25,17 +25,19 @@
#include <boost/shared_ptr.hpp>
namespace qpid {
- namespace broker {
+namespace broker {
+class TransactionObserver;
- class TxOp{
- public:
- typedef boost::shared_ptr<TxOp> shared_ptr;
+class TxOp{
+ public:
+ typedef boost::shared_ptr<TxOp> shared_ptr;
- virtual bool prepare(TransactionContext*) throw() = 0;
- virtual void commit() throw() = 0;
- virtual void rollback() throw() = 0;
- virtual ~TxOp(){}
- };
+ virtual bool prepare(TransactionContext*) throw() = 0;
+ virtual void commit() throw() = 0;
+ virtual void rollback() throw() = 0;
+ virtual void callObserver(const boost::shared_ptr<TransactionObserver>&) = 0;
+ virtual ~TxOp(){}
+};
}} // namespace qpid::broker
diff --git a/qpid/cpp/src/qpid/broker/Vhost.cpp b/qpid/cpp/src/qpid/broker/Vhost.cpp
index e72118b570..8fd88601f5 100644
--- a/qpid/cpp/src/qpid/broker/Vhost.cpp
+++ b/qpid/cpp/src/qpid/broker/Vhost.cpp
@@ -43,6 +43,11 @@ Vhost::Vhost (qpid::management::Manageable* parentBroker, Broker* broker)
}
}
+Vhost::~Vhost () {
+ if (mgmtObject != 0)
+ mgmtObject->debugStats("destroying");
+}
+
void Vhost::setFederationTag(const std::string& tag)
{
mgmtObject->set_federationTag(tag);
diff --git a/qpid/cpp/src/qpid/broker/Vhost.h b/qpid/cpp/src/qpid/broker/Vhost.h
index 599b821870..06a11db8ea 100644
--- a/qpid/cpp/src/qpid/broker/Vhost.h
+++ b/qpid/cpp/src/qpid/broker/Vhost.h
@@ -40,6 +40,8 @@ class Vhost : public management::Manageable
Vhost (management::Manageable* parentBroker, Broker* broker = 0);
+ ~Vhost ();
+
management::ManagementObject::shared_ptr GetManagementObject (void) const
{ return mgmtObject; }
void setFederationTag(const std::string& tag);
diff --git a/qpid/cpp/src/qpid/broker/amqp/Connection.cpp b/qpid/cpp/src/qpid/broker/amqp/Connection.cpp
index 2cb0994138..d4221246c5 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Connection.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Connection.cpp
@@ -182,12 +182,9 @@ void Connection::open()
void Connection::readPeerProperties()
{
- /**
- * TODO: enable when proton 0.5 has been released:
qpid::types::Variant::Map properties;
DataReader::read(pn_connection_remote_properties(connection), properties);
setPeerProperties(properties);
- */
}
void Connection::closed()
diff --git a/qpid/cpp/src/qpid/broker/amqp/DataReader.cpp b/qpid/cpp/src/qpid/broker/amqp/DataReader.cpp
index 957134d0e6..ca3e6daabd 100644
--- a/qpid/cpp/src/qpid/broker/amqp/DataReader.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/DataReader.cpp
@@ -160,7 +160,7 @@ void DataReader::readArray(pn_data_t* /*data*/, const qpid::amqp::Descriptor* /*
void DataReader::readList(pn_data_t* data, const qpid::amqp::Descriptor* descriptor)
{
size_t count = pn_data_get_list(data);
- bool skip = reader.onStartList(count, qpid::amqp::CharSequence(), descriptor);
+ bool skip = reader.onStartList(count, qpid::amqp::CharSequence(), qpid::amqp::CharSequence(), descriptor);
if (!skip) {
pn_data_enter(data);
for (size_t i = 0; i < count && pn_data_next(data); ++i) {
@@ -174,7 +174,7 @@ void DataReader::readList(pn_data_t* data, const qpid::amqp::Descriptor* descrip
void DataReader::readMap(pn_data_t* data, const qpid::amqp::Descriptor* descriptor)
{
size_t count = pn_data_get_map(data);
- reader.onStartMap(count, qpid::amqp::CharSequence(), descriptor);
+ reader.onStartMap(count, qpid::amqp::CharSequence(), qpid::amqp::CharSequence(), descriptor);
pn_data_enter(data);
for (size_t i = 0; i < count && pn_data_next(data); ++i) {
read(data);
diff --git a/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp b/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp
index 119d05af60..f54328bc2e 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Incoming.cpp
@@ -25,6 +25,7 @@
#include "qpid/amqp/descriptors.h"
#include "qpid/broker/AsyncCompletion.h"
#include "qpid/broker/Message.h"
+#include "qpid/broker/Broker.h"
namespace qpid {
namespace broker {
@@ -104,7 +105,7 @@ namespace {
}
DecodingIncoming::DecodingIncoming(pn_link_t* link, Broker& broker, Session& parent, const std::string& source, const std::string& target, const std::string& name)
- : Incoming(link, broker, parent, source, target, name), session(parent.shared_from_this()) {}
+ : Incoming(link, broker, parent, source, target, name), session(parent.shared_from_this()), expiryPolicy(broker.getExpiryPolicy()) {}
DecodingIncoming::~DecodingIncoming() {}
void DecodingIncoming::readable(pn_delivery_t* delivery)
@@ -116,6 +117,7 @@ void DecodingIncoming::readable(pn_delivery_t* delivery)
qpid::broker::Message message(received, received);
userid.verify(message.getUserId());
+ message.computeExpiration(expiryPolicy);
handle(message);
--window;
received->begin();
diff --git a/qpid/cpp/src/qpid/broker/amqp/Incoming.h b/qpid/cpp/src/qpid/broker/amqp/Incoming.h
index 8852766eda..127f8cecf9 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Incoming.h
+++ b/qpid/cpp/src/qpid/broker/amqp/Incoming.h
@@ -77,6 +77,7 @@ class DecodingIncoming : public Incoming
virtual void handle(qpid::broker::Message&) = 0;
private:
boost::shared_ptr<Session> session;
+ boost::intrusive_ptr<ExpiryPolicy> expiryPolicy;
};
}}} // namespace qpid::broker::amqp
diff --git a/qpid/cpp/src/qpid/broker/amqp/Message.cpp b/qpid/cpp/src/qpid/broker/amqp/Message.cpp
index 3dcf1c14e6..572eea3881 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Message.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Message.cpp
@@ -21,9 +21,13 @@
#include "Message.h"
#include "qpid/amqp/Decoder.h"
#include "qpid/amqp/descriptors.h"
-#include "qpid/amqp/Reader.h"
-#include "qpid/amqp/MessageEncoder.h"
+#include "qpid/amqp/ListBuilder.h"
+#include "qpid/amqp/MapBuilder.h"
#include "qpid/amqp/MapHandler.h"
+#include "qpid/amqp/MessageEncoder.h"
+#include "qpid/amqp/Reader.h"
+#include "qpid/amqp/typecodes.h"
+#include "qpid/types/encodings.h"
#include "qpid/log/Statement.h"
#include "qpid/framing/Buffer.h"
#include <string.h>
@@ -121,8 +125,8 @@ namespace {
}
}
- bool onStartList(uint32_t, const CharSequence&, const Descriptor*) { return false; }
- bool onStartMap(uint32_t, const CharSequence&, const Descriptor*) { return false; }
+ bool onStartList(uint32_t, const CharSequence&, const CharSequence&, const Descriptor*) { return false; }
+ bool onStartMap(uint32_t, const CharSequence&, const CharSequence&, const Descriptor*) { return false; }
bool onStartArray(uint32_t, const CharSequence&, const Constructor&, const Descriptor*) { return false; }
public:
@@ -144,8 +148,12 @@ void Message::processProperties(MapHandler& mh) const {
//and whether it should indeed only be the content that is thus
//measured
uint64_t Message::getContentSize() const { return data.size(); }
-//getContent() is used primarily for decoding qmf messages in management and ha
-std::string Message::getContent() const { return empty; }
+//getContent() is used primarily for decoding qmf messages in
+//management and ha, but also by the xml exchange
+std::string Message::getContent() const
+{
+ return std::string(body.data, body.size);
+}
Message::Message(size_t size) : data(size)
{
@@ -253,12 +261,54 @@ void Message::onGroupId(const qpid::amqp::CharSequence&) {}
void Message::onGroupSequence(uint32_t) {}
void Message::onReplyToGroupId(const qpid::amqp::CharSequence&) {}
-void Message::onApplicationProperties(const qpid::amqp::CharSequence& v) { applicationProperties = v; }
-void Message::onDeliveryAnnotations(const qpid::amqp::CharSequence& v) { deliveryAnnotations = v; }
-void Message::onMessageAnnotations(const qpid::amqp::CharSequence& v) { messageAnnotations = v; }
-void Message::onBody(const qpid::amqp::CharSequence& v, const qpid::amqp::Descriptor&) { body = v; }
-void Message::onBody(const qpid::types::Variant&, const qpid::amqp::Descriptor&) {}
-void Message::onFooter(const qpid::amqp::CharSequence& v) { footer = v; }
+void Message::onApplicationProperties(const qpid::amqp::CharSequence& v, const qpid::amqp::CharSequence&) { applicationProperties = v; }
+void Message::onDeliveryAnnotations(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence& v) { deliveryAnnotations = v; }
+void Message::onMessageAnnotations(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence& v) { messageAnnotations = v; }
+
+void Message::onData(const qpid::amqp::CharSequence& v) { body = v; }
+void Message::onAmqpSequence(const qpid::amqp::CharSequence& v) { body = v; bodyType = qpid::amqp::typecodes::LIST_NAME; }
+void Message::onAmqpValue(const qpid::amqp::CharSequence& v, const std::string& t)
+{
+ body = v;
+ if (t == qpid::amqp::typecodes::STRING_NAME) {
+ bodyType = qpid::types::encodings::UTF8;
+ } else if (t == qpid::amqp::typecodes::SYMBOL_NAME) {
+ bodyType = qpid::types::encodings::ASCII;
+ } else if (t == qpid::amqp::typecodes::BINARY_NAME) {
+ bodyType = qpid::types::encodings::BINARY;
+ } else {
+ bodyType = t;
+ }
+}
+void Message::onAmqpValue(const qpid::types::Variant& v) { typedBody = v; }
+
+void Message::onFooter(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence& v) { footer = v; }
+
+bool Message::isTypedBody() const
+{
+ return !typedBody.isVoid() || !bodyType.empty();
+}
+
+qpid::types::Variant Message::getTypedBody() const
+{
+ if (bodyType == qpid::amqp::typecodes::LIST_NAME) {
+ qpid::amqp::ListBuilder builder;
+ qpid::amqp::Decoder decoder(body.data, body.size);
+ decoder.read(builder);
+ return builder.getList();
+ } else if (bodyType == qpid::amqp::typecodes::MAP_NAME) {
+ qpid::amqp::MapBuilder builder;
+ qpid::amqp::Decoder decoder(body.data, body.size);
+ decoder.read(builder);
+ return builder.getMap();
+ } else if (!bodyType.empty()) {
+ qpid::types::Variant value(std::string(body.data, body.size));
+ value.setEncoding(bodyType);
+ return value;
+ } else {
+ return typedBody;
+ }
+}
//PersistableMessage interface:
@@ -292,31 +342,41 @@ void Message::decodeHeader(framing::Buffer& buffer)
}
void Message::decodeContent(framing::Buffer& /*buffer*/) {}
-boost::intrusive_ptr<PersistableMessage> Message::merge(const std::map<std::string, qpid::types::Variant>& annotations) const
+boost::intrusive_ptr<PersistableMessage> Message::merge(const std::map<std::string, qpid::types::Variant>& added) const
{
//message- or delivery- annotations? would have to determine that from the name, for now assume always message-annotations
- size_t extra = 0;
+ std::map<std::string, qpid::types::Variant> combined;
+ const std::map<std::string, qpid::types::Variant>* annotations(0);
if (messageAnnotations) {
- //TODO: actual merge required
+ //combine existing and added annotations (TODO: this could be
+ //optimised by avoiding the decode and simply 'editing' the
+ //size and count in the raw data, then appending the new
+ //elements).
+ qpid::amqp::MapBuilder builder;
+ qpid::amqp::Decoder decoder(messageAnnotations.data, messageAnnotations.size);
+ decoder.read(builder);
+ combined = builder.getMap();
+ for (std::map<std::string, qpid::types::Variant>::const_iterator i = added.begin(); i != added.end(); ++i) {
+ combined[i->first] = i->second;
+ }
+ annotations = &combined;
} else {
- //add whole new section
- extra = qpid::amqp::MessageEncoder::getEncodedSize(annotations, true);
+ //additions form a whole new section
+ annotations = &added;
}
- boost::intrusive_ptr<Message> copy(new Message(data.size()+extra));
+ size_t annotationsSize = qpid::amqp::MessageEncoder::getEncodedSize(*annotations, true) + 3/*descriptor*/;
+
+ boost::intrusive_ptr<Message> copy(new Message(bareMessage.size+footer.size+deliveryAnnotations.size+annotationsSize));
size_t position(0);
- if (deliveryAnnotations) {
+ if (deliveryAnnotations.size) {
::memcpy(&copy->data[position], deliveryAnnotations.data, deliveryAnnotations.size);
position += deliveryAnnotations.size;
}
- if (messageAnnotations) {
- //TODO: actual merge required
- ::memcpy(&copy->data[position], messageAnnotations.data, messageAnnotations.size);
- position += messageAnnotations.size;
- } else {
- qpid::amqp::MessageEncoder encoder(&copy->data[position], extra);
- encoder.writeMap(annotations, &qpid::amqp::message::MESSAGE_ANNOTATIONS, true);
- position += extra;
- }
+
+ qpid::amqp::Encoder encoder(&copy->data[position], annotationsSize);
+ encoder.writeMap(*annotations, &qpid::amqp::message::MESSAGE_ANNOTATIONS, true);
+ position += encoder.getPosition();
+
if (bareMessage) {
::memcpy(&copy->data[position], bareMessage.data, bareMessage.size);
position += bareMessage.size;
@@ -325,7 +385,18 @@ boost::intrusive_ptr<PersistableMessage> Message::merge(const std::map<std::stri
::memcpy(&copy->data[position], footer.data, footer.size);
position += footer.size;
}
+ copy->data.resize(position);//annotationsSize may be slightly bigger than needed if optimisations are used (e.g. smallint)
copy->scan();
+ {
+ qpid::amqp::MapBuilder builder;
+ qpid::amqp::Decoder decoder(copy->messageAnnotations.data, copy->messageAnnotations.size);
+ decoder.read(builder);
+ QPID_LOG(notice, "Merged annotations are now: " << builder.getMap() << " raw=" << std::hex << std::string(copy->messageAnnotations.data, copy->messageAnnotations.size) << " " << copy->messageAnnotations.size << " bytes");
+ }
+ assert(copy->messageAnnotations);
+ assert(copy->bareMessage.size == bareMessage.size);
+ assert(copy->footer.size == footer.size);
+ assert(copy->deliveryAnnotations.size == deliveryAnnotations.size);
return copy;
}
diff --git a/qpid/cpp/src/qpid/broker/amqp/Message.h b/qpid/cpp/src/qpid/broker/amqp/Message.h
index cbf8669fc1..3a7c4529de 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Message.h
+++ b/qpid/cpp/src/qpid/broker/amqp/Message.h
@@ -64,6 +64,8 @@ class Message : public qpid::broker::Message::Encoding, private qpid::amqp::Mess
qpid::amqp::CharSequence getBareMessage() const;
qpid::amqp::CharSequence getBody() const;
qpid::amqp::CharSequence getFooter() const;
+ bool isTypedBody() const;
+ qpid::types::Variant getTypedBody() const;
Message(size_t size);
char* getData();
@@ -109,6 +111,8 @@ class Message : public qpid::broker::Message::Encoding, private qpid::amqp::Mess
//body:
qpid::amqp::CharSequence body;
+ qpid::types::Variant typedBody;
+ std::string bodyType;
//footer:
qpid::amqp::CharSequence footer;
@@ -136,12 +140,16 @@ class Message : public qpid::broker::Message::Encoding, private qpid::amqp::Mess
void onGroupSequence(uint32_t);
void onReplyToGroupId(const qpid::amqp::CharSequence&);
- void onApplicationProperties(const qpid::amqp::CharSequence&);
- void onDeliveryAnnotations(const qpid::amqp::CharSequence&);
- void onMessageAnnotations(const qpid::amqp::CharSequence&);
- void onBody(const qpid::amqp::CharSequence&, const qpid::amqp::Descriptor&);
- void onBody(const qpid::types::Variant&, const qpid::amqp::Descriptor&);
- void onFooter(const qpid::amqp::CharSequence&);
+ void onApplicationProperties(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&);
+ void onDeliveryAnnotations(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&);
+ void onMessageAnnotations(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&);
+
+ void onData(const qpid::amqp::CharSequence&);
+ void onAmqpSequence(const qpid::amqp::CharSequence&);
+ void onAmqpValue(const qpid::amqp::CharSequence&, const std::string& type);
+ void onAmqpValue(const qpid::types::Variant&);
+
+ void onFooter(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&);
};
}}} // namespace qpid::broker::amqp
diff --git a/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp b/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp
index 68ff979aa4..e8c05ed7b0 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp
@@ -29,6 +29,7 @@
#include "qpid/sys/OutputControl.h"
#include "qpid/amqp/descriptors.h"
#include "qpid/amqp/MessageEncoder.h"
+#include "qpid/framing/Buffer.h"
#include "qpid/framing/reply_exceptions.h"
#include "qpid/log/Statement.h"
@@ -44,14 +45,16 @@ void Outgoing::wakeup()
session.wakeup();
}
-OutgoingFromQueue::OutgoingFromQueue(Broker& broker, const std::string& source, const std::string& target, boost::shared_ptr<Queue> q, pn_link_t* l, Session& session, qpid::sys::OutputControl& o, bool e, bool p)
+OutgoingFromQueue::OutgoingFromQueue(Broker& broker, const std::string& source, const std::string& target, boost::shared_ptr<Queue> q, pn_link_t* l, Session& session,
+ qpid::sys::OutputControl& o, SubscriptionType type, bool e, bool p)
: Outgoing(broker, session, source, target, pn_link_name(l)),
- Consumer(pn_link_name(l), /*FIXME*/CONSUMER),
+ Consumer(pn_link_name(l), type),
exclusive(e),
isControllingUser(p),
queue(q), deliveries(5000), link(l), out(o),
current(0), outstanding(0),
- buffer(1024)/*used only for header at present*/
+ buffer(1024)/*used only for header at present*/,
+ unreliable(pn_link_remote_snd_settle_mode(link) == PN_SND_SETTLED)
{
for (size_t i = 0 ; i < deliveries.capacity(); ++i) {
deliveries[i].init(i);
@@ -91,8 +94,7 @@ void OutgoingFromQueue::write(const char* data, size_t size)
void OutgoingFromQueue::handle(pn_delivery_t* delivery)
{
- pn_delivery_tag_t tag = pn_delivery_tag(delivery);
- size_t i = *reinterpret_cast<const size_t*>(tag.bytes);
+ size_t i = Record::getIndex(pn_delivery_tag(delivery));
Record& r = deliveries[i];
if (pn_delivery_writable(delivery)) {
assert(r.msg);
@@ -104,6 +106,7 @@ void OutgoingFromQueue::handle(pn_delivery_t* delivery)
write(&buffer[0], encoder.getPosition());
Translation t(r.msg);
t.write(*this);
+ if (unreliable) pn_delivery_settle(delivery);
if (pn_link_advance(link)) {
--outstanding;
outgoingMessageSent();
@@ -112,26 +115,28 @@ void OutgoingFromQueue::handle(pn_delivery_t* delivery)
QPID_LOG(error, "Failed to send message " << r.msg.getSequence() << " from " << queue->getName() << ", index=" << r.index);
}
}
- if (pn_delivery_updated(delivery)) {
+ if (unreliable) {
+ if (preAcquires()) queue->dequeue(0, r.cursor);
+ r.reset();
+ } else if (pn_delivery_updated(delivery)) {
assert(r.delivery == delivery);
r.disposition = pn_delivery_remote_state(delivery);
if (r.disposition) {
switch (r.disposition) {
case PN_ACCEPTED:
- //TODO: only if consuming
- queue->dequeue(0, r.cursor);
+ if (preAcquires()) queue->dequeue(0, r.cursor);
outgoingMessageAccepted();
break;
case PN_REJECTED:
- queue->reject(r.cursor);
+ if (preAcquires()) queue->reject(r.cursor);
outgoingMessageRejected();
break;
case PN_RELEASED:
- queue->release(r.cursor, false);//TODO: for PN_RELEASED, delivery count should not be incremented
+ if (preAcquires()) queue->release(r.cursor, false);//TODO: for PN_RELEASED, delivery count should not be incremented
outgoingMessageRejected();//TODO: not quite true...
break;
case PN_MODIFIED:
- queue->release(r.cursor, true);//TODO: proper handling of modified
+ if (preAcquires()) queue->release(r.cursor, true);//TODO: proper handling of modified
outgoingMessageRejected();//TODO: not quite true...
break;
default:
@@ -251,12 +256,17 @@ qpid::broker::OwnershipToken* OutgoingFromQueue::getSession()
return 0;
}
-OutgoingFromQueue::Record::Record() : delivery(0), disposition(0), index(0) {}
+OutgoingFromQueue::Record::Record() : delivery(0), disposition(0), index(0)
+{
+ tag.bytes = tagData;
+ tag.size = TAG_WIDTH;
+}
void OutgoingFromQueue::Record::init(size_t i)
{
index = i;
- tag.bytes = reinterpret_cast<const char*>(&index);
- tag.size = sizeof(index);
+ qpid::framing::Buffer buffer(tagData, tag.size);
+ assert(index <= std::numeric_limits<uint32_t>::max());
+ buffer.putLong(index);
}
void OutgoingFromQueue::Record::reset()
{
@@ -266,5 +276,13 @@ void OutgoingFromQueue::Record::reset()
disposition = 0;
}
+size_t OutgoingFromQueue::Record::getIndex(pn_delivery_tag_t t)
+{
+ assert(t.size == TAG_WIDTH);
+ qpid::framing::Buffer buffer(const_cast<char*>(t.bytes)/*won't ever be written to*/, t.size);
+ return (size_t) buffer.getLong();
+}
+
+
}}} // namespace qpid::broker::amqp
diff --git a/qpid/cpp/src/qpid/broker/amqp/Outgoing.h b/qpid/cpp/src/qpid/broker/amqp/Outgoing.h
index 86d7d46111..81994f2b66 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Outgoing.h
+++ b/qpid/cpp/src/qpid/broker/amqp/Outgoing.h
@@ -88,7 +88,8 @@ class Outgoing : public ManagedOutgoingLink
class OutgoingFromQueue : public Outgoing, public qpid::broker::Consumer, public boost::enable_shared_from_this<OutgoingFromQueue>
{
public:
- OutgoingFromQueue(Broker&, const std::string& source, const std::string& target, boost::shared_ptr<Queue> q, pn_link_t* l, Session&, qpid::sys::OutputControl& o, bool exclusive, bool isControllingUser);
+ OutgoingFromQueue(Broker&, const std::string& source, const std::string& target, boost::shared_ptr<Queue> q, pn_link_t* l, Session&,
+ qpid::sys::OutputControl& o, SubscriptionType type, bool exclusive, bool isControllingUser);
void setSubjectFilter(const std::string&);
void setSelectorFilter(const std::string&);
void init();
@@ -117,10 +118,17 @@ class OutgoingFromQueue : public Outgoing, public qpid::broker::Consumer, public
int disposition;
size_t index;
pn_delivery_tag_t tag;
+ //The delivery tag is a 4 byte value representing the
+ //index. It is encoded separately to avoid alignment issues.
+ //The number of deliveries held here is always strictly
+ //bounded, so 4 bytes is more than enough.
+ static const size_t TAG_WIDTH = sizeof(uint32_t);
+ char tagData[TAG_WIDTH];
Record();
void init(size_t i);
void reset();
+ static size_t getIndex(pn_delivery_tag_t);
};
const bool exclusive;
@@ -134,6 +142,7 @@ class OutgoingFromQueue : public Outgoing, public qpid::broker::Consumer, public
std::vector<char> buffer;
std::string subjectFilter;
boost::scoped_ptr<Selector> selector;
+ bool unreliable;
};
}}} // namespace qpid::broker::amqp
diff --git a/qpid/cpp/src/qpid/broker/amqp/Relay.cpp b/qpid/cpp/src/qpid/broker/amqp/Relay.cpp
index a08971cb5c..83b3e64ee6 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Relay.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Relay.cpp
@@ -105,14 +105,14 @@ void Relay::detached(Outgoing*)
{
out = 0;
isDetached = true;
- std::cerr << "Outgoing link detached from relay" << std::endl;
+ QPID_LOG(info, "Outgoing link detached from relay [" << this << "]");
if (in) in->wakeup();
}
void Relay::detached(Incoming*)
{
in = 0;
isDetached = true;
- std::cerr << "Incoming link detached from relay" << std::endl;
+ QPID_LOG(info, "Incoming link detached from relay [" << this << "]");
if (out) out->wakeup();
}
@@ -139,13 +139,13 @@ void OutgoingFromRelay::handle(pn_delivery_t* delivery)
if (pn_delivery_writable(delivery)) {
if (transfer->write(link)) {
outgoingMessageSent();
- QPID_LOG(debug, "Sent relayed message " << name);
+ QPID_LOG(debug, "Sent relayed message " << name << " [" << relay.get() << "]");
} else {
- QPID_LOG(error, "Failed to send relayed message " << name);
+ QPID_LOG(error, "Failed to send relayed message " << name << " [" << relay.get() << "]");
}
}
if (pn_delivery_updated(delivery)) {
- pn_disposition_t d = transfer->updated();
+ uint64_t d = transfer->updated();
switch (d) {
case PN_ACCEPTED:
outgoingMessageAccepted();
@@ -226,6 +226,7 @@ void IncomingToRelay::detached()
relay->detached(this);
}
+BufferedTransfer::BufferedTransfer() : disposition(0) {}
void BufferedTransfer::initIn(pn_link_t* link, pn_delivery_t* d)
{
in.handle = d;
@@ -264,7 +265,7 @@ void BufferedTransfer::initOut(pn_link_t* link)
pn_delivery_set_context(out.handle, this);
}
-pn_disposition_t BufferedTransfer::updated()
+uint64_t BufferedTransfer::updated()
{
disposition = pn_delivery_remote_state(out.handle);
if (disposition) {
diff --git a/qpid/cpp/src/qpid/broker/amqp/Relay.h b/qpid/cpp/src/qpid/broker/amqp/Relay.h
index 0c2d48b346..ef700690fd 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Relay.h
+++ b/qpid/cpp/src/qpid/broker/amqp/Relay.h
@@ -45,10 +45,11 @@ struct Delivery
class BufferedTransfer
{
public:
+ BufferedTransfer();
void initIn(pn_link_t* link, pn_delivery_t* d);
bool settle();
void initOut(pn_link_t* link);
- pn_disposition_t updated();
+ uint64_t updated();
bool write(pn_link_t*);
private:
std::vector<char> data;
@@ -56,7 +57,7 @@ class BufferedTransfer
Delivery out;
pn_delivery_tag_t dt;
std::vector<char> tag;
- pn_disposition_t disposition;
+ uint64_t disposition;
};
/**
diff --git a/qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp b/qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp
index 678fddbba9..4317d18525 100644
--- a/qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/SaslClient.cpp
@@ -36,7 +36,7 @@ namespace amqp {
SaslClient::SaslClient(qpid::sys::OutputControl& out_, const std::string& id, boost::shared_ptr<Interconnect> c, std::auto_ptr<qpid::Sasl> s,
const std::string& hostname_, const std::string& mechs, const qpid::sys::SecuritySettings& t)
: qpid::amqp::SaslClient(id), out(out_), connection(c), sasl(s),
- hostname(hostname_), allowedMechanisms(mechs), transport(t), readHeader(true), writeHeader(false), haveOutput(false), state(NONE) {}
+ hostname(hostname_), allowedMechanisms(mechs), transport(t), readHeader(true), writeHeader(false), haveOutput(false), initialised(false), state(NONE) {}
SaslClient::~SaslClient()
{
@@ -67,8 +67,10 @@ std::size_t SaslClient::encode(char* buffer, std::size_t size)
encoded += writeProtocolHeader(buffer, size);
writeHeader = !encoded;
}
- if (state == NONE && encoded < size) {
- encoded += write(buffer + encoded, size - encoded);
+ if ((!initialised || state == NONE) && encoded < size) {
+ size_t extra = write(buffer + encoded, size - encoded);
+ encoded += extra;
+ initialised = extra > 0;
} else if (state == SUCCEEDED) {
if (securityLayer.get()) encoded += securityLayer->encode(buffer + encoded, size - encoded);
else encoded += connection->encode(buffer + encoded, size - encoded);
diff --git a/qpid/cpp/src/qpid/broker/amqp/SaslClient.h b/qpid/cpp/src/qpid/broker/amqp/SaslClient.h
index 4d802f6f65..fca293879e 100644
--- a/qpid/cpp/src/qpid/broker/amqp/SaslClient.h
+++ b/qpid/cpp/src/qpid/broker/amqp/SaslClient.h
@@ -64,6 +64,7 @@ class SaslClient : public qpid::sys::ConnectionCodec, qpid::amqp::SaslClient
bool readHeader;
bool writeHeader;
bool haveOutput;
+ bool initialised;
enum {
NONE, FAILED, SUCCEEDED
} state;
diff --git a/qpid/cpp/src/qpid/broker/amqp/Session.cpp b/qpid/cpp/src/qpid/broker/amqp/Session.cpp
index e6ea694d54..4627d724a5 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Session.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Session.cpp
@@ -36,6 +36,7 @@
#include "qpid/broker/TopicExchange.h"
#include "qpid/broker/FanOutExchange.h"
#include "qpid/broker/Queue.h"
+#include "qpid/broker/QueueCursor.h"
#include "qpid/broker/Selector.h"
#include "qpid/broker/TopicExchange.h"
#include "qpid/broker/amqp/Filter.h"
@@ -56,15 +57,16 @@ namespace broker {
namespace amqp {
namespace {
-bool is_capability_requested(const std::string& name, pn_data_t* capabilities)
+pn_bytes_t convert(const std::string& s)
{
- pn_data_rewind(capabilities);
- while (pn_data_next(capabilities)) {
- pn_bytes_t c = pn_data_get_symbol(capabilities);
- std::string s(c.start, c.size);
- if (s == name) return true;
- }
- return false;
+ pn_bytes_t result;
+ result.start = const_cast<char*>(s.data());
+ result.size = s.size();
+ return result;
+}
+std::string convert(pn_bytes_t in)
+{
+ return std::string(in.start, in.size);
}
//capabilities
const std::string CREATE_ON_DEMAND("create-on-demand");
@@ -75,40 +77,90 @@ const std::string DIRECT_FILTER("legacy-amqp-direct-binding");
const std::string TOPIC_FILTER("legacy-amqp-topic-binding");
const std::string SHARED("shared");
-void setCapabilities(pn_data_t* in, pn_data_t* out, boost::shared_ptr<Queue> node)
+void writeCapabilities(pn_data_t* out, const std::vector<std::string>& supported)
{
- pn_data_rewind(in);
- while (pn_data_next(in)) {
- pn_bytes_t c = pn_data_get_symbol(in);
- std::string s(c.start, c.size);
- if (s == DURABLE) {
- if (node->isDurable()) pn_data_put_symbol(out, c);
- } else if (s == CREATE_ON_DEMAND || s == QUEUE || s == DIRECT_FILTER || s == TOPIC_FILTER) {
- pn_data_put_symbol(out, c);
+ if (supported.size() == 1) {
+ pn_data_put_symbol(out, convert(supported.front()));
+ } else if (supported.size() > 1) {
+ pn_data_put_array(out, false, PN_SYMBOL);
+ pn_data_enter(out);
+ for (std::vector<std::string>::const_iterator i = supported.begin(); i != supported.end(); ++i) {
+ pn_data_put_symbol(out, convert(*i));
}
+ pn_data_exit(out);
}
}
-void setCapabilities(pn_data_t* in, pn_data_t* out, boost::shared_ptr<Exchange> node)
+template <class F>
+void readCapabilities(pn_data_t* data, F f)
{
- pn_data_rewind(in);
- while (pn_data_next(in)) {
- pn_bytes_t c = pn_data_get_symbol(in);
- std::string s(c.start, c.size);
- if (s == DURABLE) {
- if (node->isDurable()) pn_data_put_symbol(out, c);
- } else if (s == SHARED) {
- pn_data_put_symbol(out, c);
- } else if (s == CREATE_ON_DEMAND || s == TOPIC) {
- pn_data_put_symbol(out, c);
- } else if (s == DIRECT_FILTER) {
- if (node->getType() == DirectExchange::typeName) pn_data_put_symbol(out, c);
- } else if (s == TOPIC_FILTER) {
- if (node->getType() == TopicExchange::typeName) pn_data_put_symbol(out, c);
+ pn_data_rewind(data);
+ if (pn_data_next(data)) {
+ pn_type_t type = pn_data_type(data);
+ if (type == PN_ARRAY) {
+ pn_data_enter(data);
+ while (pn_data_next(data)) {
+ f(convert(pn_data_get_symbol(data)));
+ }
+ pn_data_exit(data);
+ } else if (type == PN_SYMBOL) {
+ f(convert(pn_data_get_symbol(data)));
+ } else {
+ QPID_LOG(error, "Skipping capabilities field of type " << pn_type_name(type));
}
}
}
+void matchCapability(const std::string& name, bool* result, const std::string& s)
+{
+ if (s == name) *result = true;
+}
+
+bool is_capability_requested(const std::string& name, pn_data_t* capabilities)
+{
+ bool result(false);
+ readCapabilities(capabilities, boost::bind(&matchCapability, name, &result, _1));
+ return result;
+}
+
+void collectQueueCapabilities(boost::shared_ptr<Queue> node, std::vector<std::string>* supported, const std::string& s)
+{
+ if (s == DURABLE) {
+ if (node->isDurable()) supported->push_back(s);
+ } else if (s == CREATE_ON_DEMAND || s == QUEUE || s == DIRECT_FILTER || s == TOPIC_FILTER) {
+ supported->push_back(s);
+ }
+}
+
+void collectExchangeCapabilities(boost::shared_ptr<Exchange> node, std::vector<std::string>* supported, const std::string& s)
+{
+ if (s == DURABLE) {
+ if (node->isDurable()) supported->push_back(s);
+ } else if (s == SHARED) {
+ supported->push_back(s);
+ } else if (s == CREATE_ON_DEMAND || s == TOPIC) {
+ supported->push_back(s);
+ } else if (s == DIRECT_FILTER) {
+ if (node->getType() == DirectExchange::typeName) supported->push_back(s);
+ } else if (s == TOPIC_FILTER) {
+ if (node->getType() == TopicExchange::typeName) supported->push_back(s);
+ }
+}
+
+void setCapabilities(pn_data_t* in, pn_data_t* out, boost::shared_ptr<Queue> node)
+{
+ std::vector<std::string> supported;
+ readCapabilities(in, boost::bind(&collectQueueCapabilities, node, &supported, _1));
+ writeCapabilities(out, supported);
+}
+
+void setCapabilities(pn_data_t* in, pn_data_t* out, boost::shared_ptr<Exchange> node)
+{
+ std::vector<std::string> supported;
+ readCapabilities(in, boost::bind(&collectExchangeCapabilities, node, &supported, _1));
+ writeCapabilities(out, supported);
+}
+
}
class IncomingToQueue : public DecodingIncoming
@@ -149,6 +201,12 @@ Session::ResolvedNode Session::resolve(const std::string name, pn_terminus_t* te
node.queue = connection.getBroker().getQueues().find(name);
node.topic = connection.getTopics().get(name);
if (node.topic) node.exchange = node.topic->getExchange();
+ if (node.exchange && !node.queue && is_capability_requested(CREATE_ON_DEMAND, pn_terminus_capabilities(terminus))) {
+ node.properties.read(pn_terminus_properties(terminus));
+ if (!node.properties.getExchangeType().empty() && node.properties.getExchangeType() != node.exchange->getType()) {
+ throw Exception(qpid::amqp::error_conditions::PRECONDITION_FAILED, "Exchange of different type already exists");
+ }
+ }
if (!node.queue && !node.exchange) {
if (pn_terminus_is_dynamic(terminus) || is_capability_requested(CREATE_ON_DEMAND, pn_terminus_capabilities(terminus))) {
//is it a queue or an exchange?
@@ -316,10 +374,10 @@ void Session::setupOutgoing(pn_link_t* link, pn_terminus_t* source, const std::s
target = targetAddress;
}
-
if (node.queue) {
authorise.outgoing(node.queue);
- boost::shared_ptr<Outgoing> q(new OutgoingFromQueue(connection.getBroker(), name, target, node.queue, link, *this, out, false, node.properties.trackControllingLink()));
+ SubscriptionType type = pn_terminus_get_distribution_mode(source) == PN_DIST_MODE_COPY ? BROWSER : CONSUMER;
+ boost::shared_ptr<Outgoing> q(new OutgoingFromQueue(connection.getBroker(), name, target, node.queue, link, *this, out, type, false, node.properties.trackControllingLink()));
q->init();
filter.apply(q);
outgoing[link] = q;
@@ -333,8 +391,12 @@ void Session::setupOutgoing(pn_link_t* link, pn_terminus_t* source, const std::s
settings.durable = durable;
settings.autodelete = !durable;
}
+ settings.autoDeleteDelay = pn_terminus_get_timeout(source);
+ if (settings.autoDeleteDelay) {
+ settings.autodelete = true;
+ settings.original["qpid.auto_delete_timeout"] = settings.autoDeleteDelay;
+ }
filter.configure(settings);
- //TODO: populate settings from source details when available from engine
std::stringstream queueName;
if (shared) {
//just use link name (TODO: could allow this to be
@@ -350,9 +412,9 @@ void Session::setupOutgoing(pn_link_t* link, pn_terminus_t* source, const std::s
if (!shared) queue->setExclusiveOwner(this);
authorise.outgoing(node.exchange, queue, filter);
filter.bind(node.exchange, queue);
- boost::shared_ptr<Outgoing> q(new OutgoingFromQueue(connection.getBroker(), name, target, queue, link, *this, out, !shared, false));
- outgoing[link] = q;
+ boost::shared_ptr<Outgoing> q(new OutgoingFromQueue(connection.getBroker(), name, target, queue, link, *this, out, CONSUMER, !shared, false));
q->init();
+ outgoing[link] = q;
} else if (node.relay) {
boost::shared_ptr<Outgoing> out(new OutgoingFromRelay(link, connection.getBroker(), *this, name, target, pn_link_name(link), node.relay));
outgoing[link] = out;
@@ -503,7 +565,6 @@ bool Session::dispatch()
void Session::close()
{
- exclusiveQueues.clear();
for (OutgoingLinks::iterator i = outgoing.begin(); i != outgoing.end(); ++i) {
i->second->detached();
}
@@ -516,6 +577,7 @@ void Session::close()
for (std::set< boost::shared_ptr<Queue> >::const_iterator i = exclusiveQueues.begin(); i != exclusiveQueues.end(); ++i) {
(*i)->releaseExclusiveOwnership();
}
+ exclusiveQueues.clear();
qpid::sys::Mutex::ScopedLock l(lock);
deleted = true;
}
diff --git a/qpid/cpp/src/qpid/broker/amqp/Topic.cpp b/qpid/cpp/src/qpid/broker/amqp/Topic.cpp
index 7d77343f26..4bb581628b 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Topic.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Topic.cpp
@@ -47,6 +47,13 @@ bool testProperty(const std::string& k, const qpid::types::Variant::Map& m)
else return i->second;
}
+qpid::types::Variant::Map filter(const qpid::types::Variant::Map& properties)
+{
+ qpid::types::Variant::Map filtered = properties;
+ filtered.erase(DURABLE);
+ filtered.erase(EXCHANGE);
+ return filtered;
+}
}
Topic::Topic(Broker& broker, const std::string& n, const qpid::types::Variant::Map& properties)
@@ -60,7 +67,7 @@ Topic::Topic(Broker& broker, const std::string& n, const qpid::types::Variant::M
qpid::management::ManagementAgent* agent = broker.getManagementAgent();
if (agent != 0) {
topic = _qmf::Topic::shared_ptr(new _qmf::Topic(agent, this, name, exchange->GetManagementObject()->getObjectId(), durable));
- topic->set_properties(policy.asMap());
+ topic->set_properties(filter(properties));
agent->addObject(topic);
}
}
@@ -117,8 +124,12 @@ bool TopicRegistry::deleteObject(Broker& broker, const std::string& type, const
{
if (type == TOPIC) {
boost::shared_ptr<Topic> topic = remove(name);
- if (topic->isDurable()) broker.getStore().destroy(*topic);
- return true;
+ if (topic) {
+ if (topic->isDurable()) broker.getStore().destroy(*topic);
+ return true;
+ } else {
+ return false;
+ }
} else {
return false;
}
diff --git a/qpid/cpp/src/qpid/broker/amqp/Translation.cpp b/qpid/cpp/src/qpid/broker/amqp/Translation.cpp
index e04d44d2c8..2196c8ff3d 100644
--- a/qpid/cpp/src/qpid/broker/amqp/Translation.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp/Translation.cpp
@@ -27,6 +27,7 @@
#include "qpid/amqp/MessageEncoder.h"
#include "qpid/amqp_0_10/Codecs.h"
#include "qpid/types/Variant.h"
+#include "qpid/types/encodings.h"
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/log/Statement.h"
#include <boost/lexical_cast.hpp>
@@ -38,6 +39,9 @@ namespace {
const std::string EMPTY;
const std::string FORWARD_SLASH("/");
+const std::string TEXT_PLAIN("text/plain");
+const std::string SUBJECT_KEY("qpid.subject");
+const std::string APP_ID("x-amqp-0-10.app-id");
qpid::framing::ReplyTo translate(const std::string address, Broker* broker)
{
@@ -98,8 +102,25 @@ class Properties_0_10 : public qpid::amqp::MessageEncoder::Properties
std::string getUserId() const { return messageProperties ? messageProperties->getUserId() : EMPTY; }
bool hasTo() const { return getDestination().size() || hasSubject(); }
std::string getTo() const { return getDestination().size() ? getDestination() : getSubject(); }
- bool hasSubject() const { return deliveryProperties && getDestination().size() && deliveryProperties->hasRoutingKey(); }
- std::string getSubject() const { return deliveryProperties && getDestination().size() ? deliveryProperties->getRoutingKey() : EMPTY; }
+ bool hasSubject() const
+ {
+ if (getDestination().empty()) {
+ return getApplicationProperties().isSet(SUBJECT_KEY);
+ } else {
+ return deliveryProperties && deliveryProperties->hasRoutingKey();
+ }
+ }
+ std::string getSubject() const
+ {
+ if (getDestination().empty()) {
+ //message was sent to default exchange, routing key is the queue name
+ return getApplicationProperties().getAsString(SUBJECT_KEY);
+ } else if (deliveryProperties) {
+ return deliveryProperties->getRoutingKey();
+ } else {
+ return EMPTY;
+ }
+ }
bool hasReplyTo() const { return messageProperties && messageProperties->hasReplyTo(); }
std::string getReplyTo() const { return messageProperties ? translate(messageProperties->getReplyTo()) : EMPTY; }
bool hasCorrelationId() const { return messageProperties && messageProperties->hasCorrelationId(); }
@@ -119,7 +140,7 @@ class Properties_0_10 : public qpid::amqp::MessageEncoder::Properties
bool hasReplyToGroupId() const { return false; }
std::string getReplyToGroupId() const { return EMPTY; }
- const qpid::framing::FieldTable& getApplicationProperties() { return messageProperties->getApplicationHeaders(); }
+ const qpid::framing::FieldTable& getApplicationProperties() const { return messageProperties->getApplicationHeaders(); }
Properties_0_10(const qpid::broker::amqp_0_10::MessageTransfer& t) : transfer(t),
messageProperties(transfer.getProperties<qpid::framing::MessageProperties>()),
deliveryProperties(transfer.getProperties<qpid::framing::DeliveryProperties>())
@@ -138,7 +159,6 @@ class Properties_0_10 : public qpid::amqp::MessageEncoder::Properties
Translation::Translation(const qpid::broker::Message& m, Broker* b) : original(m), broker(b) {}
-
boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> Translation::getTransfer()
{
boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> t =
@@ -161,13 +181,38 @@ boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> Translation
transfer->getFrames().append(method);
transfer->getFrames().append(header);
- qpid::amqp::CharSequence body = message->getBody();
- content.castBody<qpid::framing::AMQContentBody>()->getData().assign(body.data, body.size);
- transfer->getFrames().append(content);
-
qpid::framing::MessageProperties* props =
transfer->getFrames().getHeaders()->get<qpid::framing::MessageProperties>(true);
- props->setContentLength(body.size);
+
+ if (message->isTypedBody()) {
+ qpid::types::Variant body = message->getTypedBody();
+ std::string& data = content.castBody<qpid::framing::AMQContentBody>()->getData();
+ if (body.getType() == qpid::types::VAR_MAP) {
+ qpid::amqp_0_10::MapCodec::encode(body.asMap(), data);
+ props->setContentType(qpid::amqp_0_10::MapCodec::contentType);
+ } else if (body.getType() == qpid::types::VAR_LIST) {
+ qpid::amqp_0_10::ListCodec::encode(body.asList(), data);
+ props->setContentType(qpid::amqp_0_10::ListCodec::contentType);
+ } else if (body.getType() == qpid::types::VAR_STRING) {
+ data = body.getString();
+ if (body.getEncoding() == qpid::types::encodings::UTF8 || body.getEncoding() == qpid::types::encodings::ASCII) {
+ props->setContentType(TEXT_PLAIN);
+ }
+ } else {
+ qpid::types::Variant::List container;
+ container.push_back(body);
+ qpid::amqp_0_10::ListCodec::encode(container, data);
+ props->setContentType(qpid::amqp_0_10::ListCodec::contentType);
+ }
+ transfer->getFrames().append(content);
+ props->setContentLength(data.size());
+ } else {
+ qpid::amqp::CharSequence body = message->getBody();
+ content.castBody<qpid::framing::AMQContentBody>()->getData().assign(body.data, body.size);
+ transfer->getFrames().append(content);
+
+ props->setContentLength(body.size);
+ }
qpid::amqp::MessageId mid = message->getMessageId();
qpid::framing::Uuid uuid;
@@ -209,13 +254,25 @@ boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> Translation
if (ap) {
qpid::amqp::Decoder d(ap.data, ap.size);
qpid::amqp_0_10::translate(d.readMap(), props->getApplicationHeaders());
+ std::string appid = props->getApplicationHeaders().getAsString(APP_ID);
+ if (!appid.empty()) {
+ props->setAppId(appid);
+ }
}
qpid::framing::DeliveryProperties* dp =
transfer->getFrames().getHeaders()->get<qpid::framing::DeliveryProperties>(true);
dp->setPriority(message->getPriority());
if (message->isPersistent()) dp->setDeliveryMode(2);
- if (message->getRoutingKey().size()) dp->setRoutingKey(message->getRoutingKey());
+ if (message->getRoutingKey().size()) {
+ if (message->getRoutingKey().size() > std::numeric_limits<uint8_t>::max()) {
+ //have to truncate routing key as it is specified to be a str8
+ dp->setRoutingKey(message->getRoutingKey().substr(0,std::numeric_limits<uint8_t>::max()));
+ } else {
+ dp->setRoutingKey(message->getRoutingKey());
+ }
+ props->getApplicationHeaders().setString(SUBJECT_KEY, message->getRoutingKey());
+ }
return transfer.get();
} else {
@@ -226,10 +283,11 @@ boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> Translation
void Translation::write(OutgoingFromQueue& out)
{
- const Message* message = dynamic_cast<const Message*>(&original.getEncoding());
+ const Message* message = dynamic_cast<const Message*>(original.getPersistentContext().get());
+ //persistent context will contain any newly added annotations
+ if (!message) message = dynamic_cast<const Message*>(&original.getEncoding());
if (message) {
//write annotations
- //TODO: merge in any newly added annotations
qpid::amqp::CharSequence deliveryAnnotations = message->getDeliveryAnnotations();
qpid::amqp::CharSequence messageAnnotations = message->getMessageAnnotations();
if (deliveryAnnotations.size) out.write(deliveryAnnotations.data, deliveryAnnotations.size);
@@ -246,14 +304,40 @@ void Translation::write(OutgoingFromQueue& out)
Properties_0_10 properties(*transfer);
qpid::types::Variant::Map applicationProperties;
qpid::amqp_0_10::translate(properties.getApplicationProperties(), applicationProperties);
- std::string content = transfer->getContent();
- size_t size = qpid::amqp::MessageEncoder::getEncodedSize(properties, applicationProperties, content);
- std::vector<char> buffer(size);
- qpid::amqp::MessageEncoder encoder(&buffer[0], buffer.size());
- encoder.writeProperties(properties);
- encoder.writeApplicationProperties(applicationProperties);
- if (content.size()) encoder.writeBinary(content, &qpid::amqp::message::DATA);
- out.write(&buffer[0], encoder.getPosition());
+ if (properties.getContentType() == qpid::amqp_0_10::MapCodec::contentType) {
+ qpid::types::Variant::Map content;
+ qpid::amqp_0_10::MapCodec::decode(transfer->getContent(), content);
+ size_t size = qpid::amqp::MessageEncoder::getEncodedSize(properties);
+ size += qpid::amqp::MessageEncoder::getEncodedSize(applicationProperties, true) + 3;/*descriptor*/
+ size += qpid::amqp::MessageEncoder::getEncodedSize(content, true) + 3/*descriptor*/;
+ std::vector<char> buffer(size);
+ qpid::amqp::MessageEncoder encoder(&buffer[0], buffer.size());
+ encoder.writeProperties(properties);
+ encoder.writeApplicationProperties(applicationProperties);
+ encoder.writeMap(content, &qpid::amqp::message::AMQP_VALUE);
+ out.write(&buffer[0], encoder.getPosition());
+ } else if (properties.getContentType() == qpid::amqp_0_10::ListCodec::contentType) {
+ qpid::types::Variant::List content;
+ qpid::amqp_0_10::ListCodec::decode(transfer->getContent(), content);
+ size_t size = qpid::amqp::MessageEncoder::getEncodedSize(properties);
+ size += qpid::amqp::MessageEncoder::getEncodedSize(applicationProperties, true) + 3;/*descriptor*/
+ size += qpid::amqp::MessageEncoder::getEncodedSize(content, true) + 3/*descriptor*/;
+ std::vector<char> buffer(size);
+ qpid::amqp::MessageEncoder encoder(&buffer[0], buffer.size());
+ encoder.writeProperties(properties);
+ encoder.writeApplicationProperties(applicationProperties);
+ encoder.writeList(content, &qpid::amqp::message::AMQP_VALUE);
+ out.write(&buffer[0], encoder.getPosition());
+ } else {
+ std::string content = transfer->getContent();
+ size_t size = qpid::amqp::MessageEncoder::getEncodedSize(properties, applicationProperties, content);
+ std::vector<char> buffer(size);
+ qpid::amqp::MessageEncoder encoder(&buffer[0], buffer.size());
+ encoder.writeProperties(properties);
+ encoder.writeApplicationProperties(applicationProperties);
+ if (content.size()) encoder.writeBinary(content, &qpid::amqp::message::DATA);
+ out.write(&buffer[0], encoder.getPosition());
+ }
} else {
QPID_LOG(error, "Could not write message data in AMQP 1.0 format");
}
diff --git a/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp b/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp
index 6732b66ed4..4cfe988b72 100644
--- a/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp
+++ b/qpid/cpp/src/qpid/broker/amqp_0_10/Connection.cpp
@@ -174,6 +174,7 @@ void Connection::requestIOProcessing(boost::function0<void> callback)
Connection::~Connection()
{
if (mgmtObject != 0) {
+ mgmtObject->debugStats("destroying");
if (!link)
agent->raiseEvent(_qmf::EventClientDisconnect(mgmtId, getUserId(), mgmtObject->get_remoteProperties()));
QPID_LOG_CAT(debug, model, "Delete connection. user:" << getUserId()
diff --git a/qpid/cpp/src/qpid/client/AsyncSession.h b/qpid/cpp/src/qpid/client/AsyncSession.h
new file mode 100644
index 0000000000..d91efeb4f1
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/AsyncSession.h
@@ -0,0 +1,38 @@
+#ifndef QPID_CLIENT_ASYNCSESSION_H
+#define QPID_CLIENT_ASYNCSESSION_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/client/AsyncSession_0_10.h"
+
+namespace qpid {
+namespace client {
+
+/**
+ * AsyncSession is an alias for Session_0_10
+ *
+ * \ingroup clientapi
+ */
+typedef AsyncSession_0_10 AsyncSession;
+
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_ASYNCSESSION_H*/
diff --git a/qpid/cpp/src/qpid/client/ClientImportExport.h b/qpid/cpp/src/qpid/client/ClientImportExport.h
new file mode 100644
index 0000000000..2a3a5a52e9
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/ClientImportExport.h
@@ -0,0 +1,35 @@
+#ifndef QPID_CLIENT_IMPORT_EXPORT_H
+#define QPID_CLIENT_IMPORT_EXPORT_H
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "qpid/ImportExport.h"
+
+#if defined(CLIENT_EXPORT) || defined (qpidclient_EXPORTS)
+# define QPID_CLIENT_EXTERN QPID_EXPORT
+# define QPID_CLIENT_CLASS_EXTERN QPID_CLASS_EXPORT
+# define QPID_CLIENT_INLINE_EXTERN QPID_INLINE_EXPORT
+#else
+# define QPID_CLIENT_EXTERN QPID_IMPORT
+# define QPID_CLIENT_CLASS_EXTERN QPID_CLASS_IMPORT
+# define QPID_CLIENT_INLINE_EXTERN QPID_INLINE_IMPORT
+#endif
+
+#endif
diff --git a/qpid/cpp/src/qpid/client/Completion.h b/qpid/cpp/src/qpid/client/Completion.h
new file mode 100644
index 0000000000..9546db9258
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/Completion.h
@@ -0,0 +1,71 @@
+#ifndef QPID_CLIENT_COMPLETION_H
+#define QPID_CLIENT_COMPLETION_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/Handle.h"
+#include "qpid/client/ClientImportExport.h"
+#include <string>
+
+namespace qpid {
+namespace client {
+
+class CompletionImpl;
+template <class T> class PrivateImplRef;
+
+/**
+ * Asynchronous commands that do not return a result will return a
+ * Completion. You can use the completion to wait for that specific
+ * command to complete.
+ *
+ *@see TypedResult
+ *
+ *\ingroup clientapi
+ */
+class QPID_CLIENT_CLASS_EXTERN Completion : public Handle<CompletionImpl>
+{
+public:
+ QPID_CLIENT_EXTERN Completion(CompletionImpl* = 0);
+ QPID_CLIENT_EXTERN Completion(const Completion&);
+ QPID_CLIENT_EXTERN ~Completion();
+ QPID_CLIENT_EXTERN Completion& operator=(const Completion&);
+
+ /** Wait for the asynchronous command that returned this
+ *Completion to complete.
+ *
+ *@exception If the command returns an error.
+ */
+ QPID_CLIENT_EXTERN void wait();
+ QPID_CLIENT_EXTERN bool isComplete();
+
+ protected:
+ QPID_CLIENT_EXTERN std::string getResult();
+
+ private:
+ typedef CompletionImpl Impl;
+ friend class PrivateImplRef<Completion>;
+};
+
+}}
+
+
+#endif /*!QPID_CLIENT_COMPLETION_H*/
diff --git a/qpid/cpp/src/qpid/client/Connection.cpp b/qpid/cpp/src/qpid/client/Connection.cpp
index 8b4eafccaa..26e69233af 100644
--- a/qpid/cpp/src/qpid/client/Connection.cpp
+++ b/qpid/cpp/src/qpid/client/Connection.cpp
@@ -127,7 +127,7 @@ void Connection::open(const ConnectionSettings& settings)
impl->registerFailureCallback ( failureCallback );
}
-const ConnectionSettings& Connection::getNegotiatedSettings()
+const ConnectionSettings& Connection::getNegotiatedSettings() const
{
if (!isOpen())
throw Exception(QPID_MSG("Connection is not open."));
diff --git a/qpid/cpp/src/qpid/client/Connection.h b/qpid/cpp/src/qpid/client/Connection.h
new file mode 100644
index 0000000000..fb502cb40a
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/Connection.h
@@ -0,0 +1,228 @@
+#ifndef QPID_CLIENT_CONNECTION_H
+#define QPID_CLIENT_CONNECTION_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include <map>
+#include <string>
+#include "qpid/client/Session.h"
+#include "qpid/client/ClientImportExport.h"
+#include "qpid/client/ConnectionSettings.h"
+#include "qpid/framing/ProtocolVersion.h"
+
+#include "boost/function.hpp"
+
+namespace qpid {
+
+struct Url;
+
+namespace client {
+
+class ConnectionImpl;
+
+/**
+ * Represents a connection to an AMQP broker. All communication is
+ * initiated by establishing a connection, then creating one or more
+ * Session objects using the connection. @see newSession()
+ *
+ * \ingroup clientapi
+ *
+ * Some methods use an AMQP 0-10 URL to specify connection parameters.
+ * This is defined in the AMQP 0-10 specification (http://jira.amqp.org/confluence/display/AMQP/AMQP+Specification).
+ *
+ * amqp_url = "amqp:" prot_addr_list
+ * prot_addr_list = [prot_addr ","]* prot_addr
+ * prot_addr = tcp_prot_addr | tls_prot_addr
+ *
+ * tcp_prot_addr = tcp_id tcp_addr
+ * tcp_id = "tcp:" | ""
+ * tcp_addr = [host [":" port] ]
+ * host = <as per http://www.ietf.org/rfc/rfc3986.txt>
+ * port = number]]>
+ *
+ */
+
+class QPID_CLIENT_CLASS_EXTERN Connection
+{
+ framing::ProtocolVersion version;
+
+ boost::function<void ()> failureCallback;
+
+
+ protected:
+ boost::shared_ptr<ConnectionImpl> impl;
+
+
+ public:
+ /**
+ * Creates a Connection object, but does not open the connection.
+ * @see open()
+ */
+ QPID_CLIENT_EXTERN Connection();
+
+ /**
+ * Destroys a Connection object but does not close the connection if it
+ * was open. @see close()
+ */
+ QPID_CLIENT_EXTERN ~Connection();
+
+ /**
+ * Opens a connection to a broker.
+ *
+ * @param host the host on which the broker is running.
+ *
+ * @param port the port on the which the broker is listening.
+ *
+ * @param uid the userid to connect with.
+ *
+ * @param pwd the password to connect with (currently SASL
+ * PLAIN is the only authentication method supported so this
+ * is sent in clear text).
+ *
+ * @param virtualhost the AMQP virtual host to use (virtual
+ * hosts, where implemented(!), provide namespace partitioning
+ * within a single broker).
+ */
+ QPID_CLIENT_EXTERN void open(const std::string& host, int port = 5672,
+ const std::string& uid = "",
+ const std::string& pwd = "",
+ const std::string& virtualhost = "/", uint16_t maxFrameSize=65535);
+
+ /**
+ * Opens a connection to a broker using a URL.
+ * If the URL contains multiple addresses, try each in turn
+ * till connection is successful.
+ *
+ * @url address of the broker to connect to.
+ *
+ * @param uid the userid to connect with.
+ *
+ * @param pwd the password to connect with (currently SASL
+ * PLAIN is the only authentication method supported so this
+ * is sent in clear text).
+ *
+ * @param virtualhost the AMQP virtual host to use (virtual
+ * hosts, where implemented(!), provide namespace partitioning
+ * within a single broker).
+ */
+ QPID_CLIENT_EXTERN void open(const Url& url,
+ const std::string& uid = "",
+ const std::string& pwd = "",
+ const std::string& virtualhost = "/", uint16_t maxFrameSize=65535);
+
+ /**
+ * Opens a connection to a broker using a URL.
+ * If the URL contains multiple addresses, try each in turn
+ * till connection is successful.
+ *
+ * @url address of the broker to connect to.
+ *
+ * @param settings used for any settings not provided by the URL.
+ * Settings provided by the url (e.g. host, port) are ignored.
+ */
+ QPID_CLIENT_EXTERN void open(const Url& url, const ConnectionSettings& settings);
+
+ /**
+ * Opens a connection to a broker.
+ *
+ * @param the settings to use (host, port etc). @see ConnectionSettings.
+ */
+ QPID_CLIENT_EXTERN void open(const ConnectionSettings& settings);
+
+ /**
+ * Close the connection.
+ *
+ * Any further use of this connection (without reopening it) will
+ * not succeed.
+ */
+ QPID_CLIENT_EXTERN void close();
+
+ /**
+ * Create a new session on this connection. Sessions allow
+ * multiple streams of work to be multiplexed over the same
+ * connection. The returned Session provides functions to send
+ * commands to the broker.
+ *
+ * Session functions are synchronous. In other words, a Session
+ * function will send a command to the broker and does not return
+ * until it receives the broker's response confirming the command
+ * was executed.
+ *
+ * AsyncSession provides asynchronous versions of the same
+ * functions. These functions send a command to the broker but do
+ * not wait for a response.
+ *
+ * You can convert a Session s into an AsyncSession as follows:
+ * @code
+ * #include <qpid/client/AsyncSession.h>
+ * AsyncSession as = async(s);
+ * @endcode
+ *
+ * You can execute a single command asynchronously will a Session s
+ * like ths:
+ * @code
+ * async(s).messageTransfer(...);
+ * @endcode
+ *
+ * Using an AsyncSession is faster for sending large numbers of
+ * commands, since each command is sent as soon as possible
+ * without waiting for the previous command to be confirmed.
+ *
+ * However with AsyncSession you cannot assume that a command has
+ * completed until you explicitly synchronize. The simplest way to
+ * do this is to call Session::sync() or AsyncSession::sync().
+ * Both of these functions wait for the broker to confirm all
+ * commands issued so far on the session.
+ *
+ *@param name: A name to identify the session. @see qpid::SessionId
+ * If the name is empty (the default) then a unique name will be
+ * chosen using a Universally-unique identifier (UUID) algorithm.
+ */
+ QPID_CLIENT_EXTERN Session newSession(const std::string& name=std::string(), uint32_t timeoutSeconds = 0);
+
+ /**
+ * Resume a suspended session. A session may be resumed
+ * on a different connection to the one that created it.
+ */
+ QPID_CLIENT_EXTERN void resume(Session& session);
+
+ QPID_CLIENT_EXTERN bool isOpen() const;
+
+ /** In a cluster, returns the initial set of known broker URLs
+ * at the time of connection.
+ */
+ QPID_CLIENT_EXTERN std::vector<Url> getInitialBrokers();
+
+ QPID_CLIENT_EXTERN void registerFailureCallback ( boost::function<void ()> fn );
+
+ /**
+ * Return the set of client negotiated settings
+ */
+ QPID_CLIENT_EXTERN const ConnectionSettings& getNegotiatedSettings() const;
+
+ friend struct ConnectionAccess; ///<@internal
+ friend class SessionBase_0_10; ///<@internal
+};
+
+}} // namespace qpid::client
+
+
+#endif /*!QPID_CLIENT_CONNECTION_H*/
diff --git a/qpid/cpp/src/qpid/client/ConnectionHandler.cpp b/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
index 4f88cb97ee..3ee3f1cd40 100644
--- a/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
+++ b/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
@@ -50,6 +50,7 @@ using qpid::sys::Mutex;
namespace {
const std::string OK("OK");
const std::string PLAIN("PLAIN");
+const std::string ANONYMOUS("ANONYMOUS");
const std::string en_US("en_US");
const std::string INVALID_STATE_START("start received in invalid state");
@@ -244,6 +245,7 @@ void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& me
std::vector<std::string> mechlist;
mechlist.reserve(mechanisms.size());
+
if (mechanism.empty()) {
//mechlist is simply what the server offers
std::transform(mechanisms.begin(), mechanisms.end(), std::back_inserter(mechlist), Array::get<std::string, Array::ValuePtr>);
@@ -273,9 +275,25 @@ void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& me
proxy.send(body);
}
} else {
- //TODO: verify that desired mechanism and locale are supported
- std::string response = ((char)0) + username + ((char)0) + password;
- proxy.startOk(properties, mechanism, response, locale);
+ bool haveAnonymous(false);
+ bool havePlain(false);
+ for (std::vector<std::string>::const_iterator i = mechlist.begin(); i != mechlist.end(); ++i) {
+ if (*i == ANONYMOUS) {
+ haveAnonymous = true;
+ break;
+ } else if (*i == PLAIN) {
+ havePlain = true;
+ }
+ }
+ if (haveAnonymous && (mechanism.empty() || mechanism.find(ANONYMOUS) != std::string::npos)) {
+ proxy.startOk(properties, ANONYMOUS, username, locale);
+ } else if (havePlain && (mechanism.empty() || mechanism.find(PLAIN) !=std::string::npos)) {
+ std::string response = ((char)0) + username + ((char)0) + password;
+ proxy.startOk(properties, PLAIN, response, locale);
+ } else {
+ if (!mechanism.empty()) throw Exception(QPID_MSG("Desired mechanism(s) not valid: " << mechanism << "; client supports PLAIN or ANONYMOUS, broker supports: " << join(mechlist)));
+ throw Exception(QPID_MSG("No valid mechanism; client supports PLAIN or ANONYMOUS, broker supports: " << join(mechlist)));
+ }
}
}
diff --git a/qpid/cpp/src/qpid/client/ConnectionSettings.h b/qpid/cpp/src/qpid/client/ConnectionSettings.h
new file mode 100644
index 0000000000..a0c209badf
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/ConnectionSettings.h
@@ -0,0 +1,140 @@
+#ifndef QPID_CLIENT_CONNECTIONSETTINGS_H
+#define QPID_CLIENT_CONNECTIONSETTINGS_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/ClientImportExport.h"
+#include "qpid/framing/FieldTable.h"
+#include "qpid/sys/IntegerTypes.h"
+#include <string>
+
+namespace qpid {
+
+namespace sys {
+class Socket;
+}
+
+namespace client {
+
+/**
+ * Settings for a Connection.
+ */
+struct QPID_CLIENT_CLASS_EXTERN ConnectionSettings {
+
+ QPID_CLIENT_EXTERN ConnectionSettings();
+ QPID_CLIENT_EXTERN virtual ~ConnectionSettings();
+
+ /**
+ * Allows socket to be configured; default only sets tcp-nodelay
+ * based on the flag set. Can be overridden.
+ */
+ QPID_CLIENT_EXTERN virtual void configureSocket(qpid::sys::Socket&) const;
+
+ /**
+ * The protocol used for the connection (defaults to 'tcp')
+ */
+ std::string protocol;
+
+ /**
+ * The host (or ip address) to connect to (defaults to 'localhost').
+ */
+ std::string host;
+ /**
+ * The port to connect to (defaults to 5672).
+ */
+ uint16_t port;
+ /**
+ * Allows an AMQP 'virtual host' to be specified for the
+ * connection.
+ */
+ std::string virtualhost;
+
+ /**
+ * The username to use when authenticating the connection. If not
+ * specified the current users login is used if available.
+ */
+ std::string username;
+ /**
+ * The password to use when authenticating the connection.
+ */
+ std::string password;
+ /**
+ * The SASL mechanism to use when authenticating the connection;
+ * the options are currently PLAIN or ANONYMOUS.
+ */
+ std::string mechanism;
+ /**
+ * Allows a locale to be specified for the connection.
+ */
+ std::string locale;
+ /**
+ * Allows a heartbeat frequency to be specified
+ */
+ uint16_t heartbeat;
+ /**
+ * The maximum number of channels that the client will request for
+ * use on this connection.
+ */
+ uint16_t maxChannels;
+ /**
+ * The maximum frame size that the client will request for this
+ * connection.
+ */
+ uint16_t maxFrameSize;
+ /**
+ * Limit the size of the connections send buffer . The buffer
+ * is limited to bounds * maxFrameSize.
+ */
+ unsigned int bounds;
+ /**
+ * If true, TCP_NODELAY will be set for the connection.
+ */
+ bool tcpNoDelay;
+ /**
+ * SASL service name
+ */
+ std::string service;
+ /**
+ * Minimum acceptable strength of any SASL negotiated security
+ * layer. 0 means no security layer required.
+ */
+ unsigned int minSsf;
+ /**
+ * Maximum acceptable strength of any SASL negotiated security
+ * layer. 0 means no security layer allowed.
+ */
+ unsigned int maxSsf;
+ /**
+ * SSL cert-name for the connection. Overrides global SSL
+ * settings. Used only when a client connects to the broker.
+ */
+ std::string sslCertName;
+
+ /**
+ * Passed as client-propreties on opening the connecction.
+ */
+ framing::FieldTable clientProperties;
+};
+
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_CONNECTIONSETTINGS_H*/
diff --git a/qpid/cpp/src/qpid/client/FailoverListener.h b/qpid/cpp/src/qpid/client/FailoverListener.h
new file mode 100644
index 0000000000..53c7c26211
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/FailoverListener.h
@@ -0,0 +1,88 @@
+#ifndef QPID_CLIENT_FAILOVERLISTENER_H
+#define QPID_CLIENT_FAILOVERLISTENER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/ClientImportExport.h"
+#include "qpid/client/MessageListener.h"
+#include "qpid/client/Connection.h"
+#include "qpid/client/Session.h"
+#include "qpid/client/SubscriptionManager.h"
+#include "qpid/Url.h"
+#include "qpid/sys/Mutex.h"
+#include "qpid/sys/Runnable.h"
+#include "qpid/sys/Thread.h"
+#include <vector>
+
+namespace qpid {
+namespace client {
+
+
+/**
+ * Listen for updates from the amq.failover exchange.
+ *
+ * In a cluster, the amq.failover exchange provides updates whenever
+ * the cluster membership changes. This class subscribes to the
+ * failover exchange and providees the latest list of known brokers.
+ *
+ * You can also subscribe to amq.failover yourself and use
+ * FailoverListener::decode to extract a list of broker URLs from a
+ * failover exchange message.
+ */
+class QPID_CLIENT_CLASS_EXTERN FailoverListener : private MessageListener, private qpid::sys::Runnable
+{
+ public:
+ /** The name of the standard failover exchange amq.failover */
+ static QPID_CLIENT_EXTERN const std::string AMQ_FAILOVER;
+
+ /** Extract the broker list from a failover exchange message */
+ static QPID_CLIENT_EXTERN std::vector<Url> getKnownBrokers(const Message& m);
+
+ /** Subscribe to amq.failover exchange. */
+ QPID_CLIENT_EXTERN FailoverListener(Connection);
+
+ /** Subscribe to amq.failover exchange.
+ *@param useInitial If true use the connection's initial brokers as
+ * the initial value of getKnownBrokers
+ */
+ QPID_CLIENT_EXTERN FailoverListener(Connection, bool useInitial);
+
+ QPID_CLIENT_EXTERN ~FailoverListener();
+
+ /** Returns the latest list of known broker URLs. */
+ QPID_CLIENT_EXTERN std::vector<Url> getKnownBrokers() const;
+
+ private:
+ void received(Message& msg);
+ void run();
+ void init(bool);
+
+ mutable sys::Mutex lock;
+ Connection connection;
+ Session session;
+ SubscriptionManager subscriptions;
+ sys::Thread thread;
+ std::vector<Url> knownBrokers;
+};
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_FAILOVERLISTENER_H*/
diff --git a/qpid/cpp/src/qpid/client/FailoverManager.h b/qpid/cpp/src/qpid/client/FailoverManager.h
new file mode 100644
index 0000000000..bc739fd0f5
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/FailoverManager.h
@@ -0,0 +1,138 @@
+#ifndef QPID_CLIENT_FAILOVERMANAGER_H
+#define QPID_CLIENT_FAILOVERMANAGER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/Exception.h"
+#include "qpid/client/AsyncSession.h"
+#include "qpid/client/ClientImportExport.h"
+#include "qpid/client/Connection.h"
+#include "qpid/client/ConnectionSettings.h"
+#include "qpid/client/FailoverListener.h"
+#include "qpid/sys/Monitor.h"
+#include <vector>
+
+namespace qpid {
+namespace client {
+
+struct CannotConnectException : qpid::Exception
+{
+ CannotConnectException(const std::string& m) : qpid::Exception(m) {}
+};
+
+/**
+ * Utility to manage failover.
+ */
+class QPID_CLIENT_CLASS_EXTERN FailoverManager
+{
+ public:
+ /**
+ * Interface to implement for doing work that can be resumed on
+ * failover
+ */
+ struct Command
+ {
+ /**
+ * This method will be called with isRetry=false when the
+ * command is first executed. The session to use for the work
+ * will be passed to the implementing class. If the connection
+ * fails while the execute call is in progress, the
+ * FailoverManager controlling the execution will re-establish
+ * a connection, open a new session and call back to the
+ * Command implementations execute method with the new session
+ * and isRetry=true.
+ */
+ virtual void execute(AsyncSession& session, bool isRetry) = 0;
+ virtual ~Command() {}
+ };
+
+ struct ReconnectionStrategy
+ {
+ /**
+ * This method is called by the FailoverManager prior to
+ * establishing a connection (or re-connection) and can be
+ * used if the application wishes to edit or re-order the list
+ * which will default to the list of known brokers for the
+ * last connection.
+ */
+ virtual void editUrlList(std::vector<Url>& urls) = 0;
+ virtual ~ReconnectionStrategy() {}
+ };
+
+ /**
+ * Create a manager to control failover for a logical connection.
+ *
+ * @param settings the initial connection settings
+ * @param strategy optional stratgey callback allowing application
+ * to edit or reorder the list of urls to which reconnection is
+ * attempted
+ */
+ QPID_CLIENT_EXTERN FailoverManager(const ConnectionSettings& settings, ReconnectionStrategy* strategy = 0);
+ QPID_CLIENT_EXTERN ~FailoverManager();
+ /**
+ * Return the current connection if open or attept to reconnect to
+ * the specified list of urls. If no list is specified the list of
+ * known brokers from the last connection will be used. If no list
+ * is specified and this is the first connect attempt, the host
+ * and port from the initial settings will be used.
+ *
+ * If the full list is tried and all attempts fail,
+ * CannotConnectException is thrown.
+ */
+ QPID_CLIENT_EXTERN Connection& connect(std::vector<Url> brokers = std::vector<Url>());
+ /**
+ * Return the current connection whether open or not
+ */
+ QPID_CLIENT_EXTERN Connection& getConnection();
+ /**
+ * Close the current connection
+ */
+ QPID_CLIENT_EXTERN void close();
+ /**
+ * Reliably execute the specified command. This involves creating
+ * a session on which to carry out the work of the command,
+ * handling failover occuring while exeuting that command and
+ * re-starting the work.
+ *
+ * Multiple concurrent threads can call execute with different
+ * commands; each thread will be allocated its own
+ * session. FailoverManager will coordinate the different threads
+ * on failover to ensure they continue to use the same logical
+ * connection.
+ */
+ QPID_CLIENT_EXTERN void execute(Command&);
+ private:
+ enum State {IDLE, CONNECTING, CANT_CONNECT};
+
+ qpid::sys::Monitor lock;
+ Connection connection;
+ std::auto_ptr<FailoverListener> failoverListener;
+ ConnectionSettings settings;
+ ReconnectionStrategy* strategy;
+ State state;
+
+ void attempt(Connection&, ConnectionSettings settings, std::vector<Url> urls);
+ void attempt(Connection&, ConnectionSettings settings);
+};
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_FAILOVERMANAGER_H*/
diff --git a/qpid/cpp/src/qpid/client/FlowControl.h b/qpid/cpp/src/qpid/client/FlowControl.h
new file mode 100644
index 0000000000..bff7071b3b
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/FlowControl.h
@@ -0,0 +1,75 @@
+#ifndef QPID_CLIENT_FLOWCONTROL_H
+#define QPID_CLIENT_FLOWCONTROL_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <qpid/sys/IntegerTypes.h>
+
+namespace qpid {
+namespace client {
+
+/**
+ * Flow control works by associating a finite amount of "credit"
+ * with a subscription.
+ *
+ * Credit includes a message count and a byte count. Each message
+ * received decreases the message count by one, and the byte count by
+ * the size of the message. Either count can have the special value
+ * UNLIMITED which is never decreased.
+ *
+ * A subscription's credit is exhausted when the message count is 0 or
+ * the byte count is too small for the next available message. The
+ * subscription will not receive any further messages until is credit
+ * is renewed.
+ *
+ * In "window mode" credit is automatically renewed when a message is
+ * completed (which by default happens when it is accepted). In
+ * non-window mode credit is not automatically renewed, it must be
+ * explicitly re-set (@see Subscription)
+ */
+struct FlowControl {
+ static const uint32_t UNLIMITED=0xFFFFFFFF;
+ FlowControl(uint32_t messages_=0, uint32_t bytes_=0, bool window_=false)
+ : messages(messages_), bytes(bytes_), window(window_) {}
+
+ static FlowControl messageCredit(uint32_t messages_) { return FlowControl(messages_,UNLIMITED,false); }
+ static FlowControl messageWindow(uint32_t messages_) { return FlowControl(messages_,UNLIMITED,true); }
+ static FlowControl byteCredit(uint32_t bytes_) { return FlowControl(UNLIMITED,bytes_,false); }
+ static FlowControl byteWindow(uint32_t bytes_) { return FlowControl(UNLIMITED,bytes_,true); }
+ static FlowControl unlimited() { return FlowControl(UNLIMITED, UNLIMITED, false); }
+ static FlowControl zero() { return FlowControl(0, 0, false); }
+
+ /** Message credit: subscription can accept up to this many messages. */
+ uint32_t messages;
+ /** Byte credit: subscription can accept up to this many bytes of message content. */
+ uint32_t bytes;
+ /** Window mode. If true credit is automatically renewed as messages are acknowledged. */
+ bool window;
+
+ bool operator==(const FlowControl& x) {
+ return messages == x.messages && bytes == x.bytes && window == x.window;
+ };
+};
+
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_FLOWCONTROL_H*/
diff --git a/qpid/cpp/src/qpid/client/Future.h b/qpid/cpp/src/qpid/client/Future.h
new file mode 100644
index 0000000000..630a7e03c0
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/Future.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#ifndef _Future_
+#define _Future_
+
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include "qpid/Exception.h"
+#include "qpid/framing/SequenceNumber.h"
+#include "qpid/client/FutureCompletion.h"
+#include "qpid/client/FutureResult.h"
+#include "qpid/client/ClientImportExport.h"
+
+namespace qpid {
+namespace client {
+
+/**@internal */
+class QPID_CLIENT_CLASS_EXTERN Future
+{
+ framing::SequenceNumber command;
+ boost::shared_ptr<FutureResult> result;
+ bool complete;
+
+public:
+ Future() : complete(false) {}
+ Future(const framing::SequenceNumber& id) : command(id), complete(false) {}
+
+ std::string getResult(SessionImpl& session) {
+ if (result) return result->getResult(session);
+ else throw Exception("Result not expected");
+ }
+
+ QPID_CLIENT_EXTERN void wait(SessionImpl& session);
+ QPID_CLIENT_EXTERN bool isComplete(SessionImpl& session);
+ QPID_CLIENT_EXTERN void setFutureResult(boost::shared_ptr<FutureResult> r);
+};
+
+}}
+
+#endif
diff --git a/qpid/cpp/src/qmf/engine/MessageImpl.cpp b/qpid/cpp/src/qpid/client/FutureCompletion.h
index 0047d3eb9d..0970f494b7 100644
--- a/qpid/cpp/src/qmf/engine/MessageImpl.cpp
+++ b/qpid/cpp/src/qpid/client/FutureCompletion.h
@@ -1,4 +1,5 @@
/*
+ *
* 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
@@ -6,38 +7,43 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
+ *
*/
-#include "qmf/engine/MessageImpl.h"
-#include <string.h>
+#ifndef _FutureCompletion_
+#define _FutureCompletion_
-using namespace std;
-using namespace qmf::engine;
+#include "qpid/framing/amqp_framing.h"
+#include "qpid/sys/Monitor.h"
-#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());}
+namespace qpid {
+namespace client {
-Message MessageImpl::copy()
+///@internal
+class FutureCompletion
{
- Message item;
+protected:
+ mutable sys::Monitor lock;
+ bool complete;
- ::memset(&item, 0, sizeof(Message));
- item.body = const_cast<char*>(body.c_str());
- item.length = body.length();
- STRING_REF(destination);
- STRING_REF(routingKey);
- STRING_REF(replyExchange);
- STRING_REF(replyKey);
- STRING_REF(userId);
+public:
+ FutureCompletion();
+ virtual ~FutureCompletion(){}
+ bool isComplete() const;
+ void waitForCompletion() const;
+ void completed();
+};
- return item;
-}
+}}
+
+#endif
diff --git a/qpid/cpp/src/qpid/client/FutureResult.h b/qpid/cpp/src/qpid/client/FutureResult.h
new file mode 100644
index 0000000000..ead4929571
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/FutureResult.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#ifndef _FutureResult_
+#define _FutureResult_
+
+#include <string>
+
+#include "qpid/client/ClientImportExport.h"
+#include "qpid/framing/amqp_framing.h"
+#include "qpid/client/FutureCompletion.h"
+
+namespace qpid {
+namespace client {
+
+class SessionImpl;
+
+///@internal
+class QPID_CLIENT_CLASS_EXTERN FutureResult : public FutureCompletion
+{
+ std::string result;
+public:
+ QPID_CLIENT_EXTERN const std::string& getResult(SessionImpl& session) const;
+ void received(const std::string& result);
+};
+
+}}
+
+
+
+#endif
diff --git a/qpid/cpp/src/qpid/client/Handle.h b/qpid/cpp/src/qpid/client/Handle.h
new file mode 100644
index 0000000000..b8315481a9
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/Handle.h
@@ -0,0 +1,71 @@
+#ifndef QPID_CLIENT_HANDLE_H
+#define QPID_CLIENT_HANDLE_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/ClientImportExport.h"
+
+namespace qpid {
+namespace client {
+
+template <class> class PrivateImplRef;
+
+/**
+ * A handle is like a pointer: refers to an underlying implementation object.
+ * Copying the handle does not copy the object.
+ *
+ * Handles can be null, like a 0 pointer. Use isValid(), isNull() or the
+ * conversion to bool to test for a null handle.
+ */
+template <class T> class Handle {
+ public:
+
+ /**@return true if handle is valid, i.e. not null. */
+ QPID_CLIENT_INLINE_EXTERN bool isValid() const { return impl; }
+
+ /**@return true if handle is null. It is an error to call any function on a null handle. */
+ QPID_CLIENT_INLINE_EXTERN bool isNull() const { return !impl; }
+
+ /** Conversion to bool supports idiom if (handle) { handle->... } */
+ QPID_CLIENT_INLINE_EXTERN operator bool() const { return impl; }
+
+ /** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */
+ QPID_CLIENT_INLINE_EXTERN bool operator !() const { return !impl; }
+
+ void swap(Handle<T>& h) { T* t = h.impl; h.impl = impl; impl = t; }
+
+ protected:
+ typedef T Impl;
+ QPID_CLIENT_INLINE_EXTERN Handle() :impl() {}
+
+ // Not implemented,subclasses must implement.
+ QPID_CLIENT_EXTERN Handle(const Handle&);
+ QPID_CLIENT_EXTERN Handle& operator=(const Handle&);
+
+ Impl* impl;
+
+ friend class PrivateImplRef<T>; // FIXME aconway 2009-04-30: Specify
+};
+
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_HANDLE_H*/
diff --git a/qpid/cpp/src/qpid/client/LocalQueue.h b/qpid/cpp/src/qpid/client/LocalQueue.h
new file mode 100644
index 0000000000..1a19a8499d
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/LocalQueue.h
@@ -0,0 +1,120 @@
+#ifndef QPID_CLIENT_LOCALQUEUE_H
+#define QPID_CLIENT_LOCALQUEUE_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/ClientImportExport.h"
+#include "qpid/client/Handle.h"
+#include "qpid/client/Message.h"
+#include "qpid/sys/Time.h"
+
+namespace qpid {
+namespace client {
+
+class LocalQueueImpl;
+template <class T> class PrivateImplRef;
+
+/**
+ * A local queue to collect messages retrieved from a remote broker
+ * queue. Create a queue and subscribe it using the SubscriptionManager.
+ * Messages from the remote queue on the broker will be stored in the
+ * local queue until you retrieve them.
+ *
+ * \ingroup clientapi
+ *
+ * \details Using a Local Queue
+ *
+ * <pre>
+ * LocalQueue local_queue;
+ * subscriptions.subscribe(local_queue, string("message_queue"));
+ * for (int i=0; i&lt;10; i++) {
+ * Message message = local_queue.get();
+ * std::cout &lt;&lt; message.getData() &lt;&lt; std::endl;
+ * }
+ * </pre>
+ *
+ * <h2>Getting Messages</h2>
+ *
+ * <ul><li>
+ * <p>get()</p>
+ * <pre>Message message = local_queue.get();</pre>
+ * <pre>// Specifying timeouts (TIME_SEC, TIME_MSEC, TIME_USEC, TIME_NSEC)
+ *#include <qpid/sys/Time.h>
+ *Message message;
+ *local_queue.get(message, 5*sys::TIME_SEC);</pre></li></ul>
+ *
+ * <h2>Checking size</h2>
+ * <ul><li>
+ * <p>empty()</p>
+ * <pre>if (local_queue.empty()) { ... }</pre></li>
+ * <li><p>size()</p>
+ * <pre>std::cout &lt;&lt; local_queue.size();</pre></li>
+ * </ul>
+ */
+
+class QPID_CLIENT_CLASS_EXTERN LocalQueue : public Handle<LocalQueueImpl> {
+ public:
+ /** Create a local queue. Subscribe the local queue to a remote broker
+ * queue with a SubscriptionManager.
+ *
+ * LocalQueue is an alternative to implementing a MessageListener.
+ */
+ QPID_CLIENT_EXTERN LocalQueue();
+ QPID_CLIENT_EXTERN LocalQueue(const LocalQueue&);
+ QPID_CLIENT_EXTERN ~LocalQueue();
+ QPID_CLIENT_EXTERN LocalQueue& operator=(const LocalQueue&);
+
+ /** Wait up to timeout for the next message from the local queue.
+ *@param result Set to the message from the queue.
+ *@param timeout wait up this timeout for a message to appear.
+ *@return true if result was set, false if queue was empty after timeout.
+ */
+ QPID_CLIENT_EXTERN bool get(Message& result, sys::Duration timeout=0);
+
+ /** Get the next message off the local queue, or wait up to the timeout
+ * for message from the broker queue.
+ *@param timeout wait up this timeout for a message to appear.
+ *@return message from the queue.
+ *@throw ClosedException if subscription is closed or timeout exceeded.
+ */
+ QPID_CLIENT_EXTERN Message get(sys::Duration timeout=sys::TIME_INFINITE);
+
+ /** Synonym for get() */
+ QPID_CLIENT_EXTERN Message pop(sys::Duration timeout=sys::TIME_INFINITE);
+
+ /** Return true if local queue is empty. */
+ QPID_CLIENT_EXTERN bool empty() const;
+
+ /** Number of messages on the local queue */
+ QPID_CLIENT_EXTERN size_t size() const;
+
+ LocalQueue(LocalQueueImpl*); ///<@internal
+
+
+ private:
+ typedef LocalQueueImpl Impl;
+ friend class PrivateImplRef<LocalQueue>;
+};
+
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_LOCALQUEUE_H*/
diff --git a/qpid/cpp/src/qpid/client/Message.h b/qpid/cpp/src/qpid/client/Message.h
new file mode 100644
index 0000000000..ba50dda9ba
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/Message.h
@@ -0,0 +1,175 @@
+#ifndef QPID_CLIENT_MESSAGE_H
+#define QPID_CLIENT_MESSAGE_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/ClientImportExport.h"
+#include "qpid/framing/MessageProperties.h"
+#include "qpid/framing/DeliveryProperties.h"
+#include <string>
+
+namespace qpid {
+
+namespace framing {
+class FieldTable;
+class SequenceNumber; // FIXME aconway 2009-04-17: remove with getID?
+}
+
+namespace client {
+
+class MessageImpl;
+
+/**
+ * A message sent to or received from the broker.
+ *
+ * \ingroup clientapi
+ * \details
+ *
+ * <h2>Getting and setting message contents</h2>
+ *
+ * <ul>
+ * <li>
+ * <p>getData()</p>
+ * <pre>std::cout &lt;&lt; "Response: " &lt;&lt; message.getData() &lt;&lt; std::endl;</pre>
+ * </li>
+ * <li>
+ * <p>setData()</p>
+ * <pre>message.setData("That's all, folks!");</pre></li>
+ * <li>
+ * <p>appendData()</p>
+ * <pre>message.appendData(" ... let's add a bit more ...");</pre></li>
+ * </ul>
+ *
+ * <h2>Getting and Setting Delivery Properties</h2>
+ *
+ * <ul>
+ * <li>
+ * <p>getDeliveryProperties()</p>
+ * <pre>message.getDeliveryProperties().setRoutingKey("control");</pre>
+ * <pre>message.getDeliveryProperties().setDeliveryMode(PERSISTENT);</pre>
+ * <pre>message.getDeliveryProperties().setPriority(9);</pre>
+ * <pre>message.getDeliveryProperties().setTtl(100);</pre></li>
+ *
+ * <li>
+ * <p>hasDeliveryProperties()</p>
+ * <pre>if (! message.hasDeliveryProperties()) {
+ * ...
+ *}</pre></li>
+ * </ul>
+ *
+ * <h2>Getting and Setting Message Properties</h2>
+ *
+ * <ul>
+ * <li>
+ * <p>getMessageProperties()</p>
+ * <pre>
+ *request.getMessageProperties().setReplyTo(ReplyTo("amq.direct", response_queue.str()));
+ * </pre>
+ * <pre>
+ *routingKey = request.getMessageProperties().getReplyTo().getRoutingKey();
+ *exchange = request.getMessageProperties().getReplyTo().getExchange();
+ * </pre>
+ * <pre>message.getMessageProperties().setContentType("text/plain");</pre>
+ * <pre>message.getMessageProperties().setContentEncoding("text/plain");</pre>
+ * </li>
+ * <li>
+ * <p>hasMessageProperties()</p>
+ * <pre>request.getMessageProperties().hasReplyTo();</pre>
+ * </li>
+ * </ul>
+ *
+ * <h2>Getting and Setting Application Headers</h2>
+ *
+ * <ul>
+ * <li>
+ * <p>getHeaders()</p>
+ * <pre>
+ *message.getHeaders().getString("control");
+ * </pre>
+ * <pre>
+ *message.getHeaders().setString("control","continue");
+ * </pre></li>
+ * </ul>
+ *
+ *
+ */
+class QPID_CLIENT_CLASS_EXTERN Message
+{
+public:
+ /** Create a Message.
+ *@param data Data for the message body.
+ *@param routingKey Passed to the exchange that routes the message.
+ */
+ QPID_CLIENT_EXTERN Message(
+ const std::string& data=std::string(),
+ const std::string& routingKey=std::string());
+ Message(MessageImpl*); ///< @internal
+ QPID_CLIENT_EXTERN Message(const Message&);
+ QPID_CLIENT_EXTERN ~Message();
+ QPID_CLIENT_EXTERN Message& operator=(const Message&);
+ QPID_CLIENT_EXTERN void swap(Message&);
+
+ QPID_CLIENT_EXTERN void setData(const std::string&);
+ QPID_CLIENT_EXTERN const std::string& getData() const;
+ QPID_CLIENT_EXTERN std::string& getData();
+
+ QPID_CLIENT_EXTERN void appendData(const std::string&);
+
+ QPID_CLIENT_EXTERN bool hasMessageProperties() const;
+ QPID_CLIENT_EXTERN framing::MessageProperties& getMessageProperties();
+ QPID_CLIENT_EXTERN const framing::MessageProperties& getMessageProperties() const;
+
+ QPID_CLIENT_EXTERN bool hasDeliveryProperties() const;
+ QPID_CLIENT_EXTERN framing::DeliveryProperties& getDeliveryProperties();
+ QPID_CLIENT_EXTERN const framing::DeliveryProperties& getDeliveryProperties() const;
+
+
+ /** The destination of messages sent to the broker is the exchange
+ * name. The destination of messages received from the broker is
+ * the delivery tag identifyig the local subscription (often this
+ * is the name of the subscribed queue.)
+ */
+ QPID_CLIENT_EXTERN std::string getDestination() const;
+
+ /** Check the redelivered flag. */
+ QPID_CLIENT_EXTERN bool isRedelivered() const;
+ /** Set the redelivered flag. */
+ QPID_CLIENT_EXTERN void setRedelivered(bool redelivered);
+
+ /** Get a modifyable reference to the message headers. */
+ QPID_CLIENT_EXTERN framing::FieldTable& getHeaders();
+
+ /** Get a non-modifyable reference to the message headers. */
+ QPID_CLIENT_EXTERN const framing::FieldTable& getHeaders() const;
+
+ // FIXME aconway 2009-04-17: does this need to be in public API?
+ ///@internal
+ QPID_CLIENT_EXTERN const framing::SequenceNumber& getId() const;
+
+ private:
+ MessageImpl* impl;
+ friend class MessageImpl; // Helper template for implementation
+};
+
+}}
+
+#endif /*!QPID_CLIENT_MESSAGE_H*/
diff --git a/qpid/cpp/src/qpid/client/MessageListener.h b/qpid/cpp/src/qpid/client/MessageListener.h
new file mode 100644
index 0000000000..3ca2fa964a
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/MessageListener.h
@@ -0,0 +1,101 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include <string>
+#include "qpid/client/ClientImportExport.h"
+
+#ifndef _MessageListener_
+#define _MessageListener_
+
+#include "qpid/client/Message.h"
+
+namespace qpid {
+namespace client {
+
+ /**
+ * Implement a subclass of MessageListener and subscribe it using
+ * the SubscriptionManager to receive messages.
+ *
+ * Another way to receive messages is by using a LocalQueue.
+ *
+ * \ingroup clientapi
+ * \details
+ *
+ * <h2>Using a MessageListener</h2>
+ *
+ * <ul>
+ * <li>
+ * <p>The received() function is called when a message arrives:</p>
+ * <pre>virtual void received(Message&amp; message)=0;</pre>
+ * </li>
+ * <li>
+ * <p>Derive your own listener, implement the received() function:</p>
+ * <pre>
+ * class Listener : public MessageListener {
+ * private:
+ * SubscriptionManager&amp; subscriptions;
+ * public:
+ * Listener(SubscriptionManager&amp; subscriptions);
+ * virtual void received(Message&amp; message);
+ * };
+ *
+ * Listener::Listener(SubscriptionManager&amp; subs) : subscriptions(subs)
+ * {}
+ *
+ * void Listener::received(Message&amp; message) {
+ * std::cout &lt;&lt; "Message: " &lt;&lt; message.getData() &lt;&lt; std::endl;
+ * if (message.getData() == "That's all, folks!") {
+ * std::cout &lt;&lt; "Shutting down listener for " &lt;&lt; message.getDestination()
+ * &lt;&lt; std::endl;
+ * subscriptions.cancel(message.getDestination());
+ * }
+ * }
+ *</pre>
+ * <pre>
+ * SubscriptionManager subscriptions(session);
+ *
+ * // Create a listener and subscribe it to the queue named "message_queue"
+ * Listener listener(subscriptions);
+ * subscriptions.subscribe(listener, "message_queue");
+ *
+ * // Receive messages until the subscription is cancelled
+ * // by Listener::received()
+ * subscriptions.run();
+ * </pre>
+ * </li>
+ * </ul>
+ *
+ */
+
+ class QPID_CLIENT_CLASS_EXTERN MessageListener{
+ public:
+ QPID_CLIENT_EXTERN virtual ~MessageListener();
+
+ /** Called for each message arriving from the broker. Override
+ * in your own subclass to process messages.
+ */
+ virtual void received(Message& msg) = 0;
+ };
+
+}
+}
+
+
+#endif
diff --git a/qpid/cpp/src/qpid/client/MessageReplayTracker.h b/qpid/cpp/src/qpid/client/MessageReplayTracker.h
new file mode 100644
index 0000000000..06a3f29c7d
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/MessageReplayTracker.h
@@ -0,0 +1,73 @@
+#ifndef QPID_CLIENT_MESSAGEREPLAYTRACKER_H
+#define QPID_CLIENT_MESSAGEREPLAYTRACKER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/client/AsyncSession.h"
+#include "qpid/client/Message.h"
+#include "qpid/client/ClientImportExport.h"
+#include <list>
+#include <string>
+
+namespace qpid {
+namespace client {
+
+/**
+ * Utility to track messages sent asynchronously, allowing those that
+ * are indoubt to be replayed over a new session.
+ */
+class QPID_CLIENT_CLASS_EXTERN MessageReplayTracker
+{
+ public:
+ QPID_CLIENT_EXTERN MessageReplayTracker(uint flushInterval);
+ QPID_CLIENT_EXTERN void send(const Message& message, const std::string& destination = "");
+ QPID_CLIENT_EXTERN void init(AsyncSession session);
+ QPID_CLIENT_EXTERN void replay(AsyncSession session);
+ QPID_CLIENT_EXTERN void setFlushInterval(uint interval);
+ QPID_CLIENT_EXTERN uint getFlushInterval();
+ QPID_CLIENT_EXTERN void checkCompletion();
+
+ template <class F> void foreach(F& f) {
+ for (std::list<ReplayRecord>::const_iterator i = buffer.begin(); i != buffer.end(); i++) {
+ f(i->message);
+ }
+ }
+
+ private:
+ struct ReplayRecord
+ {
+ Completion status;
+ Message message;
+ std::string destination;
+
+ ReplayRecord(const Message& message, const std::string& destination);
+ void send(MessageReplayTracker&);
+ bool isComplete();
+ };
+
+ AsyncSession session;
+ uint flushInterval;
+ uint count;
+ std::list<ReplayRecord> buffer;
+};
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_MESSAGEREPLAYTRACKER_H*/
diff --git a/qpid/cpp/src/qpid/client/QueueOptions.h b/qpid/cpp/src/qpid/client/QueueOptions.h
new file mode 100644
index 0000000000..3984b63fdd
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/QueueOptions.h
@@ -0,0 +1,129 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/ClientImportExport.h"
+#include "qpid/framing/FieldTable.h"
+
+#ifndef _QueueOptions_
+#define _QueueOptions_
+
+namespace qpid {
+namespace client {
+
+enum QueueSizePolicy {NONE, REJECT, FLOW_TO_DISK, RING, RING_STRICT};
+enum QueueOrderingPolicy {FIFO, LVQ, LVQ_NO_BROWSE};
+
+/**
+ * A help class to set options on the Queue. Create a configured args while
+ * still allowing any custom configuration via the FieldTable base class
+ */
+class QPID_CLIENT_CLASS_EXTERN QueueOptions: public framing::FieldTable
+{
+ public:
+ QPID_CLIENT_EXTERN QueueOptions();
+ QPID_CLIENT_EXTERN virtual ~QueueOptions();
+
+ /**
+ * Sets the queue sizing policy
+ *
+ * @param sp SizePolicy
+ * REJECT - reject if queue greater than size/count
+ * FLOW_TO_DISK - page messages to disk from this point is greater than size/count
+ * RING - limit the queue to size/count and over-write old messages round a ring
+ * RING_STRICT - limit the queue to size/count and reject is head == tail
+ * NONE - Use default broker sizing policy
+ * @param maxSize Set the max number of bytes for the sizing policies
+ * @param setMaxCount Set the max number of messages for the sizing policies
+ */
+ QPID_CLIENT_EXTERN void setSizePolicy(QueueSizePolicy sp, uint64_t maxSize, uint32_t maxCount );
+
+ /**
+ * Enables the persisting of a queue to the store module when a cluster fails down to it's last
+ * node. Does so optimistically. Will start persisting when cluster count >1 again.
+ */
+ QPID_CLIENT_EXTERN void setPersistLastNode();
+
+ /**
+ * Sets the odering policy on the Queue, default ordering is FIFO.
+ */
+ QPID_CLIENT_EXTERN void setOrdering(QueueOrderingPolicy op);
+
+ /**
+ * Use broker defualt sizing ploicy
+ */
+ QPID_CLIENT_EXTERN void clearSizePolicy();
+
+ /**
+ * Clear Persist Last Node Policy
+ */
+ QPID_CLIENT_EXTERN void clearPersistLastNode();
+
+ /**
+ * get the key used match LVQ in args for message transfer
+ */
+ QPID_CLIENT_EXTERN void getLVQKey(std::string& key);
+
+ /**
+ * Use default odering policy
+ */
+ QPID_CLIENT_EXTERN void clearOrdering();
+
+ /**
+ * Turns on event generation for this queue (either enqueue only
+ * or for enqueue and dequeue events); the events can then be
+ * processed by a regsitered broker plugin.
+ *
+ * DEPRECATED
+ *
+ * This is confusing to anyone who sees only the function call
+ * and not the variable name / doxygen. Consider the following call:
+ *
+ * options.enableQueueEvents(false);
+ *
+ * It looks like it disables queue events, but what it really does is
+ * enable both enqueue and dequeue events.
+ *
+ * Use setInt() instead:
+ *
+ * options.setInt("qpid.queue_event_generation", 2);
+ */
+
+ QPID_CLIENT_EXTERN void enableQueueEvents(bool enqueueOnly);
+
+ static QPID_CLIENT_EXTERN const std::string strMaxCountKey;
+ static QPID_CLIENT_EXTERN const std::string strMaxSizeKey;
+ static QPID_CLIENT_EXTERN const std::string strTypeKey;
+ static QPID_CLIENT_EXTERN const std::string strREJECT;
+ static QPID_CLIENT_EXTERN const std::string strFLOW_TO_DISK;
+ static QPID_CLIENT_EXTERN const std::string strRING;
+ static QPID_CLIENT_EXTERN const std::string strRING_STRICT;
+ static QPID_CLIENT_EXTERN const std::string strLastValueQueue;
+ static QPID_CLIENT_EXTERN const std::string strPersistLastNode;
+ static QPID_CLIENT_EXTERN const std::string strLVQMatchProperty;
+ static QPID_CLIENT_EXTERN const std::string strLastValueQueueNoBrowse;
+ static QPID_CLIENT_EXTERN const std::string strQueueEventMode;
+};
+
+}
+}
+
+
+#endif
diff --git a/qpid/cpp/src/qpid/client/Session.h b/qpid/cpp/src/qpid/client/Session.h
new file mode 100644
index 0000000000..c40549bbc5
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/Session.h
@@ -0,0 +1,39 @@
+#ifndef QPID_CLIENT_SESSION_H
+#define QPID_CLIENT_SESSION_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/client/Session_0_10.h"
+
+namespace qpid {
+namespace client {
+
+/**
+ * Session is an alias for Session_0_10
+ *
+ * \ingroup clientapi
+ */
+typedef Session_0_10 Session;
+
+
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_SESSION_H*/
diff --git a/qpid/cpp/src/qpid/client/SessionBase_0_10.h b/qpid/cpp/src/qpid/client/SessionBase_0_10.h
new file mode 100644
index 0000000000..630987c11d
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/SessionBase_0_10.h
@@ -0,0 +1,109 @@
+#ifndef QPID_CLIENT_SESSIONBASE_H
+#define QPID_CLIENT_SESSIONBASE_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/SessionId.h"
+#include "qpid/framing/amqp_structs.h"
+#include "qpid/client/Message.h"
+#include "qpid/client/Completion.h"
+#include "qpid/client/TypedResult.h"
+#include "qpid/client/ClientImportExport.h"
+#include <string>
+
+namespace qpid {
+namespace client {
+
+class Connection;
+class SessionImpl;
+
+using qpid::framing::Content;
+using qpid::framing::FieldTable;
+using qpid::framing::SequenceNumber;
+using qpid::framing::SequenceSet;
+using qpid::framing::SequenceNumberSet;
+using qpid::SessionId;
+using qpid::framing::Xid;
+
+/** Unit of message credit: messages or bytes */
+enum CreditUnit { MESSAGE_CREDIT=0, BYTE_CREDIT=1, UNLIMITED_CREDIT=0xFFFFFFFF };
+
+/**
+ * Base class for handles to an AMQP session.
+ *
+ * Subclasses provide the AMQP commands for a given
+ * version of the protocol.
+ */
+class QPID_CLIENT_CLASS_EXTERN SessionBase_0_10 {
+ public:
+
+ ///@internal
+ QPID_CLIENT_EXTERN SessionBase_0_10();
+ QPID_CLIENT_EXTERN ~SessionBase_0_10();
+
+ /** Get the session ID */
+ QPID_CLIENT_EXTERN SessionId getId() const;
+
+ /** Close the session.
+ * A session is automatically closed when all handles to it are destroyed.
+ */
+ QPID_CLIENT_EXTERN void close();
+
+ /**
+ * Synchronize the session: sync() waits until all commands issued
+ * on this session so far have been completed by the broker.
+ *
+ * Note sync() is always synchronous, even on an AsyncSession object
+ * because that's almost always what you want. You can call
+ * AsyncSession::executionSync() directly in the unusual event
+ * that you want to do an asynchronous sync.
+ */
+ QPID_CLIENT_EXTERN void sync();
+
+ /** Set the timeout for this session. */
+ QPID_CLIENT_EXTERN uint32_t timeout(uint32_t seconds);
+
+ /** Suspend the session - detach it from its connection */
+ QPID_CLIENT_EXTERN void suspend();
+
+ /** Resume a suspended session with a new connection */
+ QPID_CLIENT_EXTERN void resume(Connection);
+
+ /** Get the channel associated with this session */
+ QPID_CLIENT_EXTERN uint16_t getChannel() const;
+
+ QPID_CLIENT_EXTERN void flush();
+ QPID_CLIENT_EXTERN void markCompleted(const framing::SequenceSet& ids, bool notifyPeer);
+ QPID_CLIENT_EXTERN void markCompleted(const framing::SequenceNumber& id, bool cumulative, bool notifyPeer);
+ QPID_CLIENT_EXTERN void sendCompletion();
+
+ QPID_CLIENT_EXTERN bool isValid() const;
+
+ QPID_CLIENT_EXTERN Connection getConnection();
+ protected:
+ boost::shared_ptr<SessionImpl> impl;
+ friend class SessionBase_0_10Access;
+};
+
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_SESSIONBASE_H*/
diff --git a/qpid/cpp/src/qpid/client/Subscription.h b/qpid/cpp/src/qpid/client/Subscription.h
new file mode 100644
index 0000000000..bb9b98e8ff
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/Subscription.h
@@ -0,0 +1,123 @@
+#ifndef QPID_CLIENT_SUBSCRIPTION_H
+#define QPID_CLIENT_SUBSCRIPTION_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/Handle.h"
+#include "qpid/client/Session.h"
+#include "qpid/client/SubscriptionSettings.h"
+#include "qpid/client/Message.h"
+#include "qpid/client/ClientImportExport.h"
+
+namespace qpid {
+namespace client {
+
+template <class> class PrivateImplRef;
+class SubscriptionImpl;
+class SubscriptionManager;
+
+/**
+ * A handle to an active subscription. Provides methods to query the subscription status
+ * and control acknowledgement (acquire and accept) of messages.
+ */
+class QPID_CLIENT_CLASS_EXTERN Subscription : public Handle<SubscriptionImpl> {
+ public:
+ QPID_CLIENT_EXTERN Subscription(SubscriptionImpl* = 0);
+ QPID_CLIENT_EXTERN Subscription(const Subscription&);
+ QPID_CLIENT_EXTERN ~Subscription();
+ QPID_CLIENT_EXTERN Subscription& operator=(const Subscription&);
+
+
+ /** The name of the subscription, used as the "destination" for messages from the broker.
+ * Usually the same as the queue name but can be set differently.
+ */
+ QPID_CLIENT_EXTERN std::string getName() const;
+
+ /** Name of the queue this subscription subscribes to */
+ QPID_CLIENT_EXTERN std::string getQueue() const;
+
+ /** Get the flow control and acknowledgement settings for this subscription */
+ QPID_CLIENT_EXTERN const SubscriptionSettings& getSettings() const;
+
+ /** Set the flow control parameters */
+ QPID_CLIENT_EXTERN void setFlowControl(const FlowControl&);
+
+ /** Automatically acknowledge (acquire and accept) batches of n messages.
+ * You can disable auto-acknowledgement by setting n=0, and use acquire() and accept()
+ * to manually acquire and accept messages.
+ */
+ QPID_CLIENT_EXTERN void setAutoAck(unsigned int n);
+
+ /** Get the set of ID's for messages received by this subscription but not yet acquired.
+ * This will always be empty if getSettings().acquireMode=ACQUIRE_MODE_PRE_ACQUIRED
+ */
+ QPID_CLIENT_EXTERN SequenceSet getUnacquired() const;
+
+ /** Get the set of ID's for messages received by this subscription but not yet accepted. */
+ QPID_CLIENT_EXTERN SequenceSet getUnaccepted() const;
+
+ /** Acquire messageIds and remove them from the unacquired set.
+ * oAdd them to the unaccepted set if getSettings().acceptMode == ACCEPT_MODE_EXPLICIT.
+ */
+ QPID_CLIENT_EXTERN void acquire(const SequenceSet& messageIds);
+
+ /** Accept messageIds and remove them from the unaccepted set.
+ *@pre messageIds is a subset of getUnaccepted()
+ */
+ QPID_CLIENT_EXTERN void accept(const SequenceSet& messageIds);
+
+ /** Release messageIds and remove them from the unaccepted set.
+ *@pre messageIds is a subset of getUnaccepted()
+ */
+ QPID_CLIENT_EXTERN void release(const SequenceSet& messageIds);
+
+ /* Acquire a single message */
+ QPID_CLIENT_INLINE_EXTERN void acquire(const Message& m) { acquire(SequenceSet(m.getId())); }
+
+ /* Accept a single message */
+ QPID_CLIENT_INLINE_EXTERN void accept(const Message& m) { accept(SequenceSet(m.getId())); }
+
+ /* Release a single message */
+ QPID_CLIENT_INLINE_EXTERN void release(const Message& m) { release(SequenceSet(m.getId())); }
+
+ /** Get the session associated with this subscription */
+ QPID_CLIENT_EXTERN Session getSession() const;
+
+ /** Get the subscription manager associated with this subscription */
+ QPID_CLIENT_EXTERN SubscriptionManager getSubscriptionManager();
+
+ /** Cancel the subscription. */
+ QPID_CLIENT_EXTERN void cancel();
+
+ /** Grant the specified amount of message credit */
+ QPID_CLIENT_EXTERN void grantMessageCredit(uint32_t);
+
+ /** Grant the specified amount of byte credit */
+ QPID_CLIENT_EXTERN void grantByteCredit(uint32_t);
+
+ private:
+ friend class PrivateImplRef<Subscription>;
+ friend class SubscriptionManager;
+};
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_SUBSCRIPTION_H*/
diff --git a/qpid/cpp/src/qpid/client/SubscriptionManager.h b/qpid/cpp/src/qpid/client/SubscriptionManager.h
new file mode 100644
index 0000000000..404a9c6eb9
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/SubscriptionManager.h
@@ -0,0 +1,292 @@
+#ifndef QPID_CLIENT_SUBSCRIPTIONMANAGER_H
+#define QPID_CLIENT_SUBSCRIPTIONMANAGER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/Session.h"
+#include "qpid/client/Subscription.h"
+#include "qpid/sys/Runnable.h"
+#include "qpid/sys/Thread.h"
+#include "qpid/client/ClientImportExport.h"
+#include "qpid/client/MessageListener.h"
+#include "qpid/client/LocalQueue.h"
+#include "qpid/client/Handle.h"
+#include <string>
+
+namespace qpid {
+namespace client {
+
+class SubscriptionManagerImpl;
+
+/**
+ * A class to help create and manage subscriptions.
+ *
+ * Set up your subscriptions, then call run() to have messages
+ * delivered.
+ *
+ * \ingroup clientapi
+ *
+ * \details
+ *
+ * <h2>Subscribing and canceling subscriptions</h2>
+ *
+ * <ul>
+ * <li>
+ * <p>subscribe()</p>
+ * <pre> SubscriptionManager subscriptions(session);
+ * Listener listener(subscriptions);
+ * subscriptions.subscribe(listener, myQueue);</pre>
+ * <pre> SubscriptionManager subscriptions(session);
+ * LocalQueue local_queue;
+ * subscriptions.subscribe(local_queue, string("message_queue"));</pre></li>
+ * <li>
+ * <p>cancel()</p>
+ * <pre>subscriptions.cancel();</pre></li>
+ * </ul>
+ *
+ * <h2>Waiting for messages (and returning)</h2>
+ *
+ * <ul>
+ * <li>
+ * <p>run()</p>
+ * <pre> // Give up control to receive messages
+ * subscriptions.run();</pre></li>
+ * <li>
+ * <p>stop()</p>
+ * <pre>.// Use this code in a listener to return from run()
+ * subscriptions.stop();</pre></li>
+ * <li>
+ * <p>setAutoStop()</p>
+ * <pre>.// Return from subscriptions.run() when last subscription is cancelled
+ *.subscriptions.setAutoStop(true);
+ *.subscriptons.run();
+ * </pre></li>
+ * <li>
+ * <p>Ending a subscription in a listener</p>
+ * <pre>
+ * void Listener::received(Message&amp; message) {
+ *
+ * if (message.getData() == "That's all, folks!") {
+ * subscriptions.cancel(message.getDestination());
+ * }
+ * }
+ * </pre>
+ * </li>
+ * </ul>
+ *
+ */
+class QPID_CLIENT_CLASS_EXTERN SubscriptionManager : public sys::Runnable, public Handle<SubscriptionManagerImpl>
+{
+ public:
+ /** Create a new SubscriptionManager associated with a session */
+ QPID_CLIENT_EXTERN SubscriptionManager(const Session& session);
+ QPID_CLIENT_EXTERN SubscriptionManager(const SubscriptionManager&);
+ QPID_CLIENT_EXTERN ~SubscriptionManager();
+ QPID_CLIENT_EXTERN SubscriptionManager& operator=(const SubscriptionManager&);
+
+ /**
+ * Subscribe a MessagesListener to receive messages from queue.
+ *
+ * Provide your own subclass of MessagesListener to process
+ * incoming messages. It will be called for each message received.
+ *
+ *@param listener Listener object to receive messages.
+ *@param queue Name of the queue to subscribe to.
+ *@param settings settings for the subscription.
+ *@param name unique destination name for the subscription, defaults to queue name.
+ */
+ QPID_CLIENT_EXTERN Subscription subscribe(MessageListener& listener,
+ const std::string& queue,
+ const SubscriptionSettings& settings,
+ const std::string& name=std::string());
+
+ /**
+ * Subscribe a LocalQueue to receive messages from queue.
+ *
+ * Incoming messages are stored in the queue for you to retrieve.
+ *
+ *@param queue Name of the queue to subscribe to.
+ *@param flow initial FlowControl for the subscription.
+ *@param name unique destination name for the subscription, defaults to queue name.
+ * If not specified, the queue name is used.
+ */
+ QPID_CLIENT_EXTERN Subscription subscribe(LocalQueue& localQueue,
+ const std::string& queue,
+ const SubscriptionSettings& settings,
+ const std::string& name=std::string());
+
+ /**
+ * Subscribe a MessagesListener to receive messages from queue.
+ *
+ * Provide your own subclass of MessagesListener to process
+ * incoming messages. It will be called for each message received.
+ *
+ *@param listener Listener object to receive messages.
+ *@param queue Name of the queue to subscribe to.
+ *@param name unique destination name for the subscription, defaults to queue name.
+ * If not specified, the queue name is used.
+ */
+ QPID_CLIENT_EXTERN Subscription subscribe(MessageListener& listener,
+ const std::string& queue,
+ const std::string& name=std::string());
+
+ /**
+ * Subscribe a LocalQueue to receive messages from queue.
+ *
+ * Incoming messages are stored in the queue for you to retrieve.
+ *
+ *@param queue Name of the queue to subscribe to.
+ *@param name unique destination name for the subscription, defaults to queue name.
+ * If not specified, the queue name is used.
+ */
+ QPID_CLIENT_EXTERN Subscription subscribe(LocalQueue& localQueue,
+ const std::string& queue,
+ const std::string& name=std::string());
+
+
+ /** Get a single message from a queue.
+ * (Note: this currently uses a subscription per invocation and is
+ * thus relatively expensive. The subscription is cancelled as
+ * part of each call which can trigger auto-deletion).
+ *@param result is set to the message from the queue.
+ *@param timeout wait up this timeout for a message to appear.
+ *@return true if result was set, false if no message available after timeout.
+ */
+ QPID_CLIENT_EXTERN bool get(Message& result, const std::string& queue, sys::Duration timeout=0);
+
+ /** Get a single message from a queue.
+ * (Note: this currently uses a subscription per invocation and is
+ * thus relatively expensive. The subscription is cancelled as
+ * part of each call which can trigger auto-deletion).
+ *@param timeout wait up this timeout for a message to appear.
+ *@return message from the queue.
+ *@throw Exception if the timeout is exceeded.
+ */
+ QPID_CLIENT_EXTERN Message get(const std::string& queue, sys::Duration timeout=sys::TIME_INFINITE);
+
+ /** Get a subscription by name.
+ *@throw Exception if not found.
+ */
+ QPID_CLIENT_EXTERN Subscription getSubscription(const std::string& name) const;
+
+ /** Cancel a subscription. See also: Subscription.cancel() */
+ QPID_CLIENT_EXTERN void cancel(const std::string& name);
+
+ /** Deliver messages in the current thread until stop() is called.
+ * Only one thread may be running in a SubscriptionManager at a time.
+ * @see run
+ */
+ QPID_CLIENT_EXTERN void run();
+
+ /** Start a new thread to deliver messages.
+ * Only one thread may be running in a SubscriptionManager at a time.
+ * @see start
+ */
+ QPID_CLIENT_EXTERN void start();
+
+ /**
+ * Wait for the thread started by a call to start() to complete.
+ */
+ QPID_CLIENT_EXTERN void wait();
+
+ /** If set true, run() will stop when all subscriptions
+ * are cancelled. If false, run will only stop when stop()
+ * is called. True by default.
+ */
+ QPID_CLIENT_EXTERN void setAutoStop(bool set=true);
+
+ /** Stop delivery. Causes run() to return, or the thread started with start() to exit. */
+ QPID_CLIENT_EXTERN void stop();
+
+ static const uint32_t UNLIMITED=0xFFFFFFFF;
+
+ /** Set the flow control for a subscription. */
+ QPID_CLIENT_EXTERN void setFlowControl(const std::string& name, const FlowControl& flow);
+
+ /** Set the flow control for a subscription.
+ *@param name: name of the subscription.
+ *@param messages: message credit.
+ *@param bytes: byte credit.
+ *@param window: if true use window-based flow control.
+ */
+ QPID_CLIENT_EXTERN void setFlowControl(const std::string& name, uint32_t messages, uint32_t bytes, bool window=true);
+
+ /** Set the default settings for subscribe() calls that don't
+ * include a SubscriptionSettings parameter.
+ */
+ QPID_CLIENT_EXTERN void setDefaultSettings(const SubscriptionSettings& s);
+
+ /** Get the default settings for subscribe() calls that don't
+ * include a SubscriptionSettings parameter.
+ */
+ QPID_CLIENT_EXTERN const SubscriptionSettings& getDefaultSettings() const;
+
+ /** Get the default settings for subscribe() calls that don't
+ * include a SubscriptionSettings parameter.
+ */
+ QPID_CLIENT_EXTERN SubscriptionSettings& getDefaultSettings();
+
+ /**
+ * Set the default flow control settings for subscribe() calls
+ * that don't include a SubscriptionSettings parameter.
+ *
+ *@param messages: message credit.
+ *@param bytes: byte credit.
+ *@param window: if true use window-based flow control.
+ */
+ QPID_CLIENT_EXTERN void setFlowControl(uint32_t messages, uint32_t bytes, bool window=true);
+
+ /**
+ *Set the default accept-mode for subscribe() calls that don't
+ *include a SubscriptionSettings parameter.
+ */
+ QPID_CLIENT_EXTERN void setAcceptMode(AcceptMode mode);
+
+ /**
+ * Set the default acquire-mode subscribe()s that don't specify SubscriptionSettings.
+ */
+ QPID_CLIENT_EXTERN void setAcquireMode(AcquireMode mode);
+
+ QPID_CLIENT_EXTERN void registerFailoverHandler ( boost::function<void ()> fh );
+
+ QPID_CLIENT_EXTERN Session getSession() const;
+
+ SubscriptionManager(SubscriptionManagerImpl*); ///<@internal
+
+ private:
+ typedef SubscriptionManagerImpl Impl;
+ friend class PrivateImplRef<SubscriptionManager>;
+};
+
+/** AutoCancel cancels a subscription in its destructor */
+class AutoCancel {
+ public:
+ AutoCancel(SubscriptionManager&, const std::string& tag);
+ ~AutoCancel();
+ private:
+ SubscriptionManager& sm;
+ std::string tag;
+};
+
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_SUBSCRIPTIONMANAGER_H*/
diff --git a/qpid/cpp/src/qpid/client/SubscriptionSettings.h b/qpid/cpp/src/qpid/client/SubscriptionSettings.h
new file mode 100644
index 0000000000..bee39f6816
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/SubscriptionSettings.h
@@ -0,0 +1,135 @@
+#ifndef QPID_CLIENT_SUBSCRIPTIONSETTINGS_H
+#define QPID_CLIENT_SUBSCRIPTIONSETTINGS_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/client/FlowControl.h"
+#include "qpid/framing/enum.h"
+
+namespace qpid {
+namespace client {
+
+/** Bring AMQP enum definitions for message class into this namespace. */
+using qpid::framing::message::AcceptMode;
+using qpid::framing::message::AcquireMode;
+using qpid::framing::message::ACCEPT_MODE_EXPLICIT;
+using qpid::framing::message::ACCEPT_MODE_NONE;
+using qpid::framing::message::ACQUIRE_MODE_NOT_ACQUIRED;
+using qpid::framing::message::ACQUIRE_MODE_PRE_ACQUIRED;
+using qpid::framing::message::CREDIT_UNIT_BYTE;
+using qpid::framing::message::CREDIT_UNIT_MESSAGE;
+using qpid::framing::message::DELIVERY_MODE_NON_PERSISTENT;
+using qpid::framing::message::DELIVERY_MODE_PERSISTENT;
+using qpid::framing::message::FLOW_MODE_CREDIT;
+using qpid::framing::message::FLOW_MODE_WINDOW;
+
+
+enum CompletionMode {
+ MANUAL_COMPLETION = 0,
+ COMPLETE_ON_DELIVERY = 1,
+ COMPLETE_ON_ACCEPT = 2
+};
+/**
+ * Settings for a subscription.
+ */
+struct SubscriptionSettings
+{
+ SubscriptionSettings(
+ FlowControl flow=FlowControl::unlimited(),
+ AcceptMode accept=ACCEPT_MODE_EXPLICIT,
+ AcquireMode acquire=ACQUIRE_MODE_PRE_ACQUIRED,
+ unsigned int autoAck_=1,
+ CompletionMode completion=COMPLETE_ON_DELIVERY
+ ) : flowControl(flow), acceptMode(accept), acquireMode(acquire), autoAck(autoAck_), completionMode(completion), exclusive(false) {}
+
+ FlowControl flowControl; ///@< Flow control settings. @see FlowControl
+ /**
+ * The acceptMode determines whether the broker should expect
+ * delivery of messages to be acknowledged by the client
+ * indicating that it accepts them. A value of
+ * ACCEPT_MODE_EXPLICIT means that messages must be accepted
+ * (note: this may be done automatically by the library - see
+ * autoAck - or through an explicit call be the application - see
+ * Subscription::accept()) before they can be dequeued. A value of
+ * ACCEPT_MODE_NONE means that the broker can dequeue a message as
+ * soon as it is acquired.
+ */
+ AcceptMode acceptMode; ///@< ACCEPT_MODE_EXPLICIT or ACCEPT_MODE_NONE
+ /**
+ * The acquireMode determines whether messages are locked for the
+ * subscriber when delivered, and thus are not delivered to any
+ * other subscriber unless this subscriber releases them.
+ *
+ * The default is ACQUIRE_MODE_PRE_ACQUIRED meaning that the
+ * subscriber expects to have been given that message exclusively
+ * (i.e. the message will not be given to any other subscriber
+ * unless released explicitly or by this subscribers session
+ * failing without having accepted the message).
+ *
+ * Delivery of message in ACQUIRE_MODE_NOT_ACQUIRED mode means the
+ * message will still be available for other subscribers to
+ * receive. The application can if desired acquire a (set of)
+ * messages through an explicit acquire call - see
+ * Subscription::acquire().
+ */
+ AcquireMode acquireMode; ///@< ACQUIRE_MODE_PRE_ACQUIRED or ACQUIRE_MODE_NOT_ACQUIRED
+
+ /**
+ * Configures the frequency at which messages are automatically
+ * accepted (e.g. a value of 5 means that messages are accepted in
+ * batches of 5). A value of 0 means no automatic acknowledgement
+ * will occur and the application will itself be responsible for
+ * accepting messages.
+ */
+ unsigned int autoAck;
+ /**
+ * In windowing mode, completion of a message will cause the
+ * credit used up by that message to be reallocated. The
+ * subscriptions completion mode controls how completion is
+ * managed.
+ *
+ * If set to COMPLETE_ON_DELIVERY (which is the default), messages
+ * will be marked as completed once they have been received. The
+ * server will be explicitly notified of all completed messages
+ * for the session when the next accept is sent through the
+ * subscription (either explictly or through autAck). However the
+ * server may also periodically request information on the
+ * completed messages.
+ *
+ * If set to COMPLETE_ON_ACCEPT, messages will be marked as
+ * completed once they are accepted (via the Subscription class)
+ * and the server will also be notified of all completed messages
+ * for the session.
+ *
+ * If set to MANUAL_COMPLETION the application is responsible for
+ * completing messages (@see Session::markCompleted()).
+ */
+ CompletionMode completionMode;
+ /**
+ * If set, requests that no other subscriber be allowed to access
+ * the queue while this subscription is active.
+ */
+ bool exclusive;
+};
+
+}} // namespace qpid::client
+
+#endif /*!QPID_CLIENT_SUBSCRIPTIONSETTINGS_H*/
diff --git a/qpid/cpp/src/qpid/client/TypedResult.h b/qpid/cpp/src/qpid/client/TypedResult.h
new file mode 100644
index 0000000000..8e1a16580c
--- /dev/null
+++ b/qpid/cpp/src/qpid/client/TypedResult.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#ifndef _TypedResult_
+#define _TypedResult_
+
+#include "qpid/client/Completion.h"
+#include "qpid/framing/StructHelper.h"
+
+namespace qpid {
+namespace client {
+
+/**
+ * Returned by asynchronous commands that return a result.
+ * You can use get() to wait for completion and get the result value.
+ * \ingroup clientapi
+ */
+template <class T> class TypedResult : public Completion
+{
+ T result;
+ bool decoded;
+
+public:
+ ///@internal
+ TypedResult(const Completion& c) : Completion(c), decoded(false) {}
+
+ /**
+ * Wait for the asynchronous command that returned this TypedResult to complete
+ * and return its result.
+ *
+ *@return The result returned by the command.
+ *@exception If the command returns an error, get() throws an exception.
+ *
+ */
+ T& get() {
+ if (!decoded) {
+ framing::StructHelper helper;
+ helper.decode(result, getResult());
+ decoded = true;
+ }
+ return result;
+ }
+};
+
+}}
+
+#endif
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp b/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
index dac2a4a6d9..872e1d59df 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
@@ -89,6 +89,7 @@ const std::string NODE("node");
const std::string LINK("link");
const std::string MODE("mode");
const std::string RELIABILITY("reliability");
+const std::string TIMEOUT("timeout");
const std::string NAME("name");
const std::string DURABLE("durable");
const std::string X_DECLARE("x-declare");
@@ -240,8 +241,8 @@ class Subscription : public Exchange, public MessageSource
void cancel(qpid::client::AsyncSession& session, const std::string& destination);
private:
const std::string queue;
- const bool reliable;
const bool durable;
+ const bool reliable;
const std::string actualType;
const bool exclusiveQueue;
const bool exclusiveSubscription;
@@ -516,13 +517,25 @@ std::string Subscription::getSubscriptionName(const std::string& base, const std
Subscription::Subscription(const Address& address, const std::string& type)
: Exchange(address),
queue(getSubscriptionName(name, (Opt(address)/LINK/NAME).str())),
- reliable(AddressResolution::is_reliable(address)),
durable(Opt(address)/LINK/DURABLE),
+ //if the link is durable, then assume it is also reliable unless explicitly stated otherwise
+ //if not assume it is unreliable unless explicitly stated otherwise
+ reliable(durable ? !AddressResolution::is_unreliable(address) : AddressResolution::is_reliable(address)),
actualType(type.empty() ? (specifiedType.empty() ? TOPIC_EXCHANGE : specifiedType) : type),
exclusiveQueue((Opt(address)/LINK/X_DECLARE/EXCLUSIVE).asBool(true)),
exclusiveSubscription((Opt(address)/LINK/X_SUBSCRIBE/EXCLUSIVE).asBool(exclusiveQueue)),
alternateExchange((Opt(address)/LINK/X_DECLARE/ALTERNATE_EXCHANGE).str())
{
+ const Variant* timeout = (Opt(address)/LINK/TIMEOUT).value;
+ if (timeout) {
+ if (timeout->asUint32()) queueOptions.setInt("qpid.auto_delete_timeout", timeout->asUint32());
+ } else if (durable && !(Opt(address)/LINK/RELIABILITY).value) {
+ //if durable but not explicitly reliable, then set a non-zero
+ //default for the autodelete timeout (previously this would
+ //have defaulted to autodelete immediately anyway, so the risk
+ //of the change causing problems is mitigated)
+ queueOptions.setInt("qpid.auto_delete_delay", 15*60);
+ }
(Opt(address)/LINK/X_DECLARE/ARGUMENTS).collect(queueOptions);
(Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(subscriptionOptions);
std::string selector = Opt(address)/LINK/SELECTOR;
@@ -584,7 +597,7 @@ void Subscription::subscribe(qpid::client::AsyncSession& session, const std::str
//create subscription queue:
session.queueDeclare(arg::queue=queue, arg::exclusive=exclusiveQueue,
- arg::autoDelete=!reliable, arg::durable=durable,
+ arg::autoDelete=!(durable || reliable), arg::durable=durable,
arg::alternateExchange=alternateExchange,
arg::arguments=queueOptions);
//'default' binding:
@@ -997,6 +1010,7 @@ Verifier::Verifier()
link[NAME] = true;
link[DURABLE] = true;
link[RELIABILITY] = true;
+ link[TIMEOUT] = true;
link[X_SUBSCRIBE] = true;
link[X_DECLARE] = true;
link[X_BINDINGS] = true;
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp b/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
index 668b500570..9406c992fe 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
@@ -43,6 +43,7 @@ using qpid::framing::Uuid;
namespace {
const std::string TCP("tcp");
+const std::string COLON(":");
double FOREVER(std::numeric_limits<double>::max());
// Time values in seconds can be specified as integer or floating point values.
@@ -86,9 +87,9 @@ bool expired(const sys::AbsTime& start, double timeout)
} // namespace
ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& options) :
- replaceUrls(false), reconnect(false), timeout(FOREVER), limit(-1),
+ replaceUrls(false), autoReconnect(false), timeout(FOREVER), limit(-1),
minReconnectInterval(0.001), maxReconnectInterval(2),
- retries(0), reconnectOnLimitExceeded(true)
+ retries(0), reconnectOnLimitExceeded(true), disableAutoDecode(false)
{
setOptions(options);
urls.insert(urls.begin(), url);
@@ -106,7 +107,7 @@ void ConnectionImpl::setOption(const std::string& name, const Variant& value)
{
sys::Mutex::ScopedLock l(lock);
if (name == "reconnect") {
- reconnect = value;
+ autoReconnect = value;
} else if (name == "reconnect-timeout" || name == "reconnect_timeout") {
timeout = timeValue(value);
} else if (name == "reconnect-limit" || name == "reconnect_limit") {
@@ -157,8 +158,10 @@ void ConnectionImpl::setOption(const std::string& name, const Variant& value)
settings.sslCertName = value.asString();
} else if (name == "x-reconnect-on-limit-exceeded" || name == "x_reconnect_on_limit_exceeded") {
reconnectOnLimitExceeded = value;
- } else if (name == "client-properties") {
+ } else if (name == "client-properties" || name == "client_properties") {
amqp_0_10::translate(value.asMap(), settings.clientProperties);
+ } else if (name == "disable-auto-decode" || name == "disable_auto_decode") {
+ disableAutoDecode = value;
} else {
throw qpid::messaging::MessagingException(QPID_MSG("Invalid option: " << name << " not recognised"));
}
@@ -254,7 +257,7 @@ void ConnectionImpl::open()
void ConnectionImpl::reopen()
{
- if (!reconnect) {
+ if (!autoReconnect) {
throw qpid::messaging::TransportFailure("Failed to connect (reconnect disabled)");
}
open();
@@ -265,7 +268,7 @@ void ConnectionImpl::connect(const qpid::sys::AbsTime& started)
{
QPID_LOG(debug, "Starting connection, urls=" << asString(urls));
for (double i = minReconnectInterval; !tryConnect(); i = std::min(i*2, maxReconnectInterval)) {
- if (!reconnect) {
+ if (!autoReconnect) {
throw qpid::messaging::TransportFailure("Failed to connect (reconnect disabled)");
}
if (limit >= 0 && retries++ >= limit) {
@@ -341,9 +344,52 @@ bool ConnectionImpl::backoff()
}
}
+void ConnectionImpl::reconnect(const std::string& u)
+{
+ sys::Mutex::ScopedLock l(lock);
+ try {
+ QPID_LOG(info, "Trying to connect to " << u << "...");
+ Url url(u, settings.protocol.size() ? settings.protocol : TCP);
+ if (url.getUser().size()) settings.username = url.getUser();
+ if (url.getPass().size()) settings.password = url.getPass();
+ connection.open(url, settings);
+ QPID_LOG(info, "Connected to " << u);
+ mergeUrls(connection.getInitialBrokers(), l);
+ if (!resetSessions(l)) throw qpid::messaging::TransportFailure("Could not re-establish sessions");
+ } catch (const qpid::TransportFailure& e) {
+ QPID_LOG(info, "Failed to connect to " << u << ": " << e.what());
+ throw qpid::messaging::TransportFailure(e.what());
+ } catch (const std::exception& e) {
+ QPID_LOG(info, "Error while connecting to " << u << ": " << e.what());
+ throw qpid::messaging::MessagingException(e.what());
+ }
+}
+
+void ConnectionImpl::reconnect()
+{
+ if (!tryConnect()) {
+ throw qpid::messaging::TransportFailure("Could not reconnect");
+ }
+}
+std::string ConnectionImpl::getUrl() const
+{
+ if (isOpen()) {
+ std::stringstream u;
+ u << connection.getNegotiatedSettings().protocol << COLON << connection.getNegotiatedSettings().host << COLON << connection.getNegotiatedSettings().port;
+ return u.str();
+ } else {
+ return std::string();
+ }
+}
+
std::string ConnectionImpl::getAuthenticatedUsername()
{
return connection.getNegotiatedSettings().username;
}
+bool ConnectionImpl::getAutoDecode() const
+{
+ return !disableAutoDecode;
+}
+
}}} // namespace qpid::client::amqp0_10
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h b/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
index d1ac4533d5..ae839dc690 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
+++ b/qpid/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
@@ -53,6 +53,10 @@ class ConnectionImpl : public qpid::messaging::ConnectionImpl
void setOption(const std::string& name, const qpid::types::Variant& value);
bool backoff();
std::string getAuthenticatedUsername();
+ void reconnect(const std::string& url);
+ void reconnect();
+ std::string getUrl() const;
+ bool getAutoDecode() const;
private:
typedef std::map<std::string, qpid::messaging::Session> Sessions;
@@ -63,13 +67,14 @@ class ConnectionImpl : public qpid::messaging::ConnectionImpl
bool replaceUrls; // Replace rather than merging with reconnect-urls
std::vector<std::string> urls;
qpid::client::ConnectionSettings settings;
- bool reconnect;
+ bool autoReconnect;
double timeout;
int32_t limit;
double minReconnectInterval;
double maxReconnectInterval;
int32_t retries;
bool reconnectOnLimitExceeded;
+ bool disableAutoDecode;
void setOptions(const qpid::types::Variant::Map& options);
void connect(const qpid::sys::AbsTime& started);
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp b/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
index db6e843cf6..27a2107702 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
@@ -399,7 +399,7 @@ void populate(qpid::messaging::Message& message, FrameSet& command)
//need to be able to link the message back to the transfer it was delivered by
//e.g. for rejecting.
MessageImplAccess::get(message).setInternalId(command.getId());
-
+
message.setContent(command.getContent());
populateHeaders(message, command.getHeaders());
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp b/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
index 348f9e160c..834ba1fe9f 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
@@ -21,6 +21,7 @@
#include "qpid/client/amqp0_10/OutgoingMessage.h"
#include "qpid/client/amqp0_10/AddressResolution.h"
#include "qpid/amqp_0_10/Codecs.h"
+#include "qpid/types/encodings.h"
#include "qpid/types/Variant.h"
#include "qpid/messaging/Address.h"
#include "qpid/messaging/Message.h"
@@ -45,13 +46,30 @@ const std::string SUBJECT("qpid.subject");
const std::string X_APP_ID("x-amqp-0-10.app-id");
const std::string X_ROUTING_KEY("x-amqp-0-10.routing-key");
const std::string X_CONTENT_ENCODING("x-amqp-0-10.content-encoding");
+const std::string TEXT_PLAIN("text/plain");
}
void OutgoingMessage::convert(const qpid::messaging::Message& from)
{
//TODO: need to avoid copying as much as possible
- message.setData(from.getContent());
- message.getMessageProperties().setContentType(from.getContentType());
+ if (from.getContentObject().getType() == qpid::types::VAR_MAP) {
+ std::string content;
+ qpid::amqp_0_10::MapCodec::encode(from.getContentObject().asMap(), content);
+ message.getMessageProperties().setContentType(qpid::amqp_0_10::MapCodec::contentType);
+ message.setData(content);
+ } else if (from.getContentObject().getType() == qpid::types::VAR_LIST) {
+ std::string content;
+ qpid::amqp_0_10::ListCodec::encode(from.getContentObject().asList(), content);
+ message.getMessageProperties().setContentType(qpid::amqp_0_10::ListCodec::contentType);
+ message.setData(content);
+ } else if (from.getContentObject().getType() == qpid::types::VAR_STRING &&
+ (from.getContentObject().getEncoding() == qpid::types::encodings::UTF8 || from.getContentObject().getEncoding() == qpid::types::encodings::ASCII)) {
+ message.getMessageProperties().setContentType(TEXT_PLAIN);
+ message.setData(from.getContent());
+ } else {
+ message.setData(from.getContent());
+ message.getMessageProperties().setContentType(from.getContentType());
+ }
if ( !from.getCorrelationId().empty() )
message.getMessageProperties().setCorrelationId(from.getCorrelationId());
message.getMessageProperties().setUserId(from.getUserId());
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp b/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp
index 7e8de21247..c356bc298b 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp
@@ -25,6 +25,8 @@
#include "qpid/messaging/exceptions.h"
#include "qpid/messaging/Receiver.h"
#include "qpid/messaging/Session.h"
+#include "qpid/amqp_0_10/Codecs.h"
+#include "qpid/types/encodings.h"
namespace qpid {
namespace client {
@@ -83,6 +85,7 @@ void ReceiverImpl::start()
if (state == STOPPED) {
state = STARTED;
startFlow(l);
+ session.sendCompletion();
}
}
@@ -148,18 +151,42 @@ qpid::messaging::Address ReceiverImpl::getAddress() const
}
ReceiverImpl::ReceiverImpl(SessionImpl& p, const std::string& name,
- const qpid::messaging::Address& a) :
+ const qpid::messaging::Address& a, bool autoDecode_) :
- parent(&p), destination(name), address(a), byteCredit(0xFFFFFFFF),
+ parent(&p), destination(name), address(a), byteCredit(0xFFFFFFFF), autoDecode(autoDecode_),
state(UNRESOLVED), capacity(0), window(0) {}
+namespace {
+const std::string TEXT_PLAIN("text/plain");
+}
+
bool ReceiverImpl::getImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout)
{
{
sys::Mutex::ScopedLock l(lock);
if (state == CANCELLED) return false;
}
- return parent->get(*this, message, timeout);
+ if (parent->get(*this, message, timeout)) {
+ if (autoDecode) {
+ if (message.getContentType() == qpid::amqp_0_10::MapCodec::contentType) {
+ message.getContentObject() = qpid::types::Variant::Map();
+ decode(message, message.getContentObject().asMap());
+ } else if (message.getContentType() == qpid::amqp_0_10::ListCodec::contentType) {
+ message.getContentObject() = qpid::types::Variant::List();
+ decode(message, message.getContentObject().asList());
+ } else if (!message.getContentBytes().empty()) {
+ message.getContentObject() = message.getContentBytes();
+ if (message.getContentType() == TEXT_PLAIN) {
+ message.getContentObject().setEncoding(qpid::types::encodings::UTF8);
+ } else {
+ message.getContentObject().setEncoding(qpid::types::encodings::BINARY);
+ }
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
}
bool ReceiverImpl::fetchImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout)
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h b/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h
index 4dba76c8d9..0d3366907b 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h
+++ b/qpid/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h
@@ -48,7 +48,7 @@ class ReceiverImpl : public qpid::messaging::ReceiverImpl
enum State {UNRESOLVED, STOPPED, STARTED, CANCELLED};
ReceiverImpl(SessionImpl& parent, const std::string& name,
- const qpid::messaging::Address& address);
+ const qpid::messaging::Address& address, bool autoDecode);
void init(qpid::client::AsyncSession session, AddressResolution& resolver);
bool get(qpid::messaging::Message& message, qpid::messaging::Duration timeout);
@@ -74,6 +74,7 @@ class ReceiverImpl : public qpid::messaging::ReceiverImpl
const std::string destination;
const qpid::messaging::Address address;
const uint32_t byteCredit;
+ const bool autoDecode;
State state;
std::auto_ptr<MessageSource> source;
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp b/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp
index e4c2c6afb8..982bfa3503 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp
@@ -207,7 +207,7 @@ Receiver SessionImpl::createReceiverImpl(const qpid::messaging::Address& address
ScopedLock l(lock);
std::string name = address.getName();
getFreeKey(name, receivers);
- Receiver receiver(new ReceiverImpl(*this, name, address));
+ Receiver receiver(new ReceiverImpl(*this, name, address, connection->getAutoDecode()));
getImplPtr<Receiver, ReceiverImpl>(receiver)->init(session, resolver);
receivers[name] = receiver;
return receiver;
diff --git a/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp b/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp
index 53d825771b..5ffd14596f 100644
--- a/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp
+++ b/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp
@@ -26,6 +26,7 @@
#include "qpid/sys/SecurityLayer.h"
#include "qpid/sys/SecuritySettings.h"
#include "qpid/log/Statement.h"
+#include "qpid/NullSaslServer.h"
#include "boost/tokenizer.hpp"
@@ -107,6 +108,12 @@ std::auto_ptr<Sasl> SaslFactory::create( const std::string & username, const std
return sasl;
}
+std::auto_ptr<SaslServer> SaslFactory::createServer( const std::string& realm, bool /*encryptionRequired*/, const qpid::sys::SecuritySettings& )
+{
+ std::auto_ptr<SaslServer> server(new NullSaslServer(realm));
+ return server;
+}
+
namespace {
const std::string ANONYMOUS = "ANONYMOUS";
const std::string PLAIN = "PLAIN";
diff --git a/qpid/cpp/src/qpid/console/Broker.cpp b/qpid/cpp/src/qpid/console/Broker.cpp
deleted file mode 100644
index 86a17d4a10..0000000000
--- a/qpid/cpp/src/qpid/console/Broker.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/console/Broker.h"
-#include "qpid/console/Object.h"
-#include "qpid/console/Value.h"
-#include "qpid/console/SessionManager.h"
-#include "qpid/console/ConsoleListener.h"
-#include "qpid/log/Statement.h"
-#include "qpid/sys/SystemInfo.h"
-
-using namespace qpid::client;
-using namespace qpid::console;
-using namespace qpid::framing;
-using namespace qpid::sys;
-using namespace std;
-
-Broker::Broker(SessionManager& sm, ConnectionSettings& settings) :
- sessionManager(sm), connected(false), connectionSettings(settings),
- reqsOutstanding(1), syncInFlight(false), topicBound(false), methodObject(0),
- connThreadBody(*this), connThread(connThreadBody)
-{
- string osName;
- string nodeName;
- string release;
- string version;
- string machine;
-
- sys::SystemInfo::getSystemId(osName, nodeName, release, version, machine);
- uint32_t pid = sys::SystemInfo::getParentProcessId();
-
- stringstream text;
-
- text << "qmfc-cpp-" << nodeName << "-" << pid;
- amqpSessionId = string(text.str());
-
- QPID_LOG(debug, "Broker::Broker: constructed, amqpSessionId=" << amqpSessionId);
-}
-
-Broker::~Broker()
-{
- connThreadBody.shutdown();
- connThread.join();
- resetAgents();
- // resetAgents() does not delete the broker agent...
- for (AgentMap::iterator iter = agents.begin(); iter != agents.end(); iter++) {
- delete iter->second;
- }
-}
-
-string Broker::getUrl() const
-{
- stringstream url;
- url << connectionSettings.host << ":" << connectionSettings.port;
- return url.str();
-}
-
-void Broker::encodeHeader(Buffer& buf, uint8_t opcode, uint32_t seq) const
-{
- buf.putOctet('A');
- buf.putOctet('M');
- buf.putOctet('2');
- buf.putOctet(opcode);
- buf.putLong (seq);
-}
-
-bool Broker::checkHeader(Buffer& buf, uint8_t *opcode, uint32_t *seq) const
-{
- if (buf.getSize() < 8)
- return false;
-
- uint8_t h1 = buf.getOctet();
- uint8_t h2 = buf.getOctet();
- uint8_t h3 = buf.getOctet();
-
- *opcode = buf.getOctet();
- *seq = buf.getLong();
-
- return h1 == 'A' && h2 == 'M' && h3 == '2';
-}
-
-void Broker::received(qpid::client::Message& msg)
-{
-#define QMF_HEADER_SIZE 8
- string data = msg.getData();
- Buffer inBuffer(const_cast<char*>(data.c_str()), data.size());
- uint8_t opcode;
- uint32_t sequence;
-
- while (inBuffer.available() >= QMF_HEADER_SIZE) {
- if (checkHeader(inBuffer, &opcode, &sequence)) {
- QPID_LOG(trace, "Broker::received: opcode=" << opcode << " seq=" << sequence);
-
- if (opcode == 'b') sessionManager.handleBrokerResp(this, inBuffer, sequence);
- else if (opcode == 'p') sessionManager.handlePackageInd(this, inBuffer, sequence);
- else if (opcode == 'z') sessionManager.handleCommandComplete(this, inBuffer, sequence);
- else if (opcode == 'q') sessionManager.handleClassInd(this, inBuffer, sequence);
- else if (opcode == 'm') sessionManager.handleMethodResp(this, inBuffer, sequence);
- else if (opcode == 'h') sessionManager.handleHeartbeatInd(this, inBuffer, sequence);
- else if (opcode == 'e') sessionManager.handleEventInd(this, inBuffer, sequence);
- else if (opcode == 's') sessionManager.handleSchemaResp(this, inBuffer, sequence);
- else if (opcode == 'c') sessionManager.handleContentInd(this, inBuffer, sequence, true, false);
- else if (opcode == 'i') sessionManager.handleContentInd(this, inBuffer, sequence, false, true);
- else if (opcode == 'g') sessionManager.handleContentInd(this, inBuffer, sequence, true, true);
- } else
- return;
- }
-}
-
-void Broker::resetAgents()
-{
- for (AgentMap::iterator iter = agents.begin(); iter != agents.end(); iter++) {
- if (sessionManager.listener != 0)
- sessionManager.listener->delAgent(*(iter->second));
- delete iter->second;
- }
-
- agents.clear();
- agents[0x0000000100000000LL] = new Agent(this, 0, "BrokerAgent");
-}
-
-void Broker::updateAgent(const Object& object)
-{
- uint32_t brokerBank = object.attrUint("brokerBank");
- uint32_t agentBank = object.attrUint("agentBank");
- uint64_t agentKey = ((uint64_t) brokerBank << 32) | (uint64_t) agentBank;
- AgentMap::iterator iter = agents.find(agentKey);
-
- if (object.isDeleted()) {
- if (iter != agents.end()) {
- if (sessionManager.listener != 0)
- sessionManager.listener->delAgent(*(iter->second));
- delete iter->second;
- agents.erase(iter);
- }
- } else {
- if (iter == agents.end()) {
- Agent* agent = new Agent(this, agentBank, object.attrString("label"));
- agents[agentKey] = agent;
- if (sessionManager.listener != 0)
- sessionManager.listener->newAgent(*agent);
- }
- }
-}
-
-void Broker::ConnectionThread::run()
-{
- static const int delayMin(1);
- static const int delayMax(128);
- static const int delayFactor(2);
- int delay(delayMin);
- string dest("qmfc");
-
- sessionId.generate();
- queueName << "qmfc-" << sessionId;
-
- while (true) {
- try {
- broker.topicBound = false;
- broker.reqsOutstanding = 1;
- connection.open(broker.connectionSettings);
- session = connection.newSession(queueName.str());
- subscriptions = new client::SubscriptionManager(session);
-
- session.queueDeclare(arg::queue=queueName.str(), arg::autoDelete=true,
- arg::exclusive=true);
- session.exchangeBind(arg::exchange="amq.direct", arg::queue=queueName.str(),
- arg::bindingKey=queueName.str());
-
- subscriptions->setAcceptMode(ACCEPT_MODE_NONE);
- subscriptions->setAcquireMode(ACQUIRE_MODE_PRE_ACQUIRED);
- subscriptions->subscribe(broker, queueName.str(), dest);
- subscriptions->setFlowControl(dest, FlowControl::unlimited());
- {
- Mutex::ScopedLock _lock(connLock);
- if (shuttingDown)
- return;
- operational = true;
- broker.resetAgents();
- broker.connected = true;
- broker.sessionManager.handleBrokerConnect(&broker);
- broker.sessionManager.startProtocol(&broker);
- try {
- Mutex::ScopedUnlock _unlock(connLock);
- subscriptions->run();
- } catch (std::exception) {}
-
- operational = false;
- broker.connected = false;
- broker.sessionManager.handleBrokerDisconnect(&broker);
- }
- delay = delayMin;
- connection.close();
- delete subscriptions;
- subscriptions = 0;
- } catch (std::exception &e) {
- QPID_LOG(debug, " outer exception: " << e.what());
- if (delay < delayMax)
- delay *= delayFactor;
- }
-
- {
- Mutex::ScopedLock _lock(connLock);
- if (shuttingDown)
- return;
- {
- Mutex::ScopedUnlock _unlock(connLock);
- ::sleep(delay);
- }
- if (shuttingDown)
- return;
- }
- }
-}
-
-Broker::ConnectionThread::~ConnectionThread()
-{
- if (subscriptions != 0) {
- delete subscriptions;
- }
-}
-
-void Broker::ConnectionThread::sendBuffer(Buffer& buf, uint32_t length,
- const string& exchange, const string& routingKey)
-{
- {
- Mutex::ScopedLock _lock(connLock);
- if (!operational)
- return;
- }
-
- client::Message msg;
- string data;
-
- buf.getRawData(data, length);
- msg.getDeliveryProperties().setRoutingKey(routingKey);
- msg.getMessageProperties().setReplyTo(ReplyTo("amq.direct", queueName.str()));
- msg.setData(data);
- try {
- session.messageTransfer(arg::content=msg, arg::destination=exchange);
- } catch(std::exception&) {}
-}
-
-void Broker::ConnectionThread::bindExchange(const std::string& exchange, const std::string& key)
-{
- {
- Mutex::ScopedLock _lock(connLock);
- if (!operational)
- return;
- }
-
- QPID_LOG(debug, "Broker::ConnectionThread::bindExchange: exchange=" << exchange << " key=" << key);
- session.exchangeBind(arg::exchange=exchange, arg::queue=queueName.str(),
- arg::bindingKey=key);
-}
-
-void Broker::ConnectionThread::shutdown()
-{
- {
- Mutex::ScopedLock _lock(connLock);
- shuttingDown = true;
- }
- if (subscriptions)
- subscriptions->stop();
-}
-
-void Broker::waitForStable()
-{
- Mutex::ScopedLock l(lock);
- if (reqsOutstanding == 0)
- return;
- syncInFlight = true;
- while (reqsOutstanding != 0) {
- bool result = cond.wait(lock, AbsTime(now(), TIME_SEC * sessionManager.settings.getTimeout));
- if (!result)
- throw(Exception("Timed out waiting for broker to synchronize"));
- }
-}
-
-void Broker::incOutstanding()
-{
- Mutex::ScopedLock l(lock);
- reqsOutstanding++;
-}
-
-void Broker::decOutstanding()
-{
- Mutex::ScopedLock l(lock);
- reqsOutstanding--;
- if (reqsOutstanding == 0) {
- if (!topicBound) {
- topicBound = true;
- for (vector<string>::const_iterator iter = sessionManager.bindingKeyList.begin();
- iter != sessionManager.bindingKeyList.end(); iter++)
- connThreadBody.bindExchange("qpid.management", *iter);
- }
- if (syncInFlight) {
- syncInFlight = false;
- cond.notify();
- }
- }
-}
-
-void Broker::appendAgents(Agent::Vector& agentlist) const
-{
- for (AgentMap::const_iterator iter = agents.begin(); iter != agents.end(); iter++) {
- agentlist.push_back(iter->second);
- }
-}
-
-ostream& qpid::console::operator<<(ostream& o, const Broker& k)
-{
- o << "Broker: " << k.connectionSettings.host << ":" << k.connectionSettings.port;
- return o;
-}
diff --git a/qpid/cpp/src/qpid/console/ClassKey.cpp b/qpid/cpp/src/qpid/console/ClassKey.cpp
deleted file mode 100644
index d4b59fc413..0000000000
--- a/qpid/cpp/src/qpid/console/ClassKey.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/console/ClassKey.h"
-#include <string.h>
-#include <iostream>
-#include <cstdio>
-
-using namespace std;
-using namespace qpid::console;
-
-ClassKey::ClassKey(const string& _package, const string& _name, const uint8_t* _hash) :
- package(_package), name(_name)
-{
- ::memcpy(hash, _hash, HASH_SIZE);
-}
-
-string ClassKey::getHashString() const
-{
- char cstr[36];
- ::sprintf(cstr, "%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x",
- hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7],
- hash[8], hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]);
- return string(cstr);
-}
-
-string ClassKey::str() const
-{
- string result(package + ":" + name + "(" + getHashString() + ")");
- return result;
-}
-
-bool ClassKey::operator==(const ClassKey& other) const
-{
- return ::memcmp(hash, other.hash, HASH_SIZE) == 0 &&
- name == other.name &&
- package == other.package;
-}
-
-bool ClassKey::operator!=(const ClassKey& other) const
-{
- return !(*this == other);
-}
-
-bool ClassKey::operator<(const ClassKey& other) const
-{
- int cmp = ::memcmp(hash, other.hash, HASH_SIZE);
- if (cmp != 0)
- return cmp < 0;
- cmp = name.compare(other.name);
- if (cmp != 0)
- return cmp < 0;
- return package < other.package;
-}
-
-bool ClassKey::operator>(const ClassKey& other) const
-{
- int cmp = ::memcmp(hash, other.hash, HASH_SIZE);
- if (cmp != 0)
- return cmp > 0;
- cmp = name.compare(other.name);
- if (cmp != 0)
- return cmp > 0;
- return package > other.package;
-}
-
-bool ClassKey::operator<=(const ClassKey& other) const
-{
- return !(*this > other);
-}
-
-bool ClassKey::operator>=(const ClassKey& other) const
-{
- return !(*this < other);
-}
-
-void ClassKey::encode(qpid::framing::Buffer& buffer) const
-{
- buffer.putShortString(package);
- buffer.putShortString(name);
- buffer.putBin128(const_cast<uint8_t*>(hash));
-}
-
-ostream& qpid::console::operator<<(ostream& o, const ClassKey& k)
-{
- o << k.str();
- return o;
-}
diff --git a/qpid/cpp/src/qpid/console/Event.cpp b/qpid/cpp/src/qpid/console/Event.cpp
deleted file mode 100644
index 3e14804b35..0000000000
--- a/qpid/cpp/src/qpid/console/Event.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/console/Broker.h"
-#include "qpid/console/ClassKey.h"
-#include "qpid/console/Schema.h"
-#include "qpid/console/Event.h"
-#include "qpid/console/Value.h"
-#include "qpid/sys/Time.h"
-#include "qpid/framing/Buffer.h"
-
-using namespace qpid::console;
-using namespace std;
-using qpid::framing::Uuid;
-using qpid::framing::FieldTable;
-
-Event::Event(Broker* _broker, SchemaClass* _schema, qpid::framing::Buffer& buffer) :
- broker(_broker), schema(_schema)
-{
- timestamp = buffer.getLongLong();
- severity = (Severity) buffer.getOctet();
- for (vector<SchemaArgument*>::const_iterator aIter = schema->arguments.begin();
- aIter != schema->arguments.end(); aIter++) {
- SchemaArgument* argument = *aIter;
- attributes[argument->name] = argument->decodeValue(buffer);
- }
-}
-
-const ClassKey& Event::getClassKey() const
-{
- return schema->getClassKey();
-}
-
-string Event::getSeverityString() const
-{
- switch (severity) {
- case SEV_EMERGENCY : return string("EMER");
- case SEV_ALERT : return string("ALERT");
- case SEV_CRITICAL : return string("CRIT");
- case SEV_ERROR : return string("ERROR");
- case SEV_WARNING : return string("WARN");
- case SEV_NOTICE : return string("NOTIC");
- case SEV_INFO : return string("INFO");
- case SEV_DEBUG : return string("DEBUG");
- }
- return string("<UNKNOWN>");
-}
-
-ObjectId Event::attrRef(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return ObjectId();
- Value::Ptr val = iter->second;
- if (!val->isObjectId())
- return ObjectId();
- return val->asObjectId();
-}
-
-uint32_t Event::attrUint(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0;
- Value::Ptr val = iter->second;
- if (!val->isUint())
- return 0;
- return val->asUint();
-}
-
-int32_t Event::attrInt(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0;
- Value::Ptr val = iter->second;
- if (!val->isInt())
- return 0;
- return val->asInt();
-}
-
-uint64_t Event::attrUint64(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0;
- Value::Ptr val = iter->second;
- if (!val->isUint64())
- return 0;
- return val->asUint64();
-}
-
-int64_t Event::attrInt64(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0;
- Value::Ptr val = iter->second;
- if (!val->isInt64())
- return 0;
- return val->asInt64();
-}
-
-string Event::attrString(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return string();
- Value::Ptr val = iter->second;
- if (!val->isString())
- return string();
- return val->asString();
-}
-
-bool Event::attrBool(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return false;
- Value::Ptr val = iter->second;
- if (!val->isBool())
- return false;
- return val->asBool();
-}
-
-float Event::attrFloat(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0.0;
- Value::Ptr val = iter->second;
- if (!val->isFloat())
- return 0.0;
- return val->asFloat();
-}
-
-double Event::attrDouble(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0.0;
- Value::Ptr val = iter->second;
- if (!val->isDouble())
- return 0.0;
- return val->asDouble();
-}
-
-Uuid Event::attrUuid(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return Uuid();
- Value::Ptr val = iter->second;
- if (!val->isUuid())
- return Uuid();
- return val->asUuid();
-}
-
-FieldTable Event::attrMap(const string& key) const
-{
- Object::AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return FieldTable();
- Value::Ptr val = iter->second;
- if (!val->isMap())
- return FieldTable();
- return val->asMap();
-}
-
-
-std::ostream& qpid::console::operator<<(std::ostream& o, const Event& event)
-{
- const ClassKey& key = event.getClassKey();
- sys::AbsTime aTime(sys::AbsTime(), sys::Duration(event.getTimestamp()));
- o << aTime << " " << event.getSeverityString() << " " <<
- key.getPackageName() << ":" << key.getClassName() <<
- " broker=" << event.getBroker()->getUrl();
-
- const Object::AttributeMap& attributes = event.getAttributes();
- for (Object::AttributeMap::const_iterator iter = attributes.begin();
- iter != attributes.end(); iter++) {
- o << " " << iter->first << "=" << iter->second->str();
- }
- return o;
-}
-
-
diff --git a/qpid/cpp/src/qpid/console/Object.cpp b/qpid/cpp/src/qpid/console/Object.cpp
deleted file mode 100644
index 6570e293ab..0000000000
--- a/qpid/cpp/src/qpid/console/Object.cpp
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/console/SessionManager.h"
-#include "qpid/console/Broker.h"
-#include "qpid/console/Object.h"
-#include "qpid/console/Schema.h"
-#include "qpid/console/ClassKey.h"
-#include "qpid/console/Value.h"
-#include "qpid/framing/Buffer.h"
-#include "qpid/sys/Mutex.h"
-
-using namespace qpid::console;
-using namespace qpid::sys;
-using namespace qpid;
-using namespace std;
-using qpid::framing::Uuid;
-using qpid::framing::FieldTable;
-
-void Object::AttributeMap::addRef(const string& key, const ObjectId& val)
-{
- (*this)[key] = Value::Ptr(new RefValue(val));
-}
-
-void Object::AttributeMap::addUint(const string& key, uint32_t val)
-{
- (*this)[key] = Value::Ptr(new UintValue(val));
-}
-
-void Object::AttributeMap::addInt(const string& key, int32_t val)
-{
- (*this)[key] = Value::Ptr(new IntValue(val));
-}
-
-void Object::AttributeMap::addUint64(const string& key, uint64_t val)
-{
- (*this)[key] = Value::Ptr(new Uint64Value(val));
-}
-
-void Object::AttributeMap::addInt64(const string& key, int64_t val)
-{
- (*this)[key] = Value::Ptr(new Int64Value(val));
-}
-
-void Object::AttributeMap::addString(const string& key, const string& val)
-{
- (*this)[key] = Value::Ptr(new StringValue(val));
-}
-
-void Object::AttributeMap::addBool(const string& key, bool val)
-{
- (*this)[key] = Value::Ptr(new BoolValue(val));
-}
-
-void Object::AttributeMap::addFloat(const string& key, float val)
-{
- (*this)[key] = Value::Ptr(new FloatValue(val));
-}
-
-void Object::AttributeMap::addDouble(const string& key, double val)
-{
- (*this)[key] = Value::Ptr(new DoubleValue(val));
-}
-
-void Object::AttributeMap::addUuid(const string& key, const Uuid& val)
-{
- (*this)[key] = Value::Ptr(new UuidValue(val));
-}
-
-void Object::AttributeMap::addMap(const string& key, const FieldTable& val)
-{
- (*this)[key] = Value::Ptr(new MapValue(val));
-}
-
-Object::Object(Broker* b, SchemaClass* s, framing::Buffer& buffer, bool prop, bool stat) :
- broker(b), schema(s), pendingMethod(0)
-{
- currentTime = buffer.getLongLong();
- createTime = buffer.getLongLong();
- deleteTime = buffer.getLongLong();
- objectId.decode(buffer);
-
- if (prop) {
- set<string> excludes;
- parsePresenceMasks(buffer, excludes);
- for (vector<SchemaProperty*>::const_iterator pIter = schema->properties.begin();
- pIter != schema->properties.end(); pIter++) {
- SchemaProperty* property = *pIter;
- if (excludes.count(property->name) != 0) {
- attributes[property->name] = Value::Ptr(new NullValue());
- } else {
- attributes[property->name] = property->decodeValue(buffer);
- }
- }
- }
-
- if (stat) {
- for (vector<SchemaStatistic*>::const_iterator sIter = schema->statistics.begin();
- sIter != schema->statistics.end(); sIter++) {
- SchemaStatistic* statistic = *sIter;
- attributes[statistic->name] = statistic->decodeValue(buffer);
- }
- }
-}
-
-Object::~Object() {}
-
-const ClassKey& Object::getClassKey() const
-{
- return schema->getClassKey();
-}
-
-string Object::getIndex() const
-{
- string result;
-
- for (vector<SchemaProperty*>::const_iterator pIter = schema->properties.begin();
- pIter != schema->properties.end(); pIter++) {
- SchemaProperty* property = *pIter;
- if (property->isIndex) {
- AttributeMap::const_iterator vIter = attributes.find(property->name);
- if (vIter != attributes.end()) {
- if (!result.empty())
- result += ":";
- result += vIter->second->str();
- }
- }
- }
- return result;
-}
-
-void Object::mergeUpdate(const Object& /*updated*/)
-{
- // TODO
-}
-
-void Object::invokeMethod(const string name, const AttributeMap& args, MethodResponse& result)
-{
- for (vector<SchemaMethod*>::const_iterator iter = schema->methods.begin();
- iter != schema->methods.end(); iter++) {
- if ((*iter)->name == name) {
- SchemaMethod* method = *iter;
- char rawbuffer[65536];
- framing::Buffer buffer(rawbuffer, 65536);
- uint32_t sequence = broker->sessionManager.sequenceManager.reserve("method");
- pendingMethod = method;
- broker->methodObject = this;
- broker->encodeHeader(buffer, 'M', sequence);
- objectId.encode(buffer);
- schema->key.encode(buffer);
- buffer.putShortString(name);
-
- for (vector<SchemaArgument*>::const_iterator aIter = method->arguments.begin();
- aIter != method->arguments.end(); aIter++) {
- SchemaArgument* arg = *aIter;
- if (arg->dirInput) {
- AttributeMap::const_iterator attr = args.find(arg->name);
- if (attr != args.end()) {
- ValueFactory::encodeValue(arg->typeCode, attr->second, buffer);
- } else {
- // TODO Use the default value instead of throwing
- throw Exception("Missing arguments in method call");
- }
- }
- }
-
- uint32_t length = buffer.getPosition();
- buffer.reset();
- stringstream routingKey;
- routingKey << "agent." << objectId.getBrokerBank() << "." << objectId.getAgentBank();
- broker->connThreadBody.sendBuffer(buffer, length, "qpid.management", routingKey.str());
-
- {
- Mutex::ScopedLock l(broker->lock);
- bool ok = true;
- while (pendingMethod != 0 && ok) {
- ok = broker->cond.wait(broker->lock, AbsTime(now(), broker->sessionManager.settings.methodTimeout * TIME_SEC));
- }
-
- if (!ok) {
- result.code = 0x1001;
- result.text.assign("Method call timed out");
- result.arguments.clear();
- } else {
- result = methodResponse;
- }
- }
- }
- }
-}
-
-void Object::handleMethodResp(framing::Buffer& buffer, uint32_t sequence)
-{
- broker->sessionManager.sequenceManager.release(sequence);
- methodResponse.code = buffer.getLong();
- buffer.getMediumString(methodResponse.text);
- methodResponse.arguments.clear();
-
- for (vector<SchemaArgument*>::const_iterator aIter = pendingMethod->arguments.begin();
- aIter != pendingMethod->arguments.end(); aIter++) {
- SchemaArgument* arg = *aIter;
- if (arg->dirOutput) {
- methodResponse.arguments[arg->name] = arg->decodeValue(buffer);
- }
- }
-
- {
- Mutex::ScopedLock l(broker->lock);
- pendingMethod = 0;
- broker->cond.notify();
- }
-}
-
-ObjectId Object::attrRef(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return ObjectId();
- Value::Ptr val = iter->second;
- if (!val->isObjectId())
- return ObjectId();
- return val->asObjectId();
-}
-
-uint32_t Object::attrUint(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0;
- Value::Ptr val = iter->second;
- if (!val->isUint())
- return 0;
- return val->asUint();
-}
-
-int32_t Object::attrInt(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0;
- Value::Ptr val = iter->second;
- if (!val->isInt())
- return 0;
- return val->asInt();
-}
-
-uint64_t Object::attrUint64(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0;
- Value::Ptr val = iter->second;
- if (!val->isUint64())
- return 0;
- return val->asUint64();
-}
-
-int64_t Object::attrInt64(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0;
- Value::Ptr val = iter->second;
- if (!val->isInt64())
- return 0;
- return val->asInt64();
-}
-
-string Object::attrString(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return string();
- Value::Ptr val = iter->second;
- if (!val->isString())
- return string();
- return val->asString();
-}
-
-bool Object::attrBool(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return false;
- Value::Ptr val = iter->second;
- if (!val->isBool())
- return false;
- return val->asBool();
-}
-
-float Object::attrFloat(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0.0;
- Value::Ptr val = iter->second;
- if (!val->isFloat())
- return 0.0;
- return val->asFloat();
-}
-
-double Object::attrDouble(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return 0.0;
- Value::Ptr val = iter->second;
- if (!val->isDouble())
- return 0.0;
- return val->asDouble();
-}
-
-Uuid Object::attrUuid(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return Uuid();
- Value::Ptr val = iter->second;
- if (!val->isUuid())
- return Uuid();
- return val->asUuid();
-}
-
-FieldTable Object::attrMap(const string& key) const
-{
- AttributeMap::const_iterator iter = attributes.find(key);
- if (iter == attributes.end())
- return FieldTable();
- Value::Ptr val = iter->second;
- if (!val->isMap())
- return FieldTable();
- return val->asMap();
-}
-
-void Object::parsePresenceMasks(framing::Buffer& buffer, set<string>& excludeList)
-{
- excludeList.clear();
- uint8_t bit = 0;
- uint8_t mask = 0;
-
- for (vector<SchemaProperty*>::const_iterator pIter = schema->properties.begin();
- pIter != schema->properties.end(); pIter++) {
- SchemaProperty* property = *pIter;
- if (property->isOptional) {
- if (bit == 0) {
- mask = buffer.getOctet();
- bit = 1;
- }
- if ((mask & bit) == 0)
- excludeList.insert(property->name);
- if (bit == 0x80)
- bit = 0;
- else
- bit = bit << 1;
- }
- }
-}
-
-ostream& qpid::console::operator<<(ostream& o, const Object& object)
-{
- const ClassKey& key = object.getClassKey();
- o << key.getPackageName() << ":" << key.getClassName() << "[" << object.getObjectId() << "] " <<
- object.getIndex();
- return o;
-}
-
diff --git a/qpid/cpp/src/qpid/console/ObjectId.cpp b/qpid/cpp/src/qpid/console/ObjectId.cpp
deleted file mode 100644
index fbaad20d57..0000000000
--- a/qpid/cpp/src/qpid/console/ObjectId.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/console/ObjectId.h"
-#include "qpid/framing/Buffer.h"
-
-using namespace qpid::console;
-using namespace qpid;
-using namespace std;
-
-ObjectId::ObjectId(framing::Buffer& buffer)
-{
- decode(buffer);
-}
-
-void ObjectId::decode(framing::Buffer& buffer)
-{
- first = buffer.getLongLong();
- second = buffer.getLongLong();
-}
-
-void ObjectId::encode(framing::Buffer& buffer)
-{
- buffer.putLongLong(first);
- buffer.putLongLong(second);
-}
-
-bool ObjectId::operator==(const ObjectId& other) const
-{
- return second == other.second && first == other.first;
-}
-
-bool ObjectId::operator!=(const ObjectId& other) const
-{
- return !(*this == other);
-}
-
-bool ObjectId::operator<(const ObjectId& other) const
-{
- if (first < other.first)
- return true;
- if (first > other.first)
- return false;
- return second < other.second;
-}
-
-bool ObjectId::operator>(const ObjectId& other) const
-{
- if (first > other.first)
- return true;
- if (first < other.first)
- return false;
- return second > other.second;
-}
-
-bool ObjectId::operator<=(const ObjectId& other) const
-{
- return !(*this > other);
-}
-
-bool ObjectId::operator>=(const ObjectId& other) const
-{
- return !(*this < other);
-}
-
-ostream& qpid::console::operator<<(ostream& o, const ObjectId& id)
-{
- o << (int) id.getFlags() << "-" << id.getSequence() << "-" << id.getBrokerBank() << "-" <<
- id.getAgentBank() << "-" << id.getObject();
- return o;
-}
-
-
diff --git a/qpid/cpp/src/qpid/console/Schema.cpp b/qpid/cpp/src/qpid/console/Schema.cpp
deleted file mode 100644
index a3dbd91201..0000000000
--- a/qpid/cpp/src/qpid/console/Schema.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/console/Schema.h"
-#include "qpid/console/Value.h"
-#include "qpid/framing/FieldTable.h"
-
-using namespace qpid::console;
-using namespace qpid;
-using std::string;
-using std::vector;
-
-SchemaArgument::SchemaArgument(framing::Buffer& buffer, bool forMethod)
-{
- framing::FieldTable map;
- map.decode(buffer);
-
- name = map.getAsString("name");
- typeCode = map.getAsInt("type");
- unit = map.getAsString("unit");
- min = map.getAsInt("min");
- max = map.getAsInt("max");
- maxLen = map.getAsInt("maxlen");
- desc = map.getAsString("desc");
-
- dirInput = false;
- dirOutput = false;
- if (forMethod) {
- string dir(map.getAsString("dir"));
- if (dir.find('I') != dir.npos || dir.find('i') != dir.npos)
- dirInput = true;
- if (dir.find('O') != dir.npos || dir.find('o') != dir.npos)
- dirOutput = true;
- }
-}
-
-Value::Ptr SchemaArgument::decodeValue(framing::Buffer& buffer)
-{
- return ValueFactory::newValue(typeCode, buffer);
-}
-
-SchemaProperty::SchemaProperty(framing::Buffer& buffer)
-{
- framing::FieldTable map;
- map.decode(buffer);
-
- name = map.getAsString("name");
- typeCode = map.getAsInt("type");
- accessCode = map.getAsInt("access");
- isIndex = map.getAsInt("index") != 0;
- isOptional = map.getAsInt("optional") != 0;
- unit = map.getAsString("unit");
- min = map.getAsInt("min");
- max = map.getAsInt("max");
- maxLen = map.getAsInt("maxlen");
- desc = map.getAsString("desc");
-}
-
-Value::Ptr SchemaProperty::decodeValue(framing::Buffer& buffer)
-{
- return ValueFactory::newValue(typeCode, buffer);
-}
-
-SchemaStatistic::SchemaStatistic(framing::Buffer& buffer)
-{
- framing::FieldTable map;
- map.decode(buffer);
-
- name = map.getAsString("name");
- typeCode = map.getAsInt("type");
- unit = map.getAsString("unit");
- desc = map.getAsString("desc");
-}
-
-Value::Ptr SchemaStatistic::decodeValue(framing::Buffer& buffer)
-{
- return ValueFactory::newValue(typeCode, buffer);
-}
-
-SchemaMethod::SchemaMethod(framing::Buffer& buffer)
-{
- framing::FieldTable map;
- map.decode(buffer);
-
- name = map.getAsString("name");
- desc = map.getAsString("desc");
- int argCount = map.getAsInt("argCount");
-
- for (int i = 0; i < argCount; i++)
- arguments.push_back(new SchemaArgument(buffer, true));
-}
-
-SchemaMethod::~SchemaMethod()
-{
- for (vector<SchemaArgument*>::iterator iter = arguments.begin();
- iter != arguments.end(); iter++)
- delete *iter;
-}
-
-SchemaClass::SchemaClass(const uint8_t _kind, const ClassKey& _key, framing::Buffer& buffer) :
- kind(_kind), key(_key)
-{
- if (kind == KIND_TABLE) {
- uint8_t hasSupertype = 0; //buffer.getOctet();
- uint16_t propCount = buffer.getShort();
- uint16_t statCount = buffer.getShort();
- uint16_t methodCount = buffer.getShort();
-
- if (hasSupertype) {
- string unused;
- buffer.getShortString(unused);
- buffer.getShortString(unused);
- buffer.getLongLong();
- buffer.getLongLong();
- }
-
- for (uint16_t idx = 0; idx < propCount; idx++)
- properties.push_back(new SchemaProperty(buffer));
- for (uint16_t idx = 0; idx < statCount; idx++)
- statistics.push_back(new SchemaStatistic(buffer));
- for (uint16_t idx = 0; idx < methodCount; idx++)
- methods.push_back(new SchemaMethod(buffer));
-
- } else if (kind == KIND_EVENT) {
- uint16_t argCount = buffer.getShort();
-
- for (uint16_t idx = 0; idx < argCount; idx++)
- arguments.push_back(new SchemaArgument(buffer));
- }
-}
-
-SchemaClass::~SchemaClass()
-{
- for (vector<SchemaProperty*>::iterator iter = properties.begin();
- iter != properties.end(); iter++)
- delete *iter;
- for (vector<SchemaStatistic*>::iterator iter = statistics.begin();
- iter != statistics.end(); iter++)
- delete *iter;
- for (vector<SchemaMethod*>::iterator iter = methods.begin();
- iter != methods.end(); iter++)
- delete *iter;
- for (vector<SchemaArgument*>::iterator iter = arguments.begin();
- iter != arguments.end(); iter++)
- delete *iter;
-}
-
diff --git a/qpid/cpp/src/qpid/console/SessionManager.cpp b/qpid/cpp/src/qpid/console/SessionManager.cpp
deleted file mode 100644
index 910ae22be8..0000000000
--- a/qpid/cpp/src/qpid/console/SessionManager.cpp
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-#include "qpid/console/SessionManager.h"
-#include "qpid/console/Schema.h"
-#include "qpid/console/Agent.h"
-#include "qpid/console/ConsoleListener.h"
-#include "qpid/log/Statement.h"
-#include "qpid/sys/Time.h"
-#include "qpid/framing/Buffer.h"
-#include "qpid/framing/Uuid.h"
-#include "qpid/framing/FieldTable.h"
-
-using namespace qpid::console;
-using namespace qpid::sys;
-using namespace qpid;
-using namespace std;
-using qpid::framing::Buffer;
-using qpid::framing::FieldTable;
-
-SessionManager::SessionManager(ConsoleListener* _listener, Settings _settings) :
- listener(_listener), settings(_settings)
-{
- bindingKeys();
-}
-
-SessionManager::~SessionManager()
-{
- for (vector<Broker*>::iterator iter = brokers.begin();
- iter != brokers.end(); iter++)
- delete *iter;
-
- for (map<string, Package*>::iterator iter = packages.begin();
- iter != packages.end(); iter++) {
- for (Package::ClassMap::iterator citer = iter->second->classes.begin();
- citer != iter->second->classes.end();
- citer++)
- delete citer->second;
- delete iter->second;
- }
-}
-
-Broker* SessionManager::addBroker(client::ConnectionSettings& settings)
-{
- Broker* broker(new Broker(*this, settings));
- {
- Mutex::ScopedLock l(brokerListLock);
- brokers.push_back(broker);
- }
- return broker;
-}
-
-void SessionManager::delBroker(Broker* broker)
-{
- Mutex::ScopedLock l(brokerListLock);
- for (vector<Broker*>::iterator iter = brokers.begin();
- iter != brokers.end(); iter++)
- if (*iter == broker) {
- brokers.erase(iter);
- delete broker;
- return;
- }
-}
-
-void SessionManager::getPackages(NameVector& packageNames)
-{
- allBrokersStable();
- packageNames.clear();
- {
- Mutex::ScopedLock l(lock);
- for (map<string, Package*>::iterator iter = packages.begin();
- iter != packages.end(); iter++)
- packageNames.push_back(iter->first);
- }
-}
-
-void SessionManager::getClasses(KeyVector& classKeys, const std::string& packageName)
-{
- allBrokersStable();
- classKeys.clear();
- map<string, Package*>::iterator iter = packages.find(packageName);
- if (iter == packages.end())
- return;
-
- Package& package = *(iter->second);
- for (Package::ClassMap::const_iterator piter = package.classes.begin();
- piter != package.classes.end(); piter++) {
- ClassKey key(piter->second->getClassKey());
- classKeys.push_back(key);
- }
-}
-
-SchemaClass& SessionManager::getSchema(const ClassKey& classKey)
-{
- allBrokersStable();
- map<string, Package*>::iterator iter = packages.find(classKey.getPackageName());
- if (iter == packages.end())
- throw Exception("Unknown package");
-
- Package& package = *(iter->second);
- Package::NameHash key(classKey.getClassName(), classKey.getHash());
- Package::ClassMap::iterator cIter = package.classes.find(key);
- if (cIter == package.classes.end())
- throw Exception("Unknown class");
-
- return *(cIter->second);
-}
-
-void SessionManager::bindPackage(const std::string& packageName)
-{
- stringstream key;
- key << "console.obj.*.*." << packageName << ".#";
- bindingKeyList.push_back(key.str());
- for (vector<Broker*>::iterator iter = brokers.begin(); iter != brokers.end(); iter++)
- (*iter)->addBinding(key.str());
-}
-
-void SessionManager::bindClass(const ClassKey& classKey)
-{
- bindClass(classKey.getPackageName(), classKey.getClassName());
-}
-
-void SessionManager::bindClass(const std::string& packageName, const std::string& className)
-{
- stringstream key;
- key << "console.obj.*.*." << packageName << "." << className << ".#";
- bindingKeyList.push_back(key.str());
- for (vector<Broker*>::iterator iter = brokers.begin();
- iter != brokers.end(); iter++)
- (*iter)->addBinding(key.str());
-}
-
-
-void SessionManager::bindEvent(const ClassKey& classKey)
-{
- bindEvent(classKey.getPackageName(), classKey.getClassName());
-}
-
-
-void SessionManager::bindEvent(const std::string& packageName, const std::string& eventName)
-{
- if (!settings.userBindings) throw Exception("Session not configured for userBindings.");
- if (settings.rcvEvents) throw Exception("Session already configured to receive all events.");
-
- stringstream key;
- key << "console.event.*.*." << packageName;
- if (eventName.length()) {
- key << "." << eventName << ".#";
- } else {
- key << ".#";
- }
-
- bindingKeyList.push_back(key.str());
- for (vector<Broker*>::iterator iter = brokers.begin();
- iter != brokers.end(); iter++)
- (*iter)->addBinding(key.str());
-}
-
-
-void SessionManager::getAgents(Agent::Vector& agents, Broker* broker)
-{
- agents.clear();
- if (broker != 0) {
- broker->appendAgents(agents);
- } else {
- for (vector<Broker*>::iterator iter = brokers.begin(); iter != brokers.end(); iter++) {
- (*iter)->appendAgents(agents);
- }
- }
-}
-
-void SessionManager::getObjects(Object::Vector& objects, const std::string& className,
- Broker* _broker, Agent* _agent)
-{
- Agent::Vector agentList;
-
- if (_agent != 0) {
- agentList.push_back(_agent);
- _agent->getBroker()->waitForStable();
- } else {
- if (_broker != 0) {
- _broker->appendAgents(agentList);
- _broker->waitForStable();
- } else {
- allBrokersStable();
- Mutex::ScopedLock _lock(brokerListLock);
- for (vector<Broker*>::iterator iter = brokers.begin(); iter != brokers.end(); iter++) {
- (*iter)->appendAgents(agentList);
- }
- }
- }
-
- FieldTable ft;
- uint32_t sequence;
- ft.setString("_class", className);
-
- getResult.clear();
- syncSequenceList.clear();
- error = string();
-
- if (agentList.empty()) {
- objects = getResult;
- return;
- }
-
- for (Agent::Vector::iterator iter = agentList.begin(); iter != agentList.end(); iter++) {
- Agent* agent = *iter;
- char rawbuffer[512];
- Buffer buffer(rawbuffer, 512);
- stringstream routingKey;
- routingKey << "agent." << agent->getBrokerBank() << "." << agent->getAgentBank();
- {
- Mutex::ScopedLock _lock(lock);
- sequence = sequenceManager.reserve("multiget");
- syncSequenceList.insert(sequence);
- }
- agent->getBroker()->encodeHeader(buffer, 'G', sequence);
- ft.encode(buffer);
- uint32_t length = buffer.getPosition();
- buffer.reset();
- agent->getBroker()->connThreadBody.sendBuffer(buffer, length, "qpid.management", routingKey.str());
- }
-
- {
- Mutex::ScopedLock _lock(lock);
- sys::AbsTime startTime = sys::now();
- while (!syncSequenceList.empty() && error.empty()) {
- cv.wait(lock, AbsTime(now(), settings.getTimeout * TIME_SEC));
- sys::AbsTime currTime = sys::now();
- if (sys::Duration(startTime, currTime) > settings.getTimeout * TIME_SEC)
- break;
- }
- }
-
- objects = getResult;
-}
-
-void SessionManager::bindingKeys()
-{
- bindingKeyList.push_back("schema.#");
- if (settings.rcvObjects && settings.rcvEvents && settings.rcvHeartbeats && !settings.userBindings) {
- bindingKeyList.push_back("console.#");
- } else {
- if (settings.rcvObjects && !settings.userBindings)
- bindingKeyList.push_back("console.obj.#");
- else
- bindingKeyList.push_back("console.obj.*.*.org.apache.qpid.broker.agent");
- if (settings.rcvEvents)
- bindingKeyList.push_back("console.event.#");
- if (settings.rcvHeartbeats)
- bindingKeyList.push_back("console.heartbeat");
- }
-}
-
-void SessionManager::allBrokersStable()
-{
- Mutex::ScopedLock l(brokerListLock);
- for (vector<Broker*>::iterator iter = brokers.begin();
- iter != brokers.end(); iter++)
- if ((*iter)->isConnected())
- (*iter)->waitForStable();
-}
-
-void SessionManager::startProtocol(Broker* broker)
-{
- char rawbuffer[512];
- Buffer buffer(rawbuffer, 512);
-
- broker->encodeHeader(buffer, 'B');
- uint32_t length = 512 - buffer.available();
- buffer.reset();
- broker->connThreadBody.sendBuffer(buffer, length);
-}
-
-
-void SessionManager::handleBrokerResp(Broker* broker, Buffer& inBuffer, uint32_t)
-{
- framing::Uuid brokerId;
-
- brokerId.decode(inBuffer);
- broker->setBrokerId(brokerId);
-
- char rawbuffer[512];
- Buffer buffer(rawbuffer, 512);
-
- uint32_t sequence = sequenceManager.reserve("startup");
- broker->encodeHeader(buffer, 'P', sequence);
- uint32_t length = 512 - buffer.available();
- buffer.reset();
- broker->connThreadBody.sendBuffer(buffer, length);
-
- if (listener != 0) {
- listener->brokerInfo(*broker);
- }
-}
-
-void SessionManager::handlePackageInd(Broker* broker, Buffer& inBuffer, uint32_t)
-{
- string packageName;
- inBuffer.getShortString(packageName);
-
- {
- Mutex::ScopedLock l(lock);
- map<string, Package*>::iterator iter = packages.find(packageName);
- if (iter == packages.end()) {
- packages[packageName] = new Package(packageName);
- if (listener != 0)
- listener->newPackage(packageName);
- }
- }
-
- broker->incOutstanding();
- char rawbuffer[512];
- Buffer buffer(rawbuffer, 512);
-
- uint32_t sequence = sequenceManager.reserve("startup");
- broker->encodeHeader(buffer, 'Q', sequence);
- buffer.putShortString(packageName);
- uint32_t length = 512 - buffer.available();
- buffer.reset();
- broker->connThreadBody.sendBuffer(buffer, length);
-}
-
-void SessionManager::handleCommandComplete(Broker* broker, Buffer& inBuffer, uint32_t sequence)
-{
- Mutex::ScopedLock l(lock);
- uint32_t resultCode = inBuffer.getLong();
- string resultText;
- inBuffer.getShortString(resultText);
- string context = sequenceManager.release(sequence);
- if (resultCode != 0)
- QPID_LOG(debug, "Received error in completion: " << resultCode << " " << resultText);
- if (context == "startup") {
- broker->decOutstanding();
- } else if (context == "multiget") {
- if (syncSequenceList.count(sequence) == 1) {
- syncSequenceList.erase(sequence);
- if (syncSequenceList.empty()) {
- cv.notify();
- }
- }
- }
- // TODO: Other context cases
-}
-
-void SessionManager::handleClassInd(Broker* broker, Buffer& inBuffer, uint32_t)
-{
- string packageName;
- string className;
- uint8_t hash[16];
-
- /*kind*/ (void) inBuffer.getOctet();
- inBuffer.getShortString(packageName);
- inBuffer.getShortString(className);
- inBuffer.getBin128(hash);
-
- {
- Mutex::ScopedLock l(lock);
- map<string, Package*>::iterator pIter = packages.find(packageName);
- if (pIter == packages.end() || pIter->second->getClass(className, hash))
- return;
- }
-
- broker->incOutstanding();
- char rawbuffer[512];
- Buffer buffer(rawbuffer, 512);
-
- uint32_t sequence = sequenceManager.reserve("startup");
- broker->encodeHeader(buffer, 'S', sequence);
- buffer.putShortString(packageName);
- buffer.putShortString(className);
- buffer.putBin128(hash);
- uint32_t length = 512 - buffer.available();
- buffer.reset();
- broker->connThreadBody.sendBuffer(buffer, length);
-}
-
-void SessionManager::handleMethodResp(Broker* broker, Buffer& buffer, uint32_t sequence)
-{
- if (broker->methodObject) {
- broker->methodObject->handleMethodResp(buffer, sequence);
- }
-}
-
-void SessionManager::handleHeartbeatInd(Broker* /*broker*/, Buffer& /*inBuffer*/, uint32_t /*sequence*/)
-{
-}
-
-void SessionManager::handleEventInd(Broker* broker, Buffer& buffer, uint32_t /*sequence*/)
-{
- string packageName;
- string className;
- uint8_t hash[16];
- SchemaClass* schemaClass;
-
- buffer.getShortString(packageName);
- buffer.getShortString(className);
- buffer.getBin128(hash);
-
- {
- Mutex::ScopedLock l(lock);
- map<string, Package*>::iterator pIter = packages.find(packageName);
- if (pIter == packages.end())
- return;
- schemaClass = pIter->second->getClass(className, hash);
- if (schemaClass == 0)
- return;
- }
-
- Event event(broker, schemaClass, buffer);
-
- if (listener)
- listener->event(event);
-}
-
-void SessionManager::handleSchemaResp(Broker* broker, Buffer& inBuffer, uint32_t sequence)
-{
- uint8_t kind;
- string packageName;
- string className;
- uint8_t hash[16];
-
- kind = inBuffer.getOctet();
- inBuffer.getShortString(packageName);
- inBuffer.getShortString(className);
- inBuffer.getBin128(hash);
-
- {
- Mutex::ScopedLock l(lock);
- map<string, Package*>::iterator pIter = packages.find(packageName);
- if (pIter != packages.end() && !pIter->second->getClass(className, hash)) {
- ClassKey key(packageName, className, hash);
- SchemaClass* schemaClass(new SchemaClass(kind, key, inBuffer));
- pIter->second->addClass(className, hash, schemaClass);
- if (listener != 0) {
- listener->newClass(schemaClass->getClassKey());
- }
- }
- }
-
- sequenceManager.release(sequence);
- broker->decOutstanding();
-}
-
-void SessionManager::handleContentInd(Broker* broker, Buffer& buffer, uint32_t sequence, bool prop, bool stat)
-{
- string packageName;
- string className;
- uint8_t hash[16];
- SchemaClass* schemaClass;
-
- buffer.getShortString(packageName);
- buffer.getShortString(className);
- buffer.getBin128(hash);
-
- {
- Mutex::ScopedLock l(lock);
- map<string, Package*>::iterator pIter = packages.find(packageName);
- if (pIter == packages.end())
- return;
- schemaClass = pIter->second->getClass(className, hash);
- if (schemaClass == 0)
- return;
- }
-
- Object object(broker, schemaClass, buffer, prop, stat);
-
- if (prop && className == "agent" && packageName == "org.apache.qpid.broker")
- broker->updateAgent(object);
-
- {
- Mutex::ScopedLock l(lock);
- if (syncSequenceList.count(sequence) == 1) {
- if (!object.isDeleted())
- getResult.push_back(object);
- return;
- }
- }
-
- if (listener) {
- if (prop)
- listener->objectProps(*broker, object);
- if (stat)
- listener->objectStats(*broker, object);
- }
-}
-
-void SessionManager::handleBrokerConnect(Broker* broker)
-{
- if (listener != 0)
- listener->brokerConnected(*broker);
-}
-
-void SessionManager::handleBrokerDisconnect(Broker* broker)
-{
- if (listener != 0)
- listener->brokerDisconnected(*broker);
-}
-
diff --git a/qpid/cpp/src/qpid/console/Value.cpp b/qpid/cpp/src/qpid/console/Value.cpp
deleted file mode 100644
index 47c6a4ce57..0000000000
--- a/qpid/cpp/src/qpid/console/Value.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/console/Value.h"
-#include "qpid/framing/Buffer.h"
-
-#include <sstream>
-
-using namespace qpid;
-using namespace qpid::console;
-using namespace std;
-
-string NullValue::str() const
-{
- return "<Null>";
-}
-
-RefValue::RefValue(framing::Buffer& buffer)
-{
- uint64_t first = buffer.getLongLong();
- uint64_t second = buffer.getLongLong();
- value.setValue(first, second);
-}
-
-string RefValue::str() const
-{
- stringstream s;
- s << value;
- return s.str();
-}
-
-string UintValue::str() const
-{
- stringstream s;
- s << value;
- return s.str();
-}
-
-string IntValue::str() const
-{
- stringstream s;
- s << value;
- return s.str();
-}
-
-string Uint64Value::str() const
-{
- stringstream s;
- s << value;
- return s.str();
-}
-
-string Int64Value::str() const
-{
- stringstream s;
- s << value;
- return s.str();
-}
-
-StringValue::StringValue(framing::Buffer& buffer, int tc)
-{
- if (tc == 6)
- buffer.getShortString(value);
- else
- buffer.getMediumString(value);
-}
-
-string BoolValue::str() const
-{
- return value ? "T" : "F";
-}
-
-string FloatValue::str() const
-{
- stringstream s;
- s << value;
- return s.str();
-}
-
-string DoubleValue::str() const
-{
- stringstream s;
- s << value;
- return s.str();
-}
-
-UuidValue::UuidValue(framing::Buffer& buffer)
-{
- value.decode(buffer);
-}
-
-string MapValue::str() const
-{
- stringstream s;
- s << value;
- return s.str();
-}
-
-MapValue::MapValue(framing::Buffer& buffer)
-{
- value.decode(buffer);
-}
-
-
-Value::Ptr ValueFactory::newValue(int typeCode, framing::Buffer& buffer)
-{
- switch (typeCode) {
- case 1: return Value::Ptr(new UintValue(buffer.getOctet())); // U8
- case 2: return Value::Ptr(new UintValue(buffer.getShort())); // U16
- case 3: return Value::Ptr(new UintValue(buffer.getLong())); // U32
- case 4: return Value::Ptr(new Uint64Value(buffer.getLongLong())); // U64
- case 6: return Value::Ptr(new StringValue(buffer, 6)); // SSTR
- case 7: return Value::Ptr(new StringValue(buffer, 7)); // LSTR
- case 8: return Value::Ptr(new Int64Value(buffer.getLongLong())); // ABSTIME
- case 9: return Value::Ptr(new Uint64Value(buffer.getLongLong())); // DELTATIME
- case 10: return Value::Ptr(new RefValue(buffer)); // REF
- case 11: return Value::Ptr(new BoolValue(buffer.getOctet())); // BOOL
- case 12: return Value::Ptr(new FloatValue(buffer.getFloat())); // FLOAT
- case 13: return Value::Ptr(new DoubleValue(buffer.getDouble())); // DOUBLE
- case 14: return Value::Ptr(new UuidValue(buffer)); // UUID
- case 15: return Value::Ptr(new MapValue(buffer)); // MAP
- case 16: return Value::Ptr(new IntValue(buffer.getOctet())); // S8
- case 17: return Value::Ptr(new IntValue(buffer.getShort())); // S16
- case 18: return Value::Ptr(new IntValue(buffer.getLong())); // S32
- case 19: return Value::Ptr(new Int64Value(buffer.getLongLong())); // S64
- }
-
- return Value::Ptr();
-}
-
-void ValueFactory::encodeValue(int typeCode, Value::Ptr value, framing::Buffer& buffer)
-{
- switch (typeCode) {
- case 1: buffer.putOctet(value->asUint()); return; // U8
- case 2: buffer.putShort(value->asUint()); return; // U16
- case 3: buffer.putLong(value->asUint()); return; // U32
- case 4: buffer.putLongLong(value->asUint64()); return; // U64
- case 6: buffer.putShortString(value->asString()); return; // SSTR
- case 7: buffer.putMediumString(value->asString()); return; // LSTR
- case 8: buffer.putLongLong(value->asInt64()); return; // ABSTIME
- case 9: buffer.putLongLong(value->asUint64()); return; // DELTATIME
- case 10: value->asObjectId().encode(buffer); return; // REF
- case 11: buffer.putOctet(value->asBool() ? 1 : 0); return; // BOOL
- case 12: buffer.putFloat(value->asFloat()); return; // FLOAT
- case 13: buffer.putDouble(value->asDouble()); return; // DOUBLE
- case 14: value->asUuid().encode(buffer); return; // UUID
- case 15: value->asMap().encode(buffer); return; // MAP
- case 16: buffer.putOctet(value->asInt()); return; // S8
- case 17: buffer.putShort(value->asInt()); return; // S16
- case 18: buffer.putLong(value->asInt()); return; // S32
- case 19: buffer.putLongLong(value->asInt64()); return; // S64
- }
-}
diff --git a/qpid/cpp/src/qpid/framing/Array.h b/qpid/cpp/src/qpid/framing/Array.h
new file mode 100644
index 0000000000..6254f6271a
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/Array.h
@@ -0,0 +1,99 @@
+#ifndef QPID_FRAMING_ARRAY_H
+#define QPID_FRAMING_ARRAY_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/framing/amqp_types.h"
+#include "qpid/framing/TypeCode.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <iostream>
+#include <vector>
+
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+namespace framing {
+
+class Buffer;
+class FieldValue;
+
+class QPID_COMMON_CLASS_EXTERN Array
+{
+ public:
+ typedef boost::shared_ptr<FieldValue> ValuePtr;
+ typedef std::vector<ValuePtr> ValueVector;
+ typedef ValueVector::const_iterator const_iterator;
+ typedef ValueVector::iterator iterator;
+
+ QPID_COMMON_EXTERN uint32_t encodedSize() const;
+ QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
+ QPID_COMMON_EXTERN void decode(Buffer& buffer);
+
+ QPID_COMMON_EXTERN int count() const;
+ QPID_COMMON_EXTERN bool operator==(const Array& other) const;
+
+ QPID_COMMON_EXTERN Array();
+ QPID_COMMON_EXTERN Array(TypeCode type);
+ QPID_COMMON_EXTERN Array(uint8_t type);
+ //creates a longstr array
+ QPID_COMMON_EXTERN Array(const std::vector<std::string>& in);
+
+ QPID_COMMON_INLINE_EXTERN TypeCode getType() const { return type; }
+
+ // std collection interface.
+ QPID_COMMON_INLINE_EXTERN const_iterator begin() const { return values.begin(); }
+ QPID_COMMON_INLINE_EXTERN const_iterator end() const { return values.end(); }
+ QPID_COMMON_INLINE_EXTERN iterator begin() { return values.begin(); }
+ QPID_COMMON_INLINE_EXTERN iterator end(){ return values.end(); }
+
+ QPID_COMMON_INLINE_EXTERN ValuePtr front() const { return values.front(); }
+ QPID_COMMON_INLINE_EXTERN ValuePtr back() const { return values.back(); }
+ QPID_COMMON_INLINE_EXTERN size_t size() const { return values.size(); }
+
+ QPID_COMMON_EXTERN void insert(iterator i, ValuePtr value);
+ QPID_COMMON_INLINE_EXTERN void erase(iterator i) { values.erase(i); }
+ QPID_COMMON_INLINE_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
+ QPID_COMMON_INLINE_EXTERN void pop_back() { values.pop_back(); }
+
+ // Non-std interface
+ QPID_COMMON_INLINE_EXTERN void add(ValuePtr value) { push_back(value); }
+
+ // For use in standard algorithms
+ template <typename R, typename V>
+ static R get(const V& v) {
+ return v->template get<R>();
+ }
+
+ private:
+ TypeCode type;
+ ValueVector values;
+
+ friend QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& out, const Array& body);
+};
+
+}
+}
+
+
+#endif
diff --git a/qpid/cpp/src/qpid/framing/Buffer.cpp b/qpid/cpp/src/qpid/framing/Buffer.cpp
index ef977cc8a3..1c4caef046 100644
--- a/qpid/cpp/src/qpid/framing/Buffer.cpp
+++ b/qpid/cpp/src/qpid/framing/Buffer.cpp
@@ -182,27 +182,27 @@ double Buffer::getDouble(){
}
template <>
-uint64_t Buffer::getUInt<1>() {
+QPID_COMMON_EXTERN uint64_t Buffer::getUInt<1>() {
return getOctet();
}
template <>
-uint64_t Buffer::getUInt<2>() {
+QPID_COMMON_EXTERN uint64_t Buffer::getUInt<2>() {
return getShort();
}
template <>
-uint64_t Buffer::getUInt<4>() {
+QPID_COMMON_EXTERN uint64_t Buffer::getUInt<4>() {
return getLong();
}
template <>
-uint64_t Buffer::getUInt<8>() {
+QPID_COMMON_EXTERN uint64_t Buffer::getUInt<8>() {
return getLongLong();
}
template <>
-void Buffer::putUInt<1>(uint64_t i) {
+QPID_COMMON_EXTERN void Buffer::putUInt<1>(uint64_t i) {
if (std::numeric_limits<uint8_t>::min() <= i && i <= std::numeric_limits<uint8_t>::max()) {
putOctet(i);
return;
@@ -211,7 +211,7 @@ void Buffer::putUInt<1>(uint64_t i) {
}
template <>
-void Buffer::putUInt<2>(uint64_t i) {
+QPID_COMMON_EXTERN void Buffer::putUInt<2>(uint64_t i) {
if (std::numeric_limits<uint16_t>::min() <= i && i <= std::numeric_limits<uint16_t>::max()) {
putShort(i);
return;
@@ -220,7 +220,7 @@ void Buffer::putUInt<2>(uint64_t i) {
}
template <>
-void Buffer::putUInt<4>(uint64_t i) {
+QPID_COMMON_EXTERN void Buffer::putUInt<4>(uint64_t i) {
if (std::numeric_limits<uint32_t>::min() <= i && i <= std::numeric_limits<uint32_t>::max()) {
putLong(i);
return;
@@ -229,7 +229,7 @@ void Buffer::putUInt<4>(uint64_t i) {
}
template <>
-void Buffer::putUInt<8>(uint64_t i) {
+QPID_COMMON_EXTERN void Buffer::putUInt<8>(uint64_t i) {
putLongLong(i);
}
diff --git a/qpid/cpp/src/qpid/framing/Buffer.h b/qpid/cpp/src/qpid/framing/Buffer.h
new file mode 100644
index 0000000000..166b524e3c
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/Buffer.h
@@ -0,0 +1,115 @@
+#ifndef QPID_FRAMING_BUFFER_H
+#define QPID_FRAMING_BUFFER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/Exception.h"
+#include "qpid/CommonImportExport.h"
+#include "qpid/sys/IntegerTypes.h"
+
+#include <string>
+
+namespace qpid {
+namespace framing {
+
+struct QPID_COMMON_CLASS_EXTERN OutOfBounds : qpid::Exception {
+ OutOfBounds() : qpid::Exception(std::string("Out of Bounds")) {}
+};
+
+class Content;
+class FieldTable;
+
+class QPID_COMMON_CLASS_EXTERN Buffer
+{
+ uint32_t size;
+ char* data;
+ uint32_t position;
+
+ public:
+ void checkAvailable(size_t count) { if (count > size - position) throw OutOfBounds(); }
+
+ QPID_COMMON_EXTERN Buffer(char* data=0, uint32_t size=0);
+
+ QPID_COMMON_EXTERN void reset();
+
+ QPID_COMMON_INLINE_EXTERN uint32_t available() const{ return size - position; }
+ QPID_COMMON_INLINE_EXTERN uint32_t getSize() const { return size; }
+ QPID_COMMON_INLINE_EXTERN uint32_t getPosition() const { return position; }
+ QPID_COMMON_INLINE_EXTERN void setPosition(uint32_t p) { position = p; }
+ QPID_COMMON_INLINE_EXTERN const char * getPointer() const { return data; }
+ QPID_COMMON_INLINE_EXTERN char* getPointer() { return data; }
+
+ QPID_COMMON_EXTERN void putOctet(uint8_t i);
+ QPID_COMMON_EXTERN void putShort(uint16_t i);
+ QPID_COMMON_EXTERN void putLong(uint32_t i);
+ QPID_COMMON_EXTERN void putLongLong(uint64_t i);
+ QPID_COMMON_EXTERN void putInt8(int8_t i);
+ QPID_COMMON_EXTERN void putInt16(int16_t i);
+ QPID_COMMON_EXTERN void putInt32(int32_t i);
+ QPID_COMMON_EXTERN void putInt64(int64_t i);
+ QPID_COMMON_EXTERN void putFloat(float f);
+ QPID_COMMON_EXTERN void putDouble(double f);
+ QPID_COMMON_EXTERN void putBin128(const uint8_t* b);
+
+ QPID_COMMON_EXTERN uint8_t getOctet();
+ QPID_COMMON_EXTERN uint16_t getShort();
+ QPID_COMMON_EXTERN uint32_t getLong();
+ QPID_COMMON_EXTERN uint64_t getLongLong();
+ QPID_COMMON_EXTERN int8_t getInt8();
+ QPID_COMMON_EXTERN int16_t getInt16();
+ QPID_COMMON_EXTERN int32_t getInt32();
+ QPID_COMMON_EXTERN int64_t getInt64();
+ QPID_COMMON_EXTERN float getFloat();
+ QPID_COMMON_EXTERN double getDouble();
+
+ template <int n>
+ QPID_COMMON_EXTERN uint64_t getUInt();
+
+ template <int n>
+ QPID_COMMON_EXTERN void putUInt(uint64_t);
+
+ QPID_COMMON_EXTERN void putShortString(const std::string& s);
+ QPID_COMMON_EXTERN void putMediumString(const std::string& s);
+ QPID_COMMON_EXTERN void putLongString(const std::string& s);
+ QPID_COMMON_EXTERN void getShortString(std::string& s);
+ QPID_COMMON_EXTERN void getMediumString(std::string& s);
+ QPID_COMMON_EXTERN void getLongString(std::string& s);
+ QPID_COMMON_EXTERN void getBin128(uint8_t* b);
+
+ QPID_COMMON_EXTERN void putRawData(const std::string& s);
+ QPID_COMMON_EXTERN void getRawData(std::string& s, uint32_t size);
+
+ QPID_COMMON_EXTERN void putRawData(const uint8_t* data, size_t size);
+ QPID_COMMON_EXTERN void getRawData(uint8_t* data, size_t size);
+
+ template <class T> void put(const T& data) { data.encode(*this); }
+ template <class T> void get(T& data) { data.decode(*this); }
+
+ QPID_COMMON_EXTERN void dump(std::ostream&) const;
+};
+
+std::ostream& operator<<(std::ostream&, const Buffer&);
+
+}} // namespace qpid::framing
+
+
+#endif
diff --git a/qpid/cpp/src/qpid/framing/FieldTable.h b/qpid/cpp/src/qpid/framing/FieldTable.h
new file mode 100644
index 0000000000..1986a72d10
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/FieldTable.h
@@ -0,0 +1,139 @@
+#ifndef _FieldTable_
+#define _FieldTable_
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/framing/amqp_types.h"
+#include "qpid/sys/Mutex.h"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+
+#include <iosfwd>
+#include <map>
+
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+ /**
+ * The framing namespace contains classes that are used to create,
+ * send and receive the basic packets from which AMQP is built.
+ */
+namespace framing {
+
+class Array;
+class FieldValue;
+class Buffer;
+
+/**
+ * A set of name-value pairs. (See the AMQP spec for more details on
+ * AMQP field tables).
+ *
+ * \ingroup clientapi
+ */
+class FieldTable
+{
+ public:
+ typedef boost::shared_ptr<FieldValue> ValuePtr;
+ typedef std::map<std::string, ValuePtr> ValueMap;
+ typedef ValueMap::iterator iterator;
+ typedef ValueMap::const_iterator const_iterator;
+ typedef ValueMap::const_reference const_reference;
+ typedef ValueMap::reference reference;
+ typedef ValueMap::value_type value_type;
+
+ QPID_COMMON_EXTERN FieldTable();
+ QPID_COMMON_EXTERN FieldTable(const FieldTable&);
+ QPID_COMMON_EXTERN FieldTable& operator=(const FieldTable&);
+ // Compiler default destructor fine
+ QPID_COMMON_EXTERN uint32_t encodedSize() const;
+ QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
+ QPID_COMMON_EXTERN void decode(Buffer& buffer);
+
+ QPID_COMMON_EXTERN int count() const;
+ QPID_COMMON_INLINE_EXTERN size_t size() const { return values.size(); }
+ QPID_COMMON_INLINE_EXTERN bool empty() { return size() == 0; }
+ QPID_COMMON_EXTERN void set(const std::string& name, const ValuePtr& value);
+ QPID_COMMON_EXTERN ValuePtr get(const std::string& name) const;
+ QPID_COMMON_INLINE_EXTERN bool isSet(const std::string& name) const { return get(name).get() != 0; }
+
+ QPID_COMMON_EXTERN void setString(const std::string& name, const std::string& value);
+ QPID_COMMON_EXTERN void setInt(const std::string& name, const int value);
+ QPID_COMMON_EXTERN void setInt64(const std::string& name, const int64_t value);
+ QPID_COMMON_EXTERN void setTimestamp(const std::string& name, const uint64_t value);
+ QPID_COMMON_EXTERN void setUInt64(const std::string& name, const uint64_t value);
+ QPID_COMMON_EXTERN void setTable(const std::string& name, const FieldTable& value);
+ QPID_COMMON_EXTERN void setArray(const std::string& name, const Array& value);
+ QPID_COMMON_EXTERN void setFloat(const std::string& name, const float value);
+ QPID_COMMON_EXTERN void setDouble(const std::string& name, const double value);
+ //void setDecimal(string& name, xxx& value);
+
+ QPID_COMMON_EXTERN int getAsInt(const std::string& name) const;
+ QPID_COMMON_EXTERN uint64_t getAsUInt64(const std::string& name) const;
+ QPID_COMMON_EXTERN int64_t getAsInt64(const std::string& name) const;
+ QPID_COMMON_EXTERN std::string getAsString(const std::string& name) const;
+
+ QPID_COMMON_EXTERN bool getTable(const std::string& name, FieldTable& value) const;
+ QPID_COMMON_EXTERN bool getArray(const std::string& name, Array& value) const;
+ QPID_COMMON_EXTERN bool getFloat(const std::string& name, float& value) const;
+ QPID_COMMON_EXTERN bool getDouble(const std::string& name, double& value) const;
+ //QPID_COMMON_EXTERN bool getTimestamp(const std::string& name, uint64_t& value) const;
+ //QPID_COMMON_EXTERN bool getDecimal(string& name, xxx& value);
+ QPID_COMMON_EXTERN void erase(const std::string& name);
+
+
+ QPID_COMMON_EXTERN bool operator==(const FieldTable& other) const;
+
+ // Map-like interface.
+ QPID_COMMON_EXTERN ValueMap::const_iterator begin() const;
+ QPID_COMMON_EXTERN ValueMap::const_iterator end() const;
+ QPID_COMMON_EXTERN ValueMap::const_iterator find(const std::string& s) const;
+
+ QPID_COMMON_EXTERN ValueMap::iterator begin();
+ QPID_COMMON_EXTERN ValueMap::iterator end();
+ QPID_COMMON_EXTERN ValueMap::iterator find(const std::string& s);
+
+ QPID_COMMON_EXTERN std::pair <ValueMap::iterator, bool> insert(const ValueMap::value_type&);
+ QPID_COMMON_EXTERN ValueMap::iterator insert(ValueMap::iterator, const ValueMap::value_type&);
+ QPID_COMMON_EXTERN void clear();
+
+ private:
+ void realDecode() const;
+ void flushRawCache();
+
+ mutable qpid::sys::Mutex lock;
+ mutable ValueMap values;
+ mutable boost::shared_array<uint8_t> cachedBytes;
+ mutable uint32_t cachedSize; // if = 0 then non cached size as 0 is not a legal size
+ mutable bool newBytes;
+
+ QPID_COMMON_EXTERN friend std::ostream& operator<<(std::ostream& out, const FieldTable& body);
+};
+
+//class FieldNotFoundException{};
+//class UnknownFieldName : public FieldNotFoundException{};
+//class IncorrectFieldType : public FieldNotFoundException{};
+}
+}
+
+
+#endif
diff --git a/qpid/cpp/src/qpid/framing/FieldValue.h b/qpid/cpp/src/qpid/framing/FieldValue.h
new file mode 100644
index 0000000000..1adcb2fa07
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/FieldValue.h
@@ -0,0 +1,484 @@
+#ifndef _framing_FieldValue_h
+#define _framing_FieldValue_h
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/Exception.h"
+#include "qpid/framing/amqp_types.h"
+#include "qpid/framing/Buffer.h"
+#include "qpid/framing/FieldTable.h"
+#include "qpid/CommonImportExport.h"
+
+#include <iostream>
+#include <memory>
+#include <vector>
+
+#include <assert.h>
+
+namespace qpid {
+namespace framing {
+
+/**
+ * Exception that is the base exception for all field table errors.
+ *
+ * \ingroup clientapi
+ */
+class QPID_COMMON_CLASS_EXTERN FieldValueException : public qpid::Exception {};
+
+/**
+ * Exception thrown when we can't perform requested conversion
+ *
+ * \ingroup clientapi
+ */
+struct QPID_COMMON_CLASS_EXTERN InvalidConversionException : public FieldValueException {
+ InvalidConversionException() {}
+};
+
+class List;
+
+/**
+ * Value that can appear in an AMQP field table
+ *
+ * \ingroup clientapi
+ */
+class QPID_COMMON_CLASS_EXTERN FieldValue {
+ public:
+ /*
+ * Abstract type for content of different types
+ */
+ class Data {
+ public:
+ virtual ~Data() {};
+ virtual uint32_t encodedSize() const = 0;
+ virtual void encode(Buffer& buffer) = 0;
+ virtual void decode(Buffer& buffer) = 0;
+ virtual bool operator==(const Data&) const = 0;
+
+ virtual bool convertsToInt() const { return false; }
+ virtual bool convertsToString() const { return false; }
+ virtual int64_t getInt() const { throw InvalidConversionException();}
+ virtual std::string getString() const { throw InvalidConversionException(); }
+
+ virtual void print(std::ostream& out) const = 0;
+ };
+
+ FieldValue(): data(0) {};
+ // Default assignment operator is fine
+ void setType(uint8_t type);
+ QPID_COMMON_EXTERN uint8_t getType() const;
+ Data& getData() { return *data; }
+ uint32_t encodedSize() const { return 1 + data->encodedSize(); };
+ bool empty() const { return data.get() == 0; }
+ void encode(Buffer& buffer);
+ void decode(Buffer& buffer);
+ QPID_COMMON_EXTERN bool operator==(const FieldValue&) const;
+ QPID_COMMON_INLINE_EXTERN bool operator!=(const FieldValue& v) const { return !(*this == v); }
+
+ QPID_COMMON_EXTERN void print(std::ostream& out) const;
+
+ template <typename T> bool convertsTo() const { return false; }
+ template <typename T> T get() const { throw InvalidConversionException(); }
+
+ template <class T, int W> T getIntegerValue() const;
+ template <class T> T getIntegerValue() const;
+ template <class T, int W> T getFloatingPointValue() const;
+ template <int W> void getFixedWidthValue(unsigned char*) const;
+ template <class T> bool get(T&) const;
+
+ protected:
+ FieldValue(uint8_t t, Data* d): typeOctet(t), data(d) {}
+
+ QPID_COMMON_EXTERN static uint8_t* convertIfRequired(uint8_t* const octets, int width);
+
+ private:
+ uint8_t typeOctet;
+ std::auto_ptr<Data> data;
+
+};
+
+template <>
+inline bool FieldValue::convertsTo<int>() const { return data->convertsToInt(); }
+
+template <>
+inline bool FieldValue::convertsTo<int64_t>() const { return data->convertsToInt(); }
+
+template <>
+inline bool FieldValue::convertsTo<std::string>() const { return data->convertsToString(); }
+
+template <>
+inline int FieldValue::get<int>() const { return static_cast<int>(data->getInt()); }
+
+template <>
+inline int64_t FieldValue::get<int64_t>() const { return data->getInt(); }
+
+template <>
+inline std::string FieldValue::get<std::string>() const { return data->getString(); }
+
+inline std::ostream& operator<<(std::ostream& out, const FieldValue& v) {
+ v.print(out);
+ return out;
+}
+
+template <int width>
+class FixedWidthValue : public FieldValue::Data {
+ uint8_t octets[width];
+
+ public:
+ FixedWidthValue() {}
+ FixedWidthValue(const uint8_t (&data)[width]) : octets(data) {}
+ FixedWidthValue(const uint8_t* const data)
+ {
+ for (int i = 0; i < width; i++) octets[i] = data[i];
+ }
+ FixedWidthValue(uint64_t v)
+ {
+ for (int i = width; i > 1; --i) {
+ octets[i-1] = (uint8_t) (0xFF & v); v >>= 8;
+ }
+ octets[0] = (uint8_t) (0xFF & v);
+ }
+ uint32_t encodedSize() const { return width; }
+ void encode(Buffer& buffer) { buffer.putRawData(octets, width); }
+ void decode(Buffer& buffer) { buffer.getRawData(octets, width); }
+ bool operator==(const Data& d) const {
+ const FixedWidthValue<width>* rhs = dynamic_cast< const FixedWidthValue<width>* >(&d);
+ if (rhs == 0) return false;
+ else return std::equal(&octets[0], &octets[width], &rhs->octets[0]);
+ }
+
+ bool convertsToInt() const { return true; }
+ int64_t getInt() const
+ {
+ int64_t v = 0;
+ for (int i = 0; i < width-1; ++i) {
+ v |= octets[i]; v <<= 8;
+ }
+ v |= octets[width-1];
+ return v;
+ }
+ uint8_t* rawOctets() { return octets; }
+ const uint8_t* rawOctets() const { return octets; }
+
+ void print(std::ostream& o) const { o << "F" << width << ":"; };
+};
+
+class UuidData : public FixedWidthValue<16> {
+ public:
+ UuidData();
+ UuidData(const unsigned char* bytes);
+ bool convertsToString() const;
+ std::string getString() const;
+};
+
+template <class T, int W>
+inline T FieldValue::getIntegerValue() const
+{
+ FixedWidthValue<W>* const fwv = dynamic_cast< FixedWidthValue<W>* const>(data.get());
+ if (fwv) {
+ uint8_t* octets = fwv->rawOctets();
+ T v = 0;
+ for (int i = 0; i < W-1; ++i) {
+ v |= octets[i]; v <<= 8;
+ }
+ v |= octets[W-1];
+ return v;
+ } else {
+ throw InvalidConversionException();
+ }
+}
+
+template <class T>
+inline T FieldValue::getIntegerValue() const
+{
+ FixedWidthValue<1>* const fwv = dynamic_cast< FixedWidthValue<1>* const>(data.get());
+ if (fwv) {
+ uint8_t* octets = fwv->rawOctets();
+ return octets[0];
+ } else {
+ throw InvalidConversionException();
+ }
+}
+
+template <class T, int W>
+inline T FieldValue::getFloatingPointValue() const {
+ FixedWidthValue<W>* const fwv = dynamic_cast< FixedWidthValue<W>* const>(data.get());
+ if (fwv) {
+ T value;
+ uint8_t* const octets = convertIfRequired(fwv->rawOctets(), W);
+ uint8_t* const target = reinterpret_cast<uint8_t*>(&value);
+ for (size_t i = 0; i < W; ++i) target[i] = octets[i];
+ return value;
+ } else {
+ throw InvalidConversionException();
+ }
+}
+
+template <int W> void FieldValue::getFixedWidthValue(unsigned char* value) const
+{
+ FixedWidthValue<W>* const fwv = dynamic_cast< FixedWidthValue<W>* const>(data.get());
+ if (fwv) {
+ for (size_t i = 0; i < W; ++i) value[i] = fwv->rawOctets()[i];
+ } else {
+ throw InvalidConversionException();
+ }
+}
+
+template <>
+inline float FieldValue::get<float>() const {
+ return getFloatingPointValue<float, 4>();
+}
+
+template <>
+inline double FieldValue::get<double>() const {
+ return getFloatingPointValue<double, 8>();
+}
+
+template <>
+class FixedWidthValue<0> : public FieldValue::Data {
+ public:
+ // Implicit default constructor is fine
+ uint32_t encodedSize() const { return 0; }
+ void encode(Buffer&) {};
+ void decode(Buffer&) {};
+ bool operator==(const Data& d) const {
+ const FixedWidthValue<0>* rhs = dynamic_cast< const FixedWidthValue<0>* >(&d);
+ return rhs != 0;
+ }
+ void print(std::ostream& o) const { o << "F0"; };
+};
+
+template <int lenwidth>
+class VariableWidthValue : public FieldValue::Data {
+ std::vector<uint8_t> octets;
+
+ public:
+ VariableWidthValue() {}
+ VariableWidthValue(const std::vector<uint8_t>& data) : octets(data) {}
+ VariableWidthValue(const uint8_t* start, const uint8_t* end) : octets(start, end) {}
+ uint32_t encodedSize() const { return lenwidth + octets.size(); }
+ void encode(Buffer& buffer) {
+ buffer.putUInt<lenwidth>(octets.size());
+ if (octets.size() > 0)
+ buffer.putRawData(&octets[0], octets.size());
+ };
+ void decode(Buffer& buffer) {
+ uint32_t len = buffer.getUInt<lenwidth>();
+ buffer.checkAvailable(len);
+ octets.resize(len);
+ if (len > 0)
+ buffer.getRawData(&octets[0], len);
+ }
+ bool operator==(const Data& d) const {
+ const VariableWidthValue<lenwidth>* rhs = dynamic_cast< const VariableWidthValue<lenwidth>* >(&d);
+ if (rhs == 0) return false;
+ else return octets==rhs->octets;
+ }
+
+ bool convertsToString() const { return true; }
+ std::string getString() const { return std::string(octets.begin(), octets.end()); }
+
+ void print(std::ostream& o) const { o << "V" << lenwidth << ":" << octets.size() << ":"; };
+};
+
+template <class T>
+class EncodedValue : public FieldValue::Data {
+ T value;
+ public:
+
+ EncodedValue() {}
+ EncodedValue(const T& v) : value(v) {}
+
+ T& getValue() { return value; }
+ const T& getValue() const { return value; }
+
+ uint32_t encodedSize() const { return value.encodedSize(); }
+
+ void encode(Buffer& buffer) {
+ value.encode(buffer);
+ };
+ void decode(Buffer& buffer) {
+ value.decode(buffer);
+ }
+ bool operator==(const Data& d) const {
+ const EncodedValue<T>* rhs = dynamic_cast< const EncodedValue<T>* >(&d);
+ if (rhs == 0) return false;
+ else return value==rhs->value;
+ }
+
+ void print(std::ostream& o) const { o << "[" << value << "]"; };
+};
+
+/**
+ * Accessor that can be used to get values of type FieldTable, Array
+ * and List.
+ */
+template <class T>
+inline bool FieldValue::get(T& t) const
+{
+ const EncodedValue<T>* v = dynamic_cast< EncodedValue<T>* >(data.get());
+ if (v != 0) {
+ t = v->getValue();
+ return true;
+ } else {
+ try {
+ t = get<T>();
+ return true;
+ } catch (const InvalidConversionException&) {
+ return false;
+ }
+ }
+}
+
+class Str8Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Str8Value(const std::string& v);
+};
+
+class Str16Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Str16Value(const std::string& v);
+};
+
+class Var16Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Var16Value(const std::string& v, uint8_t code);
+};
+
+class Var32Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Var32Value(const std::string& v, uint8_t code);
+ };
+
+class Struct32Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Struct32Value(const std::string& v);
+};
+
+class FloatValue : public FieldValue
+{
+ public:
+ QPID_COMMON_EXTERN FloatValue(float f);
+};
+class DoubleValue : public FieldValue
+{
+ public:
+ QPID_COMMON_EXTERN DoubleValue(double f);
+};
+
+/*
+ * Basic integer value encodes as signed 32 bit
+ */
+class IntegerValue : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN IntegerValue(int v);
+};
+
+class TimeValue : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN TimeValue(uint64_t v);
+};
+
+class Integer64Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Integer64Value(int64_t v);
+};
+
+class Unsigned64Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Unsigned64Value(uint64_t v);
+};
+
+class FieldTableValue : public FieldValue {
+ public:
+ typedef FieldTable ValueType;
+ QPID_COMMON_EXTERN FieldTableValue(const FieldTable&);
+};
+
+class ArrayValue : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN ArrayValue(const Array&);
+};
+
+class VoidValue : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN VoidValue();
+};
+
+class BoolValue : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN BoolValue(bool);
+};
+
+class Unsigned8Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Unsigned8Value(uint8_t);
+};
+
+class Unsigned16Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Unsigned16Value(uint16_t);
+};
+
+class Unsigned32Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Unsigned32Value(uint32_t);
+};
+
+class Integer8Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Integer8Value(int8_t);
+};
+
+class Integer16Value : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN Integer16Value(int16_t);
+};
+
+typedef IntegerValue Integer32Value;
+
+class ListValue : public FieldValue {
+ public:
+ typedef List ValueType;
+ QPID_COMMON_EXTERN ListValue(const List&);
+};
+
+class UuidValue : public FieldValue {
+ public:
+ QPID_COMMON_EXTERN UuidValue();
+ QPID_COMMON_EXTERN UuidValue(const unsigned char*);
+};
+
+template <class T>
+bool getEncodedValue(FieldTable::ValuePtr vptr, T& value)
+{
+ if (vptr) {
+ const EncodedValue<T>* ev = dynamic_cast< EncodedValue<T>* >(&(vptr->getData()));
+ if (ev != 0) {
+ value = ev->getValue();
+ return true;
+ }
+ }
+ return false;
+}
+
+}} // qpid::framing
+
+#endif
diff --git a/qpid/cpp/src/qpid/framing/FrameSet.h b/qpid/cpp/src/qpid/framing/FrameSet.h
index 9640abb7ac..4188fd9b8c 100644
--- a/qpid/cpp/src/qpid/framing/FrameSet.h
+++ b/qpid/cpp/src/qpid/framing/FrameSet.h
@@ -9,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
@@ -44,6 +44,8 @@ class FrameSet
public:
typedef boost::shared_ptr<FrameSet> shared_ptr;
+ typedef Frames::iterator iterator;
+ typedef Frames::const_iterator const_iterator;
QPID_COMMON_EXTERN FrameSet(const SequenceNumber& id);
QPID_COMMON_EXTERN FrameSet(const FrameSet&);
@@ -62,7 +64,7 @@ public:
QPID_COMMON_EXTERN AMQMethodBody* getMethod();
QPID_COMMON_EXTERN const AMQHeaderBody* getHeaders() const;
QPID_COMMON_EXTERN AMQHeaderBody* getHeaders();
-
+
template <class T> bool isA() const {
const AMQMethodBody* method = getMethod();
return method && method->isA<T>();
@@ -71,12 +73,12 @@ public:
template <class T> const T* as() const {
const AMQMethodBody* method = getMethod();
return (method && method->isA<T>()) ? dynamic_cast<const T*>(method) : 0;
- }
+ }
template <class T> T* as() {
AMQMethodBody* method = getMethod();
return (method && method->isA<T>()) ? dynamic_cast<T*>(method) : 0;
- }
+ }
template <class T> const T* getHeaderProperties() const {
const AMQHeaderBody* header = getHeaders();
@@ -85,7 +87,7 @@ public:
Frames::const_iterator begin() const { return parts.begin(); }
Frames::const_iterator end() const { return parts.end(); }
-
+
const SequenceNumber& getId() const { return id; }
template <class P> void remove(P predicate) {
diff --git a/qpid/cpp/src/qpid/framing/List.h b/qpid/cpp/src/qpid/framing/List.h
new file mode 100644
index 0000000000..681445947c
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/List.h
@@ -0,0 +1,78 @@
+#ifndef QPID_FRAMING_LIST_H
+#define QPID_FRAMING_LIST_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/CommonImportExport.h"
+#include "qpid/framing/amqp_types.h"
+#include <iostream>
+#include <list>
+#include <boost/shared_ptr.hpp>
+
+namespace qpid {
+namespace framing {
+
+class Buffer;
+class FieldValue;
+
+/**
+ * Representation of an AMQP 0-10 list
+ */
+class QPID_COMMON_CLASS_EXTERN List
+{
+ public:
+ typedef boost::shared_ptr<FieldValue> ValuePtr;
+ typedef ValuePtr value_type;
+ typedef std::list<ValuePtr> Values;
+ typedef Values::const_iterator const_iterator;
+ typedef Values::iterator iterator;
+ typedef Values::const_reference const_reference;
+ typedef Values::reference reference;
+
+ QPID_COMMON_EXTERN uint32_t encodedSize() const;
+ QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
+ QPID_COMMON_EXTERN void decode(Buffer& buffer);
+
+ QPID_COMMON_EXTERN bool operator==(const List& other) const;
+
+ // std collection interface.
+ QPID_COMMON_INLINE_EXTERN const_iterator begin() const { return values.begin(); }
+ QPID_COMMON_INLINE_EXTERN const_iterator end() const { return values.end(); }
+ QPID_COMMON_INLINE_EXTERN iterator begin() { return values.begin(); }
+ QPID_COMMON_INLINE_EXTERN iterator end(){ return values.end(); }
+
+ QPID_COMMON_INLINE_EXTERN ValuePtr front() const { return values.front(); }
+ QPID_COMMON_INLINE_EXTERN ValuePtr back() const { return values.back(); }
+ QPID_COMMON_INLINE_EXTERN size_t size() const { return values.size(); }
+
+ QPID_COMMON_INLINE_EXTERN iterator insert(iterator i, ValuePtr value) { return values.insert(i, value); }
+ QPID_COMMON_INLINE_EXTERN void erase(iterator i) { values.erase(i); }
+ QPID_COMMON_INLINE_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
+ QPID_COMMON_INLINE_EXTERN void pop_back() { values.pop_back(); }
+
+ private:
+ Values values;
+
+ friend QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& out, const List& list);
+};
+}} // namespace qpid::framing
+
+#endif /*!QPID_FRAMING_LIST_H*/
diff --git a/qpid/cpp/src/qpid/framing/ProtocolVersion.h b/qpid/cpp/src/qpid/framing/ProtocolVersion.h
new file mode 100644
index 0000000000..309e543516
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/ProtocolVersion.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#ifndef _ProtocolVersion_
+#define _ProtocolVersion_
+
+#include "qpid/framing/amqp_types.h"
+#include "qpid/CommonImportExport.h"
+
+#include <string>
+
+namespace qpid
+{
+namespace framing
+{
+
+class QPID_COMMON_CLASS_EXTERN ProtocolVersion
+{
+private:
+ uint8_t major_;
+ uint8_t minor_;
+ uint8_t protocol_;
+
+public:
+ explicit ProtocolVersion(uint8_t _major=0, uint8_t _minor=0, uint8_t _protocol=0)
+ : major_(_major), minor_(_minor), protocol_(_protocol) {}
+
+ QPID_COMMON_INLINE_EXTERN uint8_t getMajor() const { return major_; }
+ QPID_COMMON_INLINE_EXTERN void setMajor(uint8_t major) { major_ = major; }
+ QPID_COMMON_INLINE_EXTERN uint8_t getMinor() const { return minor_; }
+ QPID_COMMON_INLINE_EXTERN void setMinor(uint8_t minor) { minor_ = minor; }
+ QPID_COMMON_INLINE_EXTERN uint8_t getProtocol() const { return protocol_; }
+ QPID_COMMON_INLINE_EXTERN void setProtocol(uint8_t protocol) { protocol_ = protocol; }
+ QPID_COMMON_EXTERN const std::string toString() const;
+
+ QPID_COMMON_EXTERN ProtocolVersion& operator=(ProtocolVersion p);
+
+ QPID_COMMON_EXTERN bool operator==(ProtocolVersion p) const;
+ QPID_COMMON_INLINE_EXTERN bool operator!=(ProtocolVersion p) const { return ! (*this == p); }
+ QPID_COMMON_EXTERN static uint8_t AMQP;
+ QPID_COMMON_EXTERN static uint8_t LEGACY_AMQP;
+ QPID_COMMON_EXTERN static uint8_t TLS;
+ QPID_COMMON_EXTERN static uint8_t SASL;
+};
+
+} // namespace framing
+} // namespace qpid
+
+
+#endif // ifndef _ProtocolVersion_
diff --git a/qpid/cpp/src/qpid/framing/SequenceNumber.h b/qpid/cpp/src/qpid/framing/SequenceNumber.h
new file mode 100644
index 0000000000..00fa2469c8
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/SequenceNumber.h
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#ifndef _framing_SequenceNumber_h
+#define _framing_SequenceNumber_h
+
+#include "qpid/framing/amqp_types.h"
+#include <boost/operators.hpp>
+#include <iosfwd>
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+namespace framing {
+
+class Buffer;
+
+/**
+ * 4-byte sequence number that 'wraps around'.
+ */
+class QPID_COMMON_CLASS_EXTERN SequenceNumber : public
+boost::equality_comparable<
+ SequenceNumber, boost::less_than_comparable<
+ SequenceNumber, boost::incrementable<
+ SequenceNumber, boost::decrementable<SequenceNumber> > > >
+{
+ int32_t value;
+
+ public:
+ SequenceNumber(uint32_t v=0) : value(v) {}
+
+ SequenceNumber& operator++() { ++value; return *this; }
+ SequenceNumber& operator--() { --value; return *this; }
+ bool operator==(const SequenceNumber& other) const { return value == other.value; }
+ bool operator<(const SequenceNumber& other) const { return (value - other.value) < 0; }
+ uint32_t getValue() const { return uint32_t(value); }
+ operator uint32_t() const { return uint32_t(value); }
+
+ QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
+ QPID_COMMON_EXTERN void decode(Buffer& buffer);
+ QPID_COMMON_EXTERN uint32_t encodedSize() const;
+
+ template <class S> void serialize(S& s) { s(value); }
+};
+
+inline int32_t operator-(const SequenceNumber& a, const SequenceNumber& b) {
+ return int32_t(a.getValue() - b.getValue());
+}
+
+inline SequenceNumber operator+(const SequenceNumber& a, int32_t n) {
+ return SequenceNumber(a.getValue() + n);
+}
+
+inline SequenceNumber operator-(const SequenceNumber& a, int32_t n) {
+ return SequenceNumber(a.getValue() - n);
+}
+
+struct Window
+{
+ SequenceNumber hwm;
+ SequenceNumber lwm;
+};
+
+QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& o, const SequenceNumber& n);
+
+}} // namespace qpid::framing
+
+
+#endif
diff --git a/qpid/cpp/src/qpid/framing/SequenceSet.h b/qpid/cpp/src/qpid/framing/SequenceSet.h
new file mode 100644
index 0000000000..827c8999b3
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/SequenceSet.h
@@ -0,0 +1,69 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#ifndef _framing_SequenceSet_h
+#define _framing_SequenceSet_h
+
+#include "qpid/framing/SequenceNumber.h"
+#include "qpid/RangeSet.h"
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+namespace framing {
+class Buffer;
+
+class QPID_COMMON_CLASS_EXTERN SequenceSet : public RangeSet<SequenceNumber> {
+ public:
+ SequenceSet() {}
+ SequenceSet(const RangeSet<SequenceNumber>& r)
+ : RangeSet<SequenceNumber>(r) {}
+ SequenceSet(const SequenceNumber& s) { add(s); }
+ SequenceSet(const SequenceNumber& start, const SequenceNumber finish) { add(start,finish); }
+
+
+ QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
+ QPID_COMMON_EXTERN void decode(Buffer& buffer);
+ QPID_COMMON_EXTERN uint32_t encodedSize() const;
+
+ QPID_COMMON_EXTERN bool contains(const SequenceNumber& s) const;
+ QPID_COMMON_EXTERN void add(const SequenceNumber& s);
+ QPID_COMMON_EXTERN void add(const SequenceNumber& start, const SequenceNumber& finish); // Closed range
+ QPID_COMMON_EXTERN void add(const SequenceSet& set);
+ QPID_COMMON_EXTERN void remove(const SequenceNumber& s);
+ QPID_COMMON_EXTERN void remove(const SequenceNumber& start, const SequenceNumber& finish); // Closed range
+ QPID_COMMON_EXTERN void remove(const SequenceSet& set);
+
+ template <class T> void for_each(T& t) const {
+ for (RangeIterator i = rangesBegin(); i != rangesEnd(); i++)
+ t(i->first(), i->last());
+ }
+
+ template <class T> void for_each(const T& t) const {
+ for (RangeIterator i = rangesBegin(); i != rangesEnd(); i++)
+ t(i->first(), i->last());
+ }
+
+ friend QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const SequenceSet&);
+};
+
+}} // namespace qpid::framing
+
+
+#endif
diff --git a/qpid/cpp/src/qpid/framing/StructHelper.h b/qpid/cpp/src/qpid/framing/StructHelper.h
new file mode 100644
index 0000000000..fe2fa64ce7
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/StructHelper.h
@@ -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.
+ *
+ */
+#ifndef _StructHelper_
+#define _StructHelper_
+
+#include "qpid/Exception.h"
+#include "qpid/CommonImportExport.h"
+#include "qpid/framing/Buffer.h"
+
+#include <stdlib.h> // For alloca
+
+namespace qpid {
+namespace framing {
+
+class QPID_COMMON_CLASS_EXTERN StructHelper
+{
+public:
+
+ template <class T> void encode(const T& t, std::string& data) {
+ uint32_t size = t.bodySize() + 2/*type*/;
+ data.resize(size);
+ Buffer wbuffer(const_cast<char*>(data.data()), size);
+ wbuffer.putShort(T::TYPE);
+ t.encodeStructBody(wbuffer);
+ }
+
+ template <class T> void decode(T& t, const std::string& data) {
+ Buffer rbuffer(const_cast<char*>(data.data()), data.length());
+ uint16_t type = rbuffer.getShort();
+ if (type == T::TYPE) {
+ t.decodeStructBody(rbuffer);
+ } else {
+ throw Exception("Type code does not match");
+ }
+ }
+};
+
+}}
+#endif
diff --git a/qpid/cpp/src/qpid/framing/Uuid.h b/qpid/cpp/src/qpid/framing/Uuid.h
new file mode 100644
index 0000000000..e9e56ed7c9
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/Uuid.h
@@ -0,0 +1,94 @@
+#ifndef QPID_FRAMING_UUID_H
+#define QPID_FRAMING_UUID_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/CommonImportExport.h"
+#include "qpid/sys/IntegerTypes.h"
+
+#include <boost/array.hpp>
+
+#include <ostream>
+#include <istream>
+
+namespace qpid {
+namespace framing {
+
+class Buffer;
+
+/**
+ * A UUID is represented as a boost::array of 16 bytes.
+ *
+ * Full value semantics, operators ==, < etc. are provided by
+ * boost::array so Uuid can be the key type in a map etc.
+ *
+ * TODO: change this implementation as it leaks boost into the
+ * client API
+ */
+struct Uuid : public boost::array<uint8_t, 16> {
+ /** If unique is true, generate a unique ID else a null ID. */
+ QPID_COMMON_EXTERN Uuid(bool unique=false);
+
+ /** Copy from 16 bytes of data. */
+ QPID_COMMON_EXTERN Uuid(const uint8_t* data);
+
+ /** Parse format 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb. */
+ QPID_COMMON_EXTERN Uuid(const std::string&);
+
+ // Default op= and copy ctor are fine.
+ // boost::array gives us ==, < etc.
+
+ /** Copy from 16 bytes of data. */
+ QPID_COMMON_EXTERN void assign(const uint8_t* data);
+
+ /** Set to a new unique identifier. */
+ QPID_COMMON_EXTERN void generate();
+
+ /** Set to all zeros. */
+ QPID_COMMON_EXTERN void clear();
+
+ /** Test for null (all zeros). */
+ QPID_COMMON_EXTERN bool isNull() const;
+ QPID_COMMON_INLINE_EXTERN operator bool() const { return !isNull(); }
+ QPID_COMMON_INLINE_EXTERN bool operator!() const { return isNull(); }
+
+ QPID_COMMON_EXTERN void encode(framing::Buffer& buf) const;
+ QPID_COMMON_EXTERN void decode(framing::Buffer& buf);
+ QPID_COMMON_INLINE_EXTERN uint32_t encodedSize() const
+ { return static_cast<uint32_t>(size()); }
+
+ /** String value in format 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb. */
+ QPID_COMMON_EXTERN std::string str() const;
+
+ template <class S> void serialize(S& s) {
+ s.raw(begin(), size());
+ }
+};
+
+/** Print in format 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb. */
+QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, Uuid);
+
+/** Read from format 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb. */
+QPID_COMMON_EXTERN std::istream& operator>>(std::istream&, Uuid&);
+
+}} // namespace qpid::framing
+
+
+
+#endif /*!QPID_FRAMING_UUID_H*/
diff --git a/qpid/cpp/src/qpid/framing/amqp_types.h b/qpid/cpp/src/qpid/framing/amqp_types.h
new file mode 100644
index 0000000000..2072a83904
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/amqp_types.h
@@ -0,0 +1,64 @@
+#ifndef AMQP_TYPES_H
+#define AMQP_TYPES_H
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+/** \file
+ * Definitions and forward declarations of all types used
+ * in AMQP messages.
+ */
+
+#include "qpid/sys/IntegerTypes.h"
+
+namespace qpid {
+namespace framing {
+
+typedef uint8_t FrameType;
+typedef uint16_t ChannelId;
+typedef uint32_t BatchOffset;
+typedef uint8_t ClassId;
+typedef uint8_t MethodId;
+typedef uint16_t ReplyCode;
+
+// Types represented by classes.
+class Content;
+class FieldTable;
+class SequenceNumberSet;
+struct Uuid;
+
+// Useful constants
+
+/** Maximum channel ID used by broker. Reserve high bit for internal use.*/
+const ChannelId CHANNEL_MAX=(ChannelId(~1))>>1;
+const ChannelId CHANNEL_HIGH_BIT= ChannelId(~CHANNEL_MAX);
+
+// Forward declare class types
+class FramingContent;
+class FieldTable;
+class SequenceNumberSet;
+class SequenceSet;
+struct Uuid;
+
+// Enum types
+enum DeliveryMode { TRANSIENT = 1, PERSISTENT = 2};
+
+}} // namespace qpid::framing
+#endif
diff --git a/qpid/cpp/src/qpid/framing/amqp_types_full.h b/qpid/cpp/src/qpid/framing/amqp_types_full.h
new file mode 100644
index 0000000000..c5d84dedea
--- /dev/null
+++ b/qpid/cpp/src/qpid/framing/amqp_types_full.h
@@ -0,0 +1,38 @@
+#ifndef _framing_amqp_types_decl_h
+#define _framing_amqp_types_decl_h
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/** \file
+ * Definitions and full declarations of all types used
+ * in AMQP messages.
+ *
+ * It's better to include amqp_types.h in another header instead of this file
+ * unless the header actually needs the full declarations. Including
+ * full declarations when forward declarations would increase compile
+ * times.
+ */
+
+#include "qpid/framing/amqp_types.h"
+#include "qpid/framing/Array.h"
+#include "qpid/framing/FieldTable.h"
+#include "qpid/framing/SequenceSet.h"
+#include "qpid/framing/Uuid.h"
+
+#endif /*!_framing_amqp_types_decl_h*/
diff --git a/qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h b/qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h
index 2386a01084..fbf4755e7d 100644
--- a/qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h
+++ b/qpid/cpp/src/qpid/ha/AlternateExchangeSetter.h
@@ -25,7 +25,6 @@
#include "qpid/log/Statement.h"
#include "qpid/broker/Exchange.h"
#include "qpid/broker/ExchangeRegistry.h"
-#include "boost/function.hpp"
#include <map>
namespace qpid {
diff --git a/qpid/cpp/src/qpid/ha/Backup.cpp b/qpid/cpp/src/qpid/ha/Backup.cpp
index e28ca1fa6a..503de3e351 100644
--- a/qpid/cpp/src/qpid/ha/Backup.cpp
+++ b/qpid/cpp/src/qpid/ha/Backup.cpp
@@ -52,9 +52,7 @@ using sys::Mutex;
Backup::Backup(HaBroker& hb, const Settings& s) :
logPrefix("Backup: "), membership(hb.getMembership()), stopped(false),
haBroker(hb), broker(hb.getBroker()), settings(s),
- statusCheck(
- new StatusCheck(
- logPrefix, broker.getOptions().linkHeartbeatInterval, hb.getBrokerInfo()))
+ statusCheck(new StatusCheck(hb))
{}
void Backup::setBrokerUrl(const Url& brokers) {
diff --git a/qpid/cpp/src/qpid/ha/Backup.h b/qpid/cpp/src/qpid/ha/Backup.h
index 4943ca5e2e..88194158ce 100644
--- a/qpid/cpp/src/qpid/ha/Backup.h
+++ b/qpid/cpp/src/qpid/ha/Backup.h
@@ -59,6 +59,8 @@ class Backup : public Role
Role* promote();
+ boost::shared_ptr<BrokerReplicator> getBrokerReplicator() { return replicator; }
+
private:
void stop(sys::Mutex::ScopedLock&);
Role* recover(sys::Mutex::ScopedLock&);
diff --git a/qpid/cpp/src/qpid/ha/BrokerInfo.h b/qpid/cpp/src/qpid/ha/BrokerInfo.h
index bd1ad86392..87d51f5113 100644
--- a/qpid/cpp/src/qpid/ha/BrokerInfo.h
+++ b/qpid/cpp/src/qpid/ha/BrokerInfo.h
@@ -23,6 +23,7 @@
*/
#include "types.h"
+#include "hash.h"
#include "qpid/Url.h"
#include "qpid/framing/FieldTable.h"
#include "qpid/types/Uuid.h"
@@ -42,7 +43,7 @@ class BrokerInfo
{
public:
typedef std::set<BrokerInfo> Set;
- typedef qpid::sys::unordered_map<types::Uuid, BrokerInfo, types::Uuid::Hasher> Map;
+ typedef qpid::sys::unordered_map<types::Uuid, BrokerInfo, Hasher<types::Uuid> > Map;
BrokerInfo();
BrokerInfo(const types::Uuid& id, BrokerStatus, const Address& = Address());
diff --git a/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp b/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp
index 17b00185ef..eb1206437a 100644
--- a/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp
+++ b/qpid/cpp/src/qpid/ha/BrokerReplicator.cpp
@@ -21,6 +21,7 @@
#include "BrokerReplicator.h"
#include "HaBroker.h"
#include "QueueReplicator.h"
+#include "TxReplicator.h"
#include "qpid/broker/Broker.h"
#include "qpid/broker/amqp_0_10/Connection.h"
#include "qpid/broker/ConnectionObserver.h"
@@ -129,7 +130,6 @@ const string COLON(":");
void sendQuery(const string& packageName, const string& className, const string& queueName,
SessionHandler& sessionHandler)
{
- framing::AMQP_ServerProxy peer(sessionHandler.out);
Variant::Map request;
request[WHAT] = OBJECT;
Variant::Map schema;
@@ -229,8 +229,8 @@ class BrokerReplicator::UpdateTracker {
typedef boost::function<void (const std::string&)> CleanFn;
UpdateTracker(const std::string& type_, // "queue" or "exchange"
- CleanFn f, const ReplicationTest& rt)
- : type(type_), cleanFn(f), repTest(rt) {}
+ CleanFn f)
+ : type(type_), cleanFn(f) {}
/** Destructor cleans up remaining initial queues. */
~UpdateTracker() {
@@ -245,16 +245,10 @@ class BrokerReplicator::UpdateTracker {
}
/** Add an exchange name */
- void addExchange(Exchange::shared_ptr ex) {
- if (repTest.getLevel(*ex))
- initial.insert(ex->getName());
- }
+ void addExchange(Exchange::shared_ptr ex) { initial.insert(ex->getName()); }
/** Add a queue name. */
- void addQueue(Queue::shared_ptr q) {
- if (repTest.getLevel(*q))
- initial.insert(q->getName());
- }
+ void addQueue(Queue::shared_ptr q) { initial.insert(q->getName()); }
/** Received an event for name */
void event(const std::string& name) {
@@ -275,13 +269,13 @@ class BrokerReplicator::UpdateTracker {
void clean(const std::string& name) {
QPID_LOG(info, "Backup: Deleted " << type << " " << name <<
": no longer exists on primary");
- cleanFn(name);
+ try { cleanFn(name); }
+ catch (const framing::NotFoundException&) {}
}
std::string type;
Names initial, events;
CleanFn cleanFn;
- ReplicationTest repTest;
};
namespace {
@@ -349,7 +343,8 @@ BrokerReplicator::~BrokerReplicator() { shutdown(); }
namespace {
void collectQueueReplicators(
- const boost::shared_ptr<Exchange> ex, set<boost::shared_ptr<QueueReplicator> >& collect)
+ const boost::shared_ptr<Exchange>& ex,
+ set<boost::shared_ptr<QueueReplicator> >& collect)
{
boost::shared_ptr<QueueReplicator> qr(boost::dynamic_pointer_cast<QueueReplicator>(ex));
if (qr) collect.insert(qr);
@@ -390,16 +385,13 @@ void BrokerReplicator::connected(Bridge& bridge, SessionHandler& sessionHandler)
exchangeTracker.reset(
new UpdateTracker("exchange",
- boost::bind(&BrokerReplicator::deleteExchange, this, _1),
- replicationTest));
- exchanges.eachExchange(
- boost::bind(&UpdateTracker::addExchange, exchangeTracker.get(), _1));
+ boost::bind(&BrokerReplicator::deleteExchange, this, _1)));
+ exchanges.eachExchange(boost::bind(&BrokerReplicator::existingExchange, this, _1));
queueTracker.reset(
new UpdateTracker("queue",
- boost::bind(&BrokerReplicator::deleteQueue, this, _1, true),
- replicationTest));
- queues.eachQueue(boost::bind(&UpdateTracker::addQueue, queueTracker.get(), _1));
+ boost::bind(&BrokerReplicator::deleteQueue, this, _1, true)));
+ queues.eachQueue(boost::bind(&BrokerReplicator::existingQueue, this, _1));
framing::AMQP_ServerProxy peer(sessionHandler.out);
const qmf::org::apache::qpid::broker::ArgsLinkBridge& args(bridge.getArgs());
@@ -428,6 +420,21 @@ void BrokerReplicator::connected(Bridge& bridge, SessionHandler& sessionHandler)
sendQuery(ORG_APACHE_QPID_BROKER, BINDING, queueName, sessionHandler);
}
+// Called for each queue in existence when the backup connects to a primary.
+void BrokerReplicator::existingQueue(const boost::shared_ptr<Queue>& q) {
+ if (replicationTest.getLevel(*q)) {
+ QPID_LOG(debug, "Existing queue: " << q->getName());
+ queueTracker->addQueue(q);
+ }
+}
+
+void BrokerReplicator::existingExchange(const boost::shared_ptr<Exchange>& ex) {
+ if (replicationTest.getLevel(*ex)) {
+ QPID_LOG(debug, "Existing exchange: " << ex->getName());
+ exchangeTracker->addExchange(ex);
+ }
+}
+
void BrokerReplicator::route(Deliverable& msg) {
// We transition from JOINING->CATCHUP on the first message received from the primary.
// Until now we couldn't be sure if we had a good connection to the primary.
@@ -554,11 +561,7 @@ void BrokerReplicator::doEventExchangeDeclare(Variant::Map& values) {
void BrokerReplicator::doEventExchangeDelete(Variant::Map& values) {
string name = values[EXNAME].asString();
boost::shared_ptr<Exchange> exchange = exchanges.find(name);
- if (!exchange) {
- QPID_LOG(warning, logPrefix << "Exchange delete event, not found: " << name);
- } else if (!replicationTest.getLevel(*exchange)) {
- QPID_LOG(warning, logPrefix << "Exchange delete event, not replicated: " << name);
- } else {
+ if (exchange && replicationTest.getLevel(*exchange)) {
QPID_LOG(debug, logPrefix << "Exchange delete event:" << name);
if (exchangeTracker.get()) exchangeTracker->event(name);
deleteExchange(name);
@@ -651,8 +654,10 @@ void BrokerReplicator::doResponseQueue(Variant::Map& values) {
if (!queueTracker.get())
throw Exception(QPID_MSG("Unexpected queue response: " << values));
if (!queueTracker->response(name)) return; // Response is out-of-date
+
QPID_LOG(debug, logPrefix << "Queue response: " << name);
boost::shared_ptr<Queue> queue = queues.find(name);
+
if (queue) { // Already exists
bool uuidOk = (getHaUuid(queue->getSettings().original) == getHaUuid(argsMap));
if (!uuidOk) QPID_LOG(debug, logPrefix << "UUID mismatch for queue: " << name);
@@ -660,6 +665,7 @@ void BrokerReplicator::doResponseQueue(Variant::Map& values) {
QPID_LOG(debug, logPrefix << "Queue response replacing queue: " << name);
deleteQueue(name);
}
+
framing::FieldTable args;
qpid::amqp_0_10::translate(argsMap, args);
boost::shared_ptr<QueueReplicator> qr = replicateQueue(
@@ -770,8 +776,13 @@ boost::shared_ptr<QueueReplicator> BrokerReplicator::startQueueReplicator(
const boost::shared_ptr<Queue>& queue)
{
if (replicationTest.getLevel(*queue) == ALL) {
- boost::shared_ptr<QueueReplicator> qr(
- new QueueReplicator(haBroker, queue, link));
+ boost::shared_ptr<QueueReplicator> qr;
+ if (TxReplicator::isTxQueue(queue->getName())){
+ qr.reset(new TxReplicator(haBroker, queue, link));
+ }
+ else {
+ qr.reset(new QueueReplicator(haBroker, queue, link));
+ }
qr->activate();
return qr;
}
@@ -785,7 +796,7 @@ void BrokerReplicator::deleteQueue(const std::string& name, bool purge) {
// messages. Any reroutes will be done at the primary and
// replicated as normal.
if (purge) queue->purge(0, boost::shared_ptr<Exchange>());
- broker.deleteQueue(name, userId, remoteHost);
+ haBroker.getBroker().deleteQueue(name, userId, remoteHost);
QPID_LOG(debug, logPrefix << "Queue deleted: " << name);
}
}
@@ -864,28 +875,35 @@ bool BrokerReplicator::isBound(boost::shared_ptr<Queue>, const string* const, co
string BrokerReplicator::getType() const { return QPID_CONFIGURATION_REPLICATOR; }
-void BrokerReplicator::autoDeleteCheck(boost::shared_ptr<Exchange> ex) {
+void BrokerReplicator::disconnectedExchange(boost::shared_ptr<Exchange> ex) {
boost::shared_ptr<QueueReplicator> qr(boost::dynamic_pointer_cast<QueueReplicator>(ex));
- if (!qr) return;
- assert(qr);
- if (qr->getQueue()->isAutoDelete() && qr->isSubscribed()) {
- if (qr->getQueue()->getSettings().autoDeleteDelay) {
- // Start the auto-delete timer
- qr->getQueue()->releaseFromUse();
- qr->getQueue()->scheduleAutoDelete();
+ if (qr) {
+ qr->disconnect();
+ if (TxReplicator::isTxQueue(qr->getQueue()->getName())) {
+ // Transactions are aborted on failover so clean up tx-queues
+ deleteQueue(qr->getQueue()->getName());
}
- else {
- // Delete immediately. Don't purge, the primary is gone so we need
- // to reroute the deleted messages.
- deleteQueue(qr->getQueue()->getName(), false);
+ else if (qr->getQueue()->isAutoDelete() && qr->isSubscribed()) {
+ if (qr->getQueue()->getSettings().autoDeleteDelay) {
+ // Start the auto-delete timer
+ qr->getQueue()->releaseFromUse();
+ qr->getQueue()->scheduleAutoDelete();
+ }
+ else {
+ // Delete immediately. Don't purge, the primary is gone so we need
+ // to reroute the deleted messages.
+ deleteQueue(qr->getQueue()->getName(), false);
+ }
}
}
}
+typedef vector<boost::shared_ptr<Exchange> > ExchangeVector;
+
// Callback function for accumulating exchange candidates
namespace {
- void exchangeAccumulatorCallback(vector<boost::shared_ptr<Exchange> >& c, const Exchange::shared_ptr& i) {
- c.push_back(i);
+ void exchangeAccumulatorCallback(ExchangeVector& ev, const Exchange::shared_ptr& i) {
+ ev.push_back(i);
}
}
@@ -893,13 +911,12 @@ namespace {
void BrokerReplicator::disconnected() {
QPID_LOG(info, logPrefix << "Disconnected from primary " << primary);
connection = 0;
- // Clean up auto-delete queues
- vector<boost::shared_ptr<Exchange> > collect;
- // Make a copy so we can work outside the ExchangeRegistry lock
- exchanges.eachExchange(
- boost::bind(&exchangeAccumulatorCallback, boost::ref(collect), _1));
- for_each(collect.begin(), collect.end(),
- boost::bind(&BrokerReplicator::autoDeleteCheck, this, _1));
+
+ // Make copy of exchanges so we can work outside the registry lock.
+ ExchangeVector exs;
+ exchanges.eachExchange(boost::bind(&exchangeAccumulatorCallback, boost::ref(exs), _1));
+ for_each(exs.begin(), exs.end(),
+ boost::bind(&BrokerReplicator::disconnectedExchange, this, _1));
}
void BrokerReplicator::setMembership(const Variant::List& brokers) {
diff --git a/qpid/cpp/src/qpid/ha/BrokerReplicator.h b/qpid/cpp/src/qpid/ha/BrokerReplicator.h
index f93e25cb81..395f0706d9 100644
--- a/qpid/cpp/src/qpid/ha/BrokerReplicator.h
+++ b/qpid/cpp/src/qpid/ha/BrokerReplicator.h
@@ -71,6 +71,8 @@ class BrokerReplicator : public broker::Exchange,
public boost::enable_shared_from_this<BrokerReplicator>
{
public:
+ typedef boost::shared_ptr<QueueReplicator> QueueReplicatorPtr;
+
BrokerReplicator(HaBroker&, const boost::shared_ptr<broker::Link>&);
~BrokerReplicator();
@@ -84,8 +86,9 @@ class BrokerReplicator : public broker::Exchange,
bool isBound(boost::shared_ptr<broker::Queue>, const std::string* const, const framing::FieldTable* const);
void shutdown();
+ QueueReplicatorPtr findQueueReplicator(const std::string& qname);
+
private:
- typedef boost::shared_ptr<QueueReplicator> QueueReplicatorPtr;
typedef std::pair<boost::shared_ptr<broker::Queue>, bool> CreateQueueResult;
typedef std::pair<boost::shared_ptr<broker::Exchange>, bool> CreateExchangeResult;
@@ -99,6 +102,8 @@ class BrokerReplicator : public broker::Exchange,
class ConnectionObserver;
void connected(broker::Bridge&, broker::SessionHandler&);
+ void existingQueue(const boost::shared_ptr<broker::Queue>&);
+ void existingExchange(const boost::shared_ptr<broker::Exchange>&);
void doEventQueueDeclare(types::Variant::Map& values);
void doEventQueueDelete(types::Variant::Map& values);
@@ -114,7 +119,6 @@ class BrokerReplicator : public broker::Exchange,
void doResponseBind(types::Variant::Map& values);
void doResponseHaBroker(types::Variant::Map& values);
- QueueReplicatorPtr findQueueReplicator(const std::string& qname);
QueueReplicatorPtr startQueueReplicator(const boost::shared_ptr<broker::Queue>&);
QueueReplicatorPtr replicateQueue(
@@ -135,8 +139,7 @@ class BrokerReplicator : public broker::Exchange,
void deleteQueue(const std::string& name, bool purge=true);
void deleteExchange(const std::string& name);
- void autoDeleteCheck(boost::shared_ptr<broker::Exchange>);
-
+ void disconnectedExchange(boost::shared_ptr<broker::Exchange>);
void disconnected();
void setMembership(const types::Variant::List&); // Set membership from list.
diff --git a/qpid/cpp/src/qpid/ha/makeMessage.cpp b/qpid/cpp/src/qpid/ha/Event.cpp
index 5b063a23e7..8265a6edd3 100644
--- a/qpid/cpp/src/qpid/ha/makeMessage.cpp
+++ b/qpid/cpp/src/qpid/ha/Event.cpp
@@ -18,45 +18,69 @@
* under the License.
*
*/
-#include "makeMessage.h"
+#include "Event.h"
#include "qpid/broker/amqp_0_10/MessageTransfer.h"
#include "qpid/framing/AMQFrame.h"
+#include "qpid/framing/DeliveryProperties.h"
#include "qpid/framing/MessageTransferBody.h"
+#include "qpid/log/Statement.h"
namespace qpid {
namespace ha {
-broker::Message makeMessage(const framing::Buffer& buffer,
- const std::string& destination)
-{
- using namespace framing;
- using broker::amqp_0_10::MessageTransfer;
+using namespace std;
+using namespace framing;
+using namespace broker::amqp_0_10;
+
+namespace {
+const string QPID_HA(QPID_HA_PREFIX);
+}
+
+bool isEventKey(const std::string& key) {
+ const std::string& prefix = QPID_HA;
+ bool ret = key.size() > prefix.size() && key.compare(0, prefix.size(), prefix) == 0;
+ return ret;
+}
+
+const string DequeueEvent::KEY(QPID_HA+"de");
+const string IdEvent::KEY(QPID_HA+"id");
+const string TxEnqueueEvent::KEY(QPID_HA+"txenq");
+const string TxDequeueEvent::KEY(QPID_HA+"txdeq");
+const string TxPrepareEvent::KEY(QPID_HA+"txpre");
+const string TxCommitEvent::KEY(QPID_HA+"txcom");
+const string TxRollbackEvent::KEY(QPID_HA+"txrb");
+const string TxPrepareOkEvent::KEY(QPID_HA+"txok");
+const string TxPrepareFailEvent::KEY(QPID_HA+"txno");
+const string TxMembersEvent::KEY(QPID_HA+"txmem");
- boost::intrusive_ptr<MessageTransfer> transfer(
- new qpid::broker::amqp_0_10::MessageTransfer());
+broker::Message makeMessage(
+ const string& data, const string& destination, const string& routingKey)
+{
+ boost::intrusive_ptr<MessageTransfer> transfer(new MessageTransfer());
AMQFrame method((MessageTransferBody(ProtocolVersion(), destination, 0, 0)));
+ method.setBof(true);
+ method.setEof(false);
+ method.setBos(true);
+ method.setEos(true);
AMQFrame header((AMQHeaderBody()));
- AMQFrame content((AMQContentBody()));
- // AMQContentBody::decode is missing a const declaration, so cast it here.
- content.castBody<AMQContentBody>()->decode(
- const_cast<Buffer&>(buffer), buffer.getSize());
header.setBof(false);
header.setEof(false);
header.setBos(true);
header.setEos(true);
+ AMQFrame content((AMQContentBody()));
content.setBof(false);
content.setEof(true);
content.setBos(true);
content.setEos(true);
+ Buffer buffer(const_cast<char*>(&data[0]), data.size());
+ content.castBody<AMQContentBody>()->decode(
+ const_cast<Buffer&>(buffer), buffer.getSize());
transfer->getFrames().append(method);
transfer->getFrames().append(header);
transfer->getFrames().append(content);
+ transfer->getFrames().getHeaders()->
+ get<DeliveryProperties>(true)->setRoutingKey(routingKey);
return broker::Message(transfer, 0);
}
-broker::Message makeMessage(const std::string& content, const std::string& destination) {
- framing::Buffer buffer(const_cast<char*>(&content[0]), content.size());
- return makeMessage(buffer, destination);
-}
-
}} // namespace qpid::ha
diff --git a/qpid/cpp/src/qpid/ha/Event.h b/qpid/cpp/src/qpid/ha/Event.h
new file mode 100644
index 0000000000..f292499e7b
--- /dev/null
+++ b/qpid/cpp/src/qpid/ha/Event.h
@@ -0,0 +1,193 @@
+#ifndef QPID_HA_EVENT_H
+#define QPID_HA_EVENT_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "types.h"
+#include "qpid/broker/Message.h"
+#include "qpid/framing/BufferTypes.h"
+
+/**@file Defines event messages used to pass transaction information from
+ * primary observers to backup replicators.
+ */
+
+namespace qpid {
+namespace ha {
+
+broker::Message makeMessage(
+ const std::string& content,
+ const std::string& destination,
+ const std::string& routingKey);
+
+
+/** Test if a string is an event key */
+bool isEventKey(const std::string& key);
+
+/** Base class for encodable events */
+class Event {
+ public:
+ virtual ~Event() {}
+ virtual void encode(framing::Buffer& buffer) const = 0;
+ virtual void decode(framing::Buffer& buffer) = 0;
+ virtual size_t encodedSize() const = 0;
+ virtual std::string key() const = 0; // Routing key
+ virtual void print(std::ostream& o) const = 0;
+ broker::Message message(const std::string& destination=std::string()) const {
+ return makeMessage(framing::encodeStr(*this), destination, key()); }
+};
+
+
+inline std::ostream& operator<<(std::ostream& o, const Event& e) {
+ o << "<" << e.key() << ":";
+ e.print(o);
+ return o << ">";
+}
+
+/** Event base template */
+template <class Derived> class EventBase : public Event {
+ public:
+ std::string key() const { return Derived::KEY; }
+};
+
+//////////////// Specific event type
+
+//// QueueReplicator events
+
+struct DequeueEvent : public EventBase<DequeueEvent> {
+ static const std::string KEY;
+ ReplicationIdSet ids;
+
+ DequeueEvent(ReplicationIdSet ids_=ReplicationIdSet()) : ids(ids_) {}
+ void encode(framing::Buffer& b) const { b.put(ids); }
+ void decode(framing::Buffer& b) { b.get(ids); }
+ virtual size_t encodedSize() const { return ids.encodedSize(); }
+ void print(std::ostream& o) const { o << ids; }
+};
+
+struct IdEvent : public EventBase<IdEvent> {
+ static const std::string KEY;
+ ReplicationId id;
+
+ IdEvent(ReplicationId id_=0) : id(id_) {}
+ void encode(framing::Buffer& b) const { b.put(id); }
+ void decode(framing::Buffer& b) { b.get(id); }
+ virtual size_t encodedSize() const { return id.encodedSize(); }
+ void print(std::ostream& o) const { o << id; }
+};
+
+//// Transaction events
+
+struct TxEnqueueEvent : public EventBase<TxEnqueueEvent> {
+ static const std::string KEY;
+ framing::LongString queue;
+ ReplicationId id;
+
+ TxEnqueueEvent(std::string q=std::string(), ReplicationId i=ReplicationId())
+ : queue(q), id(i) {}
+ void encode(framing::Buffer& b) const { b.put(queue); b.put(id); }
+ void decode(framing::Buffer& b) { b.get(queue); b.get(id); }
+ virtual size_t encodedSize() const { return queue.encodedSize()+id.encodedSize(); }
+ void print(std::ostream& o) const { o << queue.value << " " << id; }
+};
+
+struct TxDequeueEvent : public EventBase<TxDequeueEvent> {
+ static const std::string KEY;
+ framing::LongString queue;
+ ReplicationId id;
+
+ TxDequeueEvent(std::string q=std::string(), ReplicationId r=0) :
+ queue(q), id(r) {}
+ void encode(framing::Buffer& b) const { b.put(queue);b.put(id); }
+ void decode(framing::Buffer& b) { b.get(queue);b.get(id); }
+ virtual size_t encodedSize() const { return queue.encodedSize()+id.encodedSize(); }
+ void print(std::ostream& o) const { o << queue.value << " " << id; }
+};
+
+struct TxPrepareEvent : public EventBase<TxPrepareEvent> {
+ static const std::string KEY;
+ void encode(framing::Buffer&) const {}
+ void decode(framing::Buffer&) {}
+ virtual size_t encodedSize() const { return 0; }
+ void print(std::ostream&) const {}
+};
+
+struct TxCommitEvent : public EventBase<TxCommitEvent> {
+ static const std::string KEY;
+ void encode(framing::Buffer&) const {}
+ void decode(framing::Buffer&) {}
+ virtual size_t encodedSize() const { return 0; }
+ void print(std::ostream&) const {}
+};
+
+struct TxRollbackEvent : public EventBase<TxRollbackEvent> {
+ static const std::string KEY;
+ void encode(framing::Buffer&) const {}
+ void decode(framing::Buffer&) {}
+ virtual size_t encodedSize() const { return 0; }
+ void print(std::ostream&) const {}
+};
+
+struct TxPrepareOkEvent : public EventBase<TxPrepareOkEvent> {
+ static const std::string KEY;
+ types::Uuid broker;
+ TxPrepareOkEvent(const types::Uuid& b=types::Uuid()) : broker(b) {}
+
+ void encode(framing::Buffer& b) const {
+ b.putRawData(broker.data(), broker.size());
+ }
+
+ void decode(framing::Buffer& b) {
+ std::string s;
+ b.getRawData(s, broker.size());
+ broker = types::Uuid(&s[0]);
+ }
+ virtual size_t encodedSize() const { return broker.size(); }
+ void print(std::ostream& o) const { o << broker; }
+};
+
+struct TxPrepareFailEvent : public EventBase<TxPrepareFailEvent> {
+ static const std::string KEY;
+ types::Uuid broker;
+ TxPrepareFailEvent(const types::Uuid& b=types::Uuid()) : broker(b) {}
+ void encode(framing::Buffer& b) const { b.putRawData(broker.data(), broker.size()); }
+ void decode(framing::Buffer& b) {
+ std::string s;
+ b.getRawData(s, broker.size());
+ broker = types::Uuid(&s[0]);
+ }
+ virtual size_t encodedSize() const { return broker.size(); }
+ void print(std::ostream& o) const { o << broker; }
+};
+
+struct TxMembersEvent : public EventBase<TxMembersEvent> {
+ static const std::string KEY;
+ UuidSet members;
+ TxMembersEvent(const UuidSet& s=UuidSet()) : members(s) {}
+ void encode(framing::Buffer& b) const { b.put(members); }
+ void decode(framing::Buffer& b) { b.get(members); }
+ size_t encodedSize() const { return members.encodedSize(); }
+ void print(std::ostream& o) const { o << members; }
+};
+
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_EVENT_H*/
diff --git a/qpid/cpp/src/qpid/ha/FailoverExchange.cpp b/qpid/cpp/src/qpid/ha/FailoverExchange.cpp
index 556c7458b6..9c7b986bf8 100644
--- a/qpid/cpp/src/qpid/ha/FailoverExchange.cpp
+++ b/qpid/cpp/src/qpid/ha/FailoverExchange.cpp
@@ -19,7 +19,7 @@
*
*/
#include "FailoverExchange.h"
-#include "makeMessage.h"
+#include "Event.h"
#include "qpid/broker/amqp_0_10/MessageTransfer.h"
#include "qpid/broker/Message.h"
#include "qpid/broker/DeliverableMessage.h"
@@ -117,7 +117,7 @@ void FailoverExchange::sendUpdate(const Queue::shared_ptr& queue, sys::Mutex::Sc
if (urls.empty()) return;
framing::Array array = vectorToUrlArray(urls);
const ProtocolVersion v;
- broker::Message message(makeMessage(Buffer(), typeName));
+ broker::Message message(makeMessage(std::string(), typeName, typeName));
MessageTransfer& transfer = MessageTransfer::get(message);
MessageProperties* props =
transfer.getFrames().getHeaders()->get<framing::MessageProperties>(true);
diff --git a/qpid/cpp/src/qpid/ha/HaBroker.cpp b/qpid/cpp/src/qpid/ha/HaBroker.cpp
index 7efeaad5b2..61561b3af6 100644
--- a/qpid/cpp/src/qpid/ha/HaBroker.cpp
+++ b/qpid/cpp/src/qpid/ha/HaBroker.cpp
@@ -64,6 +64,7 @@ using boost::dynamic_pointer_cast;
HaBroker::HaBroker(broker::Broker& b, const Settings& s)
: systemId(b.getSystem()->getSystemId().data()),
settings(s),
+ userId(s.username+"@"+b.getOptions().realm),
broker(b),
observer(new ConnectionObserver(*this, systemId)),
role(new StandAlone),
@@ -75,14 +76,14 @@ HaBroker::HaBroker(broker::Broker& b, const Settings& s)
// otherwise there's a window for a client to connect before we get to
// initialize()
if (settings.cluster) {
- QPID_LOG(debug, "Broker startup, rejecting client connections.");
+ QPID_LOG(debug, "Backup starting, rejecting client connections.");
shared_ptr<broker::ConnectionObserver> excluder(new BackupConnectionExcluder);
observer->setObserver(excluder, "Backup: ");
broker.getConnectionObservers().add(observer);
broker.getExchanges().registerExchange(failoverExchange);
}
// QueueSnapshots are needed for standalone replication as well as cluster.
- broker.getConfigurationObservers().add(queueSnapshots);
+ broker.getBrokerObservers().add(queueSnapshots);
}
namespace {
@@ -94,7 +95,7 @@ bool isNone(const std::string& x) { return x.empty() || x == NONE; }
void HaBroker::initialize() {
if (settings.cluster) {
membership.setStatus(JOINING);
- QPID_LOG(notice, "Initializing HA broker: " << membership.getInfo());
+ QPID_LOG(notice, "Initializing HA broker: " << membership.getSelf());
}
// Set up the management object.
@@ -202,7 +203,7 @@ std::vector<Url> HaBroker::getKnownBrokers() const {
}
void HaBroker::shutdown(const std::string& message) {
- QPID_LOG(critical, message);
+ QPID_LOG(critical, "Shutting down: " << message);
broker.shutdown();
throw Exception(message);
}
@@ -213,7 +214,7 @@ BrokerStatus HaBroker::getStatus() const {
void HaBroker::setAddress(const Address& a) {
QPID_LOG(info, role->getLogPrefix() << "Set self address to: " << a);
- membership.setAddress(a);
+ membership.setSelfAddress(a);
}
boost::shared_ptr<QueueReplicator> HaBroker::findQueueReplicator(const std::string& queueName) {
diff --git a/qpid/cpp/src/qpid/ha/HaBroker.h b/qpid/cpp/src/qpid/ha/HaBroker.h
index 8e5d30acfb..d10014846c 100644
--- a/qpid/cpp/src/qpid/ha/HaBroker.h
+++ b/qpid/cpp/src/qpid/ha/HaBroker.h
@@ -84,6 +84,7 @@ class HaBroker : public management::Manageable
broker::Broker& getBroker() { return broker; }
const Settings& getSettings() const { return settings; }
+ boost::shared_ptr<Role> getRole() const {return role; }
/** Shut down the broker because of a critical error. */
void shutdown(const std::string& message);
@@ -91,7 +92,7 @@ class HaBroker : public management::Manageable
BrokerStatus getStatus() const;
boost::shared_ptr<ConnectionObserver> getObserver() { return observer; }
- BrokerInfo getBrokerInfo() const { return membership.getInfo(); }
+ BrokerInfo getBrokerInfo() const { return membership.getSelf(); }
Membership& getMembership() { return membership; }
types::Uuid getSystemId() const { return systemId; }
@@ -101,6 +102,9 @@ class HaBroker : public management::Manageable
boost::shared_ptr<QueueReplicator> findQueueReplicator(const std::string& queueName);
+ /** Authenticated user ID for queue create/delete */
+ std::string getUserId() const { return userId; }
+
private:
void setPublicUrl(const Url&);
void setBrokerUrl(const Url&);
@@ -111,6 +115,7 @@ class HaBroker : public management::Manageable
// Immutable members
const types::Uuid systemId;
const Settings settings;
+ const std::string userId;
// Member variables protected by lock
mutable sys::Mutex lock;
diff --git a/qpid/cpp/src/qpid/ha/Membership.cpp b/qpid/cpp/src/qpid/ha/Membership.cpp
index 411bad3841..2f8ef1da97 100644
--- a/qpid/cpp/src/qpid/ha/Membership.cpp
+++ b/qpid/cpp/src/qpid/ha/Membership.cpp
@@ -107,6 +107,14 @@ BrokerInfo::Set Membership::otherBackups() const {
return result;
}
+BrokerInfo::Set Membership::getBrokers() const {
+ Mutex::ScopedLock l(lock);
+ BrokerInfo::Set result;
+ transform(brokers.begin(), brokers.end(), inserter(result, result.begin()),
+ boost::bind(&BrokerInfo::Map::value_type::second, _1));
+ return result;
+}
+
bool Membership::get(const types::Uuid& id, BrokerInfo& result) const {
Mutex::ScopedLock l(lock);
BrokerInfo::Map::const_iterator i = brokers.find(id);
@@ -136,10 +144,9 @@ bool checkTransition(BrokerStatus from, BrokerStatus to) {
}
} // namespace
-
void Membership::update(Mutex::ScopedLock& l) {
QPID_LOG(info, "Membership: " << brokers);
- // Update managment and send update event.
+// Update managment and send update event.
BrokerStatus newStatus = getStatus(l);
Variant::List brokerList = asList(l);
if (mgmtObject) {
@@ -198,14 +205,14 @@ BrokerStatus Membership::getStatus(sys::Mutex::ScopedLock&) const {
return i->second.getStatus();
}
-BrokerInfo Membership::getInfo() const {
+BrokerInfo Membership::getSelf() const {
Mutex::ScopedLock l(lock);
BrokerInfo::Map::const_iterator i = brokers.find(self);
assert(i != brokers.end());
return i->second;
}
-void Membership::setAddress(const Address& a) {
+void Membership::setSelfAddress(const Address& a) {
Mutex::ScopedLock l(lock);
brokers[self].setAddress(a);
update(l);
diff --git a/qpid/cpp/src/qpid/ha/Membership.h b/qpid/cpp/src/qpid/ha/Membership.h
index f442586a71..5b2b72e2fc 100644
--- a/qpid/cpp/src/qpid/ha/Membership.h
+++ b/qpid/cpp/src/qpid/ha/Membership.h
@@ -26,6 +26,7 @@
#include "types.h"
#include "qpid/log/Statement.h"
#include "qpid/sys/Mutex.h"
+#include "qpid/sys/Time.h"
#include "qpid/types/Variant.h"
#include <boost/function.hpp>
#include <set>
@@ -69,16 +70,19 @@ class Membership
/** Return IDs of all READY backups other than self */
BrokerInfo::Set otherBackups() const;
+ /** Return IDs of all brokers */
+ BrokerInfo::Set getBrokers() const;
+
void assign(const types::Variant::List&);
types::Variant::List asList() const;
bool get(const types::Uuid& id, BrokerInfo& result) const;
- types::Uuid getSelf() const { return self; }
- BrokerInfo getInfo() const;
+ BrokerInfo getSelf() const;
BrokerStatus getStatus() const;
void setStatus(BrokerStatus s);
- void setAddress(const Address&);
+
+ void setSelfAddress(const Address&);
private:
void update(sys::Mutex::ScopedLock&);
diff --git a/qpid/cpp/src/qpid/ha/Primary.cpp b/qpid/cpp/src/qpid/ha/Primary.cpp
index beabab4e32..e7fdc5035f 100644
--- a/qpid/cpp/src/qpid/ha/Primary.cpp
+++ b/qpid/cpp/src/qpid/ha/Primary.cpp
@@ -27,17 +27,19 @@
#include "RemoteBackup.h"
#include "ConnectionObserver.h"
#include "QueueReplicator.h"
+#include "PrimaryTxObserver.h"
#include "qpid/assert.h"
#include "qpid/broker/Broker.h"
-#include "qpid/broker/ConfigurationObserver.h"
+#include "qpid/broker/BrokerObserver.h"
#include "qpid/broker/Connection.h"
#include "qpid/broker/Queue.h"
#include "qpid/framing/FieldTable.h"
#include "qpid/framing/FieldValue.h"
-#include "qpid/framing/Uuid.h"
#include "qpid/log/Statement.h"
+#include "qpid/types/Uuid.h"
#include "qpid/sys/Timer.h"
#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
namespace qpid {
namespace ha {
@@ -59,15 +61,18 @@ class PrimaryConnectionObserver : public broker::ConnectionObserver
Primary& primary;
};
-class PrimaryConfigurationObserver : public broker::ConfigurationObserver
+class PrimaryBrokerObserver : public broker::BrokerObserver
{
public:
- PrimaryConfigurationObserver(Primary& p) : primary(p) {}
+ PrimaryBrokerObserver(Primary& p) : primary(p) {}
void queueCreate(const Primary::QueuePtr& q) { primary.queueCreate(q); }
void queueDestroy(const Primary::QueuePtr& q) { primary.queueDestroy(q); }
void exchangeCreate(const Primary::ExchangePtr& q) { primary.exchangeCreate(q); }
void exchangeDestroy(const Primary::ExchangePtr& q) { primary.exchangeDestroy(q); }
- private:
+ void startTx(const shared_ptr<broker::TxBuffer>& tx) { primary.startTx(tx); }
+ void startDtx(const shared_ptr<broker::DtxBuffer>& dtx) { primary.startDtx(dtx); }
+
+ private:
Primary& primary;
};
@@ -82,8 +87,6 @@ class ExpectedBackupTimerTask : public sys::TimerTask {
} // namespace
-Primary* Primary::instance = 0;
-
Primary::Primary(HaBroker& hb, const BrokerInfo::Set& expect) :
haBroker(hb), membership(hb.getMembership()),
logPrefix("Primary: "), active(false),
@@ -92,13 +95,11 @@ Primary::Primary(HaBroker& hb, const BrokerInfo::Set& expect) :
hb.getMembership().setStatus(RECOVERING);
broker::QueueRegistry& queues = hb.getBroker().getQueues();
queues.eachQueue(boost::bind(&Primary::initializeQueue, this, _1));
- assert(instance == 0);
- instance = this; // Let queue replicators find us.
if (expect.empty()) {
QPID_LOG(notice, logPrefix << "Promoted to primary. No expected backups.");
}
else {
- // NOTE: RemoteBackups must be created before we set the ConfigurationObserver
+ // NOTE: RemoteBackups must be created before we set the BrokerObserver
// or ConnectionObserver so that there is no client activity while
// the QueueGuards are created.
QPID_LOG(notice, logPrefix << "Promoted to primary. Expected backups: " << expect);
@@ -113,8 +114,8 @@ Primary::Primary(HaBroker& hb, const BrokerInfo::Set& expect) :
timerTask = new ExpectedBackupTimerTask(*this, deadline);
hb.getBroker().getTimer().add(timerTask);
}
- configurationObserver.reset(new PrimaryConfigurationObserver(*this));
- haBroker.getBroker().getConfigurationObservers().add(configurationObserver);
+ brokerObserver.reset(new PrimaryBrokerObserver(*this));
+ haBroker.getBroker().getBrokerObservers().add(brokerObserver);
checkReady(); // Outside lock
// Allow client connections
@@ -124,7 +125,7 @@ Primary::Primary(HaBroker& hb, const BrokerInfo::Set& expect) :
Primary::~Primary() {
if (timerTask) timerTask->cancel();
- haBroker.getBroker().getConfigurationObservers().remove(configurationObserver);
+ haBroker.getBroker().getBrokerObservers().remove(brokerObserver);
haBroker.getObserver()->reset();
}
@@ -212,14 +213,42 @@ void Primary::readyReplica(const ReplicatingSubscription& rs) {
if (backup) checkReady(backup);
}
+void Primary::addReplica(ReplicatingSubscription& rs) {
+ // Note this is called before the ReplicatingSubscription has been activated
+ // on the queue.
+ sys::Mutex::ScopedLock l(lock);
+ replicas[make_pair(rs.getBrokerInfo().getSystemId(), rs.getQueue())] = &rs;
+}
+
+void Primary::skip(
+ const types::Uuid& backup,
+ const boost::shared_ptr<broker::Queue>& queue,
+ const ReplicationIdSet& ids)
+{
+ sys::Mutex::ScopedLock l(lock);
+ ReplicaMap::const_iterator i = replicas.find(make_pair(backup, queue));
+ if (i != replicas.end()) i->second->addSkip(ids);
+}
+
+void Primary::removeReplica(const ReplicatingSubscription& rs) {
+ sys::Mutex::ScopedLock l(lock);
+ replicas.erase(make_pair(rs.getBrokerInfo().getSystemId(), rs.getQueue()));
+
+ TxMap::const_iterator i = txMap.find(rs.getQueue()->getName());
+ if (i != txMap.end()) {
+ boost::shared_ptr<PrimaryTxObserver> tx = i->second.lock();
+ if (tx) tx->cancel(rs);
+ }
+}
+
// NOTE: Called with queue registry lock held.
void Primary::queueCreate(const QueuePtr& q) {
// Set replication argument.
ReplicateLevel level = replicationTest.useLevel(*q);
- QPID_LOG(debug, logPrefix << "Created queue " << q->getName()
- << " replication: " << printable(level));
q->addArgument(QPID_REPLICATE, printable(level).str());
if (level) {
+ QPID_LOG(debug, logPrefix << "Created queue " << q->getName()
+ << " replication: " << printable(level));
initializeQueue(q);
// Give each queue a unique id. Used by backups to avoid confusion of
// same-named queues.
@@ -235,24 +264,26 @@ void Primary::queueCreate(const QueuePtr& q) {
// NOTE: Called with queue registry lock held.
void Primary::queueDestroy(const QueuePtr& q) {
- QPID_LOG(debug, logPrefix << "Destroyed queue " << q->getName());
- {
- Mutex::ScopedLock l(lock);
- for (BackupMap::iterator i = backups.begin(); i != backups.end(); ++i)
- i->second->queueDestroy(q);
+ if (replicationTest.useLevel(*q)) {
+ QPID_LOG(debug, logPrefix << "Destroyed queue " << q->getName());
+ {
+ Mutex::ScopedLock l(lock);
+ for (BackupMap::iterator i = backups.begin(); i != backups.end(); ++i)
+ i->second->queueDestroy(q);
+ }
+ checkReady(); // Outside lock
}
- checkReady(); // Outside lock
}
// NOTE: Called with exchange registry lock held.
void Primary::exchangeCreate(const ExchangePtr& ex) {
ReplicateLevel level = replicationTest.useLevel(*ex);
- QPID_LOG(debug, logPrefix << "Created exchange " << ex->getName()
- << " replication: " << printable(level));
FieldTable args = ex->getArgs();
args.setString(QPID_REPLICATE, printable(level).str()); // Set replication arg.
if (level) {
- // Give each exchange a unique id to avoid confusion of same-named exchanges.
+ QPID_LOG(debug, logPrefix << "Created exchange " << ex->getName()
+ << " replication: " << printable(level));
+ // Give each exchange a unique id to avoid confusion of same-named exchanges.
args.set(QPID_HA_UUID, FieldTable::ValuePtr(new UuidValue(&Uuid(true)[0])));
}
ex->setArgs(args);
@@ -260,8 +291,10 @@ void Primary::exchangeCreate(const ExchangePtr& ex) {
// NOTE: Called with exchange registry lock held.
void Primary::exchangeDestroy(const ExchangePtr& ex) {
- QPID_LOG(debug, logPrefix << "Destroyed exchange " << ex->getName());
- // Do nothing
+ if (replicationTest.useLevel(*ex)) {
+ QPID_LOG(debug, logPrefix << "Destroyed exchange " << ex->getName());
+ // Do nothing
+ }
}
// New backup connected
@@ -280,6 +313,7 @@ void Primary::backupDisconnect(shared_ptr<RemoteBackup> backup, Mutex::ScopedLoc
backup->cancel();
expectedBackups.erase(backup);
backups.erase(id);
+ membership.remove(id);
}
@@ -365,4 +399,19 @@ void Primary::setCatchupQueues(const RemoteBackupPtr& backup, bool createGuards)
backup->startCatchup();
}
+shared_ptr<PrimaryTxObserver> Primary::makeTxObserver() {
+ shared_ptr<PrimaryTxObserver> observer(new PrimaryTxObserver(haBroker));
+ observer->initialize();
+ txMap[observer->getTxQueue()->getName()] = observer;
+ return observer;
+}
+
+void Primary::startTx(const boost::shared_ptr<broker::TxBuffer>& tx) {
+ tx->setObserver(makeTxObserver());
+}
+
+void Primary::startDtx(const boost::shared_ptr<broker::DtxBuffer>& dtx) {
+ dtx->setObserver(makeTxObserver());
+}
+
}} // namespace qpid::ha
diff --git a/qpid/cpp/src/qpid/ha/Primary.h b/qpid/cpp/src/qpid/ha/Primary.h
index 3e1ec48ce6..d1350ab261 100644
--- a/qpid/cpp/src/qpid/ha/Primary.h
+++ b/qpid/cpp/src/qpid/ha/Primary.h
@@ -23,12 +23,14 @@
*/
#include "types.h"
+#include "hash.h"
#include "BrokerInfo.h"
#include "ReplicationTest.h"
#include "Role.h"
#include "qpid/sys/Mutex.h"
#include "qpid/sys/unordered_map.h"
#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <string>
@@ -38,7 +40,9 @@ namespace broker {
class Queue;
class Connection;
class ConnectionObserver;
-class ConfigurationObserver;
+class BrokerObserver;
+class TxBuffer;
+class DtxBuffer;
}
namespace sys {
@@ -51,6 +55,7 @@ class ReplicatingSubscription;
class RemoteBackup;
class QueueGuard;
class Membership;
+class PrimaryTxObserver;
/**
* State associated with a primary broker:
@@ -66,8 +71,6 @@ class Primary : public Role
typedef boost::shared_ptr<broker::Exchange> ExchangePtr;
typedef boost::shared_ptr<RemoteBackup> RemoteBackupPtr;
- static Primary* get() { return instance; }
-
Primary(HaBroker& hb, const BrokerInfo::Set& expectedBackups);
~Primary();
@@ -77,13 +80,21 @@ class Primary : public Role
void setBrokerUrl(const Url&) {}
void readyReplica(const ReplicatingSubscription&);
- void removeReplica(const std::string& q);
+ void addReplica(ReplicatingSubscription&);
+ void removeReplica(const ReplicatingSubscription&);
+
+ /** Skip replication of ids to queue on backup. */
+ void skip(const types::Uuid& backup,
+ const boost::shared_ptr<broker::Queue>& queue,
+ const ReplicationIdSet& ids);
- // Called via ConfigurationObserver
+ // Called via BrokerObserver
void queueCreate(const QueuePtr&);
void queueDestroy(const QueuePtr&);
void exchangeCreate(const ExchangePtr&);
void exchangeDestroy(const ExchangePtr&);
+ void startTx(const boost::shared_ptr<broker::TxBuffer>&);
+ void startDtx(const boost::shared_ptr<broker::DtxBuffer>&);
// Called via ConnectionObserver
void opened(broker::Connection& connection);
@@ -95,11 +106,18 @@ class Primary : public Role
void timeoutExpectedBackups();
private:
- typedef qpid::sys::unordered_map<
- types::Uuid, RemoteBackupPtr, types::Uuid::Hasher > BackupMap;
+ typedef sys::unordered_map<
+ types::Uuid, RemoteBackupPtr, Hasher<types::Uuid> > BackupMap;
typedef std::set<RemoteBackupPtr > BackupSet;
+ typedef std::pair<types::Uuid, boost::shared_ptr<broker::Queue> > UuidQueue;
+ typedef sys::unordered_map<UuidQueue, ReplicatingSubscription*,
+ Hasher<UuidQueue> > ReplicaMap;
+
+ // Map of PrimaryTxObservers by tx-queue name
+ typedef sys::unordered_map<std::string, boost::weak_ptr<PrimaryTxObserver> > TxMap;
+
RemoteBackupPtr backupConnect(const BrokerInfo&, broker::Connection&, sys::Mutex::ScopedLock&);
void backupDisconnect(RemoteBackupPtr, sys::Mutex::ScopedLock&);
@@ -107,8 +125,10 @@ class Primary : public Role
void checkReady();
void checkReady(RemoteBackupPtr);
void setCatchupQueues(const RemoteBackupPtr&, bool createGuards);
+ void deduplicate();
+ boost::shared_ptr<PrimaryTxObserver> makeTxObserver();
- sys::Mutex lock;
+ mutable sys::Mutex lock;
HaBroker& haBroker;
Membership& membership;
std::string logPrefix;
@@ -126,9 +146,10 @@ class Primary : public Role
*/
BackupMap backups;
boost::shared_ptr<broker::ConnectionObserver> connectionObserver;
- boost::shared_ptr<broker::ConfigurationObserver> configurationObserver;
+ boost::shared_ptr<broker::BrokerObserver> brokerObserver;
boost::intrusive_ptr<sys::TimerTask> timerTask;
- static Primary* instance;
+ ReplicaMap replicas;
+ TxMap txMap;
};
}} // namespace qpid::ha
diff --git a/qpid/cpp/src/qpid/ha/PrimaryTxObserver.cpp b/qpid/cpp/src/qpid/ha/PrimaryTxObserver.cpp
new file mode 100644
index 0000000000..41494694de
--- /dev/null
+++ b/qpid/cpp/src/qpid/ha/PrimaryTxObserver.cpp
@@ -0,0 +1,227 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "Event.h"
+#include "HaBroker.h"
+#include "Primary.h"
+#include "PrimaryTxObserver.h"
+#include "QueueGuard.h"
+#include "RemoteBackup.h"
+#include "ReplicatingSubscription.h"
+#include "QueueReplicator.h"
+
+#include "qpid/broker/Broker.h"
+#include "qpid/broker/Queue.h"
+#include <boost/lexical_cast.hpp>
+#include <algorithm>
+
+namespace qpid {
+namespace framing {
+class FieldTable;
+}
+namespace ha {
+
+using namespace std;
+using namespace qpid::broker;
+using namespace qpid::framing;
+
+// Exchange to receive prepare OK events.
+class PrimaryTxObserver::Exchange : public broker::Exchange {
+ public:
+ Exchange(const boost::shared_ptr<PrimaryTxObserver>& tx_) :
+ broker::Exchange(tx_->getExchangeName()),
+ tx(tx_)
+ {
+ dispatch[TxPrepareOkEvent::KEY] =
+ boost::bind(&PrimaryTxObserver::txPrepareOkEvent, tx, _1);
+ dispatch[TxPrepareFailEvent::KEY] =
+ boost::bind(&PrimaryTxObserver::txPrepareFailEvent, tx, _1);
+ }
+
+ void route(Deliverable& deliverable) {
+ const broker::Message& message(deliverable.getMessage());
+ DispatchMap::iterator i = dispatch.find(message.getRoutingKey());
+ if (i != dispatch.end()) i->second(message.getContent());
+ }
+
+ bool bind(boost::shared_ptr<Queue>, const string&, const FieldTable*) { return false; }
+ bool unbind(boost::shared_ptr<Queue>, const string&, const FieldTable*) { return false; }
+ bool isBound(boost::shared_ptr<Queue>, const string* const, const FieldTable* const) { return false; }
+ string getType() const { return TYPE_NAME; }
+
+ private:
+ static const string TYPE_NAME;
+ typedef boost::function<void(const std::string&)> DispatchFn;
+ typedef qpid::sys::unordered_map<std::string, DispatchFn> DispatchMap;
+
+ DispatchMap dispatch;
+ boost::shared_ptr<PrimaryTxObserver> tx;
+};
+
+const string PrimaryTxObserver::Exchange::TYPE_NAME(string(QPID_HA_PREFIX)+"primary-tx-observer");
+
+PrimaryTxObserver::PrimaryTxObserver(HaBroker& hb) :
+ haBroker(hb), broker(hb.getBroker()),
+ replicationTest(hb.getSettings().replicateDefault.get()),
+ id(true),
+ exchangeName(TRANSACTION_REPLICATOR_PREFIX+id.str()),
+ failed(false), ended(false), complete(false)
+{
+ logPrefix = "Primary transaction "+shortStr(id)+": ";
+
+ // The brokers known at this point are the ones that will be included
+ // in the transaction. Brokers that join later are not included.
+ //
+ BrokerInfo::Set backups(haBroker.getMembership().otherBackups());
+ std::transform(backups.begin(), backups.end(), inserter(members, members.begin()),
+ boost::bind(&BrokerInfo::getSystemId, _1));
+
+ QPID_LOG(debug, logPrefix << "Started TX " << id);
+ QPID_LOG(debug, logPrefix << "Members: " << members);
+ unprepared = unfinished = members;
+
+ pair<QueuePtr, bool> result =
+ broker.getQueues().declare(
+ exchangeName, QueueSettings(/*durable*/false, /*autodelete*/true));
+ assert(result.second);
+ txQueue = result.first;
+ txQueue->deliver(TxMembersEvent(members).message());
+}
+
+PrimaryTxObserver::~PrimaryTxObserver() {}
+
+
+void PrimaryTxObserver::initialize() {
+ boost::shared_ptr<Exchange> ex(new Exchange(shared_from_this()));
+ FieldTable args = ex->getArgs();
+ args.setString(QPID_REPLICATE, printable(NONE).str()); // Set replication arg.
+ broker.getExchanges().registerExchange(ex);
+}
+
+void PrimaryTxObserver::enqueue(const QueuePtr& q, const broker::Message& m)
+{
+ sys::Mutex::ScopedLock l(lock);
+ if (replicationTest.useLevel(*q) == ALL) { // Ignore unreplicated queues.
+ QPID_LOG(trace, logPrefix << "Enqueue: " << LogMessageId(*q, m));
+ enqueues[q] += m.getReplicationId();
+ txQueue->deliver(TxEnqueueEvent(q->getName(), m.getReplicationId()).message());
+ txQueue->deliver(m);
+ }
+}
+
+void PrimaryTxObserver::dequeue(
+ const QueuePtr& q, QueuePosition pos, ReplicationId id)
+{
+ sys::Mutex::ScopedLock l(lock);
+ if (replicationTest.useLevel(*q) == ALL) { // Ignore unreplicated queues.
+ QPID_LOG(trace, logPrefix << "Dequeue: " << LogMessageId(*q, pos, id));
+ txQueue->deliver(TxDequeueEvent(q->getName(), id).message());
+ }
+ else {
+ QPID_LOG(warning, logPrefix << "Dequeue skipped, queue not replicated: "
+ << LogMessageId(*q, pos, id));
+ }
+}
+
+void PrimaryTxObserver::deduplicate(sys::Mutex::ScopedLock&) {
+ boost::shared_ptr<Primary> primary(boost::dynamic_pointer_cast<Primary>(haBroker.getRole()));
+ assert(primary);
+ // Tell replicating subscriptions to skip IDs in the transaction.
+ for (UuidSet::iterator b = members.begin(); b != members.end(); ++b)
+ for (QueueIdsMap::iterator q = enqueues.begin(); q != enqueues.end(); ++q)
+ primary->skip(*b, q->first, q->second);
+}
+
+bool PrimaryTxObserver::prepare() {
+ sys::Mutex::ScopedLock l(lock);
+ QPID_LOG(debug, logPrefix << "Prepare");
+ deduplicate(l);
+ txQueue->deliver(TxPrepareEvent().message());
+ // TODO aconway 2013-09-04: Blocks the current thread till backups respond.
+ // Need a non-blocking approach (e.g. async completion or borrowing a thread)
+ while (!unprepared.empty() && !failed) lock.wait();
+ return !failed;
+}
+
+void PrimaryTxObserver::commit() {
+ sys::Mutex::ScopedLock l(lock);
+ QPID_LOG(debug, logPrefix << "Commit");
+ txQueue->deliver(TxCommitEvent().message());
+ complete = true;
+ end(l);
+}
+
+void PrimaryTxObserver::rollback() {
+ sys::Mutex::ScopedLock l(lock);
+ QPID_LOG(debug, logPrefix << "Rollback");
+ txQueue->deliver(TxRollbackEvent().message());
+ complete = true;
+ end(l);
+}
+
+void PrimaryTxObserver::end(sys::Mutex::ScopedLock&) {
+ // Don't destroy the tx-queue until the transaction is complete and there
+ // are no connected subscriptions.
+ if (!ended && complete && unfinished.empty()) {
+ ended = true;
+ try {
+ haBroker.getBroker().deleteQueue(txQueue->getName(), haBroker.getUserId(), string());
+ } catch (const std::exception& e) {
+ QPID_LOG(error, logPrefix << "Deleting transaction queue: " << e.what());
+ }
+ try {
+ broker.getExchanges().destroy(getExchangeName());
+ } catch (const std::exception& e) {
+ QPID_LOG(error, logPrefix << "Deleting transaction exchange: " << e.what());
+ }
+ }
+}
+
+void PrimaryTxObserver::txPrepareOkEvent(const string& data) {
+ sys::Mutex::ScopedLock l(lock);
+ types::Uuid backup = decodeStr<TxPrepareOkEvent>(data).broker;
+ QPID_LOG(debug, logPrefix << "Backup prepared ok: " << backup);
+ unprepared.erase(backup);
+ lock.notify();
+}
+
+void PrimaryTxObserver::txPrepareFailEvent(const string& data) {
+ sys::Mutex::ScopedLock l(lock);
+ types::Uuid backup = decodeStr<TxPrepareFailEvent>(data).broker;
+ QPID_LOG(error, logPrefix << "Backup prepare failed: " << backup);
+ unprepared.erase(backup);
+ failed = true;
+ lock.notify();
+}
+
+void PrimaryTxObserver::cancel(const ReplicatingSubscription& rs) {
+ sys::Mutex::ScopedLock l(lock);
+ types::Uuid backup = rs.getBrokerInfo().getSystemId();
+ if (unprepared.find(backup) != unprepared.end()) {
+ complete = failed = true; // Canceled before prepared.
+ unprepared.erase(backup); // Consider it prepared-fail
+ }
+ unfinished.erase(backup);
+ lock.notify();
+ end(l);
+}
+
+}} // namespace qpid::ha
diff --git a/qpid/cpp/src/qpid/ha/PrimaryTxObserver.h b/qpid/cpp/src/qpid/ha/PrimaryTxObserver.h
new file mode 100644
index 0000000000..fb9db25e85
--- /dev/null
+++ b/qpid/cpp/src/qpid/ha/PrimaryTxObserver.h
@@ -0,0 +1,115 @@
+#ifndef QPID_HA_PRIMARYTXOBSERVER_H
+#define QPID_HA_PRIMARYTXOBSERVER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "types.h"
+#include "ReplicationTest.h"
+#include "qpid/broker/TransactionObserver.h"
+#include "qpid/log/Statement.h"
+#include "qpid/types/Uuid.h"
+#include "qpid/sys/unordered_map.h"
+#include "qpid/sys/Monitor.h"
+#include <boost/enable_shared_from_this.hpp>
+
+namespace qpid {
+
+namespace broker {
+class Broker;
+class Message;
+class Consumer;
+}
+
+namespace ha {
+class HaBroker;
+class ReplicatingSubscription;
+
+/**
+ * Observe events in the lifecycle of a transaction.
+ *
+ * The observer is called by TxBuffer for each transactional event.
+ * It puts the events on a special tx-queue.
+ * A TxReplicator on the backup replicates the tx-queue and creates
+ * a TxBuffer on the backup equivalent to the one on the primary.
+ *
+ * Also observes the tx-queue for prepare-complete messages and
+ * subscription cancellations.
+ *
+ * THREAD SAFE: called in user connection thread for TX events,
+ * and in backup connection threads for prepare-completed events
+ * and unsubscriptions.
+ */
+class PrimaryTxObserver : public broker::TransactionObserver,
+ public boost::enable_shared_from_this<PrimaryTxObserver>
+{
+ public:
+ PrimaryTxObserver(HaBroker&);
+ ~PrimaryTxObserver();
+
+ /** Call immediately after constructor, uses shared_from_this. */
+ void initialize();
+
+ void enqueue(const QueuePtr&, const broker::Message&);
+ void dequeue(const QueuePtr& queue, QueuePosition, ReplicationId);
+ bool prepare();
+ void commit();
+ void rollback();
+
+ types::Uuid getId() const { return id; }
+ QueuePtr getTxQueue() const { return txQueue; }
+ std::string getExchangeName() const { return exchangeName; }
+
+ // Notify that a backup subscription has been cancelled.
+ void cancel(const ReplicatingSubscription&);
+
+ private:
+ class Exchange;
+ typedef qpid::sys::unordered_map<
+ QueuePtr, ReplicationIdSet, Hasher<QueuePtr> > QueueIdsMap;
+
+ void membership(const BrokerInfo::Map&);
+ void deduplicate(sys::Mutex::ScopedLock&);
+ void end(sys::Mutex::ScopedLock&);
+ void txPrepareOkEvent(const std::string& data);
+ void txPrepareFailEvent(const std::string& data);
+
+
+ sys::Monitor lock;
+ std::string logPrefix;
+ HaBroker& haBroker;
+ broker::Broker& broker;
+ ReplicationTest replicationTest;
+
+ types::Uuid id;
+ std::string exchangeName;
+ QueuePtr txQueue;
+ QueueIdsMap enqueues;
+ bool failed, ended, complete;
+
+ UuidSet members; // All members of transaction.
+ UuidSet unprepared; // Members that have not yet responded to prepare.
+ UuidSet unfinished; // Members that have not yet disconnected.
+};
+
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_PRIMARYTXOBSERVER_H*/
diff --git a/qpid/cpp/src/qpid/ha/QueueGuard.h b/qpid/cpp/src/qpid/ha/QueueGuard.h
index e41a92c74f..33967970eb 100644
--- a/qpid/cpp/src/qpid/ha/QueueGuard.h
+++ b/qpid/cpp/src/qpid/ha/QueueGuard.h
@@ -89,7 +89,7 @@ class QueueGuard {
class QueueObserver;
typedef qpid::sys::unordered_map<ReplicationId,
boost::intrusive_ptr<broker::AsyncCompletion>,
- TrivialHasher<ReplicationId> > Delayed;
+ Hasher<ReplicationId> > Delayed;
bool complete(ReplicationId, sys::Mutex::ScopedLock &);
void complete(Delayed::iterator, sys::Mutex::ScopedLock &);
diff --git a/qpid/cpp/src/qpid/ha/QueueReplicator.cpp b/qpid/cpp/src/qpid/ha/QueueReplicator.cpp
index d99602fdda..22af7284a8 100644
--- a/qpid/cpp/src/qpid/ha/QueueReplicator.cpp
+++ b/qpid/cpp/src/qpid/ha/QueueReplicator.cpp
@@ -19,12 +19,13 @@
*
*/
-#include "makeMessage.h"
+#include "Event.h"
#include "HaBroker.h"
#include "QueueReplicator.h"
#include "QueueSnapshots.h"
#include "ReplicatingSubscription.h"
#include "Settings.h"
+#include "types.h"
#include "qpid/broker/Bridge.h"
#include "qpid/broker/Broker.h"
#include "qpid/broker/Link.h"
@@ -38,36 +39,31 @@
#include "qpid/Msg.h"
#include "qpid/assert.h"
#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
-namespace {
-const std::string QPID_REPLICATOR_("qpid.replicator-");
-const std::string TYPE_NAME("qpid.queue-replicator");
-const std::string QPID_HA("qpid.ha-");
-}
namespace qpid {
namespace ha {
using namespace broker;
using namespace framing;
using namespace std;
+using std::exception;
using sys::Mutex;
-const std::string QueueReplicator::DEQUEUE_EVENT_KEY(QPID_HA+"dequeue");
-const std::string QueueReplicator::ID_EVENT_KEY(QPID_HA+"id");
const std::string QueueReplicator::QPID_SYNC_FREQUENCY("qpid.sync_frequency");
-std::string QueueReplicator::replicatorName(const std::string& queueName) {
- return QPID_REPLICATOR_ + queueName;
+namespace {
+const string QPID_HA(QPID_HA_PREFIX);
+const std::string TYPE_NAME(QPID_HA+"queue-replicator");
}
-bool QueueReplicator::isReplicatorName(const std::string& name) {
- return name.compare(0, QPID_REPLICATOR_.size(), QPID_REPLICATOR_) == 0;
+
+std::string QueueReplicator::replicatorName(const std::string& queueName) {
+ return QUEUE_REPLICATOR_PREFIX + queueName;
}
-bool QueueReplicator::isEventKey(const std::string key) {
- const std::string& prefix = QPID_HA;
- bool ret = key.size() > prefix.size() && key.compare(0, prefix.size(), prefix) == 0;
- return ret;
+bool QueueReplicator::isReplicatorName(const std::string& name) {
+ return startsWith(name, QUEUE_REPLICATOR_PREFIX);
}
class QueueReplicator::ErrorListener : public SessionHandler::ErrorListener {
@@ -109,12 +105,15 @@ QueueReplicator::QueueReplicator(HaBroker& hb,
boost::shared_ptr<Link> l)
: Exchange(replicatorName(q->getName()), 0, q->getBroker()),
haBroker(hb),
+ brokerInfo(hb.getBrokerInfo()),
+ link(l),
+ queue(q),
+ sessionHandler(0),
logPrefix("Backup of "+q->getName()+": "),
- queue(q), link(l), brokerInfo(hb.getBrokerInfo()), subscribed(false),
- settings(hb.getSettings()), destroyed(false),
+ subscribed(false),
+ settings(hb.getSettings()),
nextId(0), maxId(0)
{
- QPID_LOG(debug, logPrefix << "Created");
args.setString(QPID_REPLICATE, printable(NONE).str());
Uuid uuid(true);
bridgeName = replicatorName(q->getName()) + std::string(".") + uuid.str();
@@ -122,12 +121,18 @@ QueueReplicator::QueueReplicator(HaBroker& hb,
args.setString(QPID_REPLICATE, printable(NONE).str());
setArgs(args);
if (q->isAutoDelete()) q->markInUse();
+
+ dispatch[DequeueEvent::KEY] =
+ boost::bind(&QueueReplicator::dequeueEvent, this, _1, _2);
+ dispatch[IdEvent::KEY] =
+ boost::bind(&QueueReplicator::idEvent, this, _1, _2);
}
// This must be called immediately after the constructor.
// It has to be separate so we can call shared_from_this().
void QueueReplicator::activate() {
Mutex::ScopedLock l(lock);
+ QPID_LOG(debug, logPrefix << "Created");
if (!queue) return; // Already destroyed
// Enable callback to route()
@@ -163,6 +168,11 @@ void QueueReplicator::activate() {
boost::shared_ptr<QueueObserver>(new QueueObserver(shared_from_this())));
}
+void QueueReplicator::disconnect() {
+ Mutex::ScopedLock l(lock);
+ sessionHandler = 0;
+}
+
QueueReplicator::~QueueReplicator() {}
// Called from Queue::destroyed()
@@ -170,25 +180,24 @@ void QueueReplicator::destroy() {
boost::shared_ptr<Bridge> bridge2; // To call outside of lock
{
Mutex::ScopedLock l(lock);
- if (destroyed) return;
- destroyed = true;
+ if (!queue) return; // Already destroyed
QPID_LOG(debug, logPrefix << "Destroyed");
+ bridge2 = bridge; // call close outside the lock.
// Need to drop shared pointers to avoid pointer cycles keeping this in memory.
queue.reset();
- link.reset();
bridge.reset();
getBroker()->getExchanges().destroy(getName());
- bridge2 = bridge;
}
if (bridge2) bridge2->close(); // Outside of lock, avoid deadlock.
}
// Called in a broker connection thread when the bridge is created.
// Note: called with the Link lock held.
-void QueueReplicator::initializeBridge(Bridge& bridge, SessionHandler& sessionHandler) {
+void QueueReplicator::initializeBridge(Bridge& bridge, SessionHandler& sessionHandler_) {
Mutex::ScopedLock l(lock);
- if (destroyed) return; // Already destroyed
- AMQP_ServerProxy peer(sessionHandler.out);
+ if (!queue) return; // Already destroyed
+ sessionHandler = &sessionHandler_;
+ AMQP_ServerProxy peer(sessionHandler->out);
const qmf::org::apache::qpid::broker::ArgsLinkBridge& args(bridge.getArgs());
FieldTable arguments;
arguments.setInt(ReplicatingSubscription::QPID_REPLICATING_SUBSCRIPTION, 1);
@@ -224,44 +233,57 @@ template <class T> T decodeContent(Message& m) {
}
}
-void QueueReplicator::dequeue(const ReplicationIdSet& dequeues, Mutex::ScopedLock&) {
- QPID_LOG(trace, logPrefix << "Dequeue " << dequeues);
+void QueueReplicator::dequeueEvent(const string& data, Mutex::ScopedLock&) {
+ DequeueEvent e;
+ decodeStr(data, e);
+ QPID_LOG(trace, logPrefix << "Dequeue " << e.ids);
//TODO: should be able to optimise the following
- for (ReplicationIdSet::iterator i = dequeues.begin(); i != dequeues.end(); ++i) {
+ for (ReplicationIdSet::iterator i = e.ids.begin(); i != e.ids.end(); ++i) {
PositionMap::iterator j = positions.find(*i);
if (j != positions.end()) queue->dequeueMessageAt(j->second);
}
}
// Called in connection thread of the queues bridge to primary.
-void QueueReplicator::route(Deliverable& msg)
+void QueueReplicator::route(Deliverable& deliverable)
{
try {
Mutex::ScopedLock l(lock);
- if (destroyed) return;
- const std::string& key = msg.getMessage().getRoutingKey();
- if (!isEventKey(key)) { // Replicated message
+ if (!queue) return; // Already destroyed
+ broker::Message& message(deliverable.getMessage());
+ string key(message.getRoutingKey());
+ if (!isEventKey(message.getRoutingKey())) {
ReplicationId id = nextId++;
maxId = std::max(maxId, id);
- msg.getMessage().setReplicationId(id);
- msg.deliverTo(queue);
+ message.setReplicationId(id);
+ deliver(message);
QueuePosition position = queue->getPosition();
positions[id] = position;
QPID_LOG(trace, logPrefix << "Enqueued " << LogMessageId(*queue,position,id));
}
- else if (key == DEQUEUE_EVENT_KEY) {
- dequeue(decodeContent<ReplicationIdSet>(msg.getMessage()), l);
- }
- else if (key == ID_EVENT_KEY) {
- nextId = decodeContent<ReplicationId>(msg.getMessage());
+ else {
+ DispatchMap::iterator i = dispatch.find(key);
+ if (i == dispatch.end()) {
+ QPID_LOG(info, logPrefix << "Ignoring unknown event: " << key);
+ }
+ else {
+ (i->second)(message.getContent(), l);
+ }
}
- // Ignore unknown event keys, may be introduced in later versions.
}
catch (const std::exception& e) {
haBroker.shutdown(QPID_MSG(logPrefix << "Replication failed: " << e.what()));
}
}
+void QueueReplicator::deliver(const broker::Message& m) {
+ queue->deliver(m);
+}
+
+void QueueReplicator::idEvent(const string& data, Mutex::ScopedLock&) {
+ nextId = decodeStr<IdEvent>(data).id;
+}
+
ReplicationId QueueReplicator::getMaxId() {
Mutex::ScopedLock l(lock);
return maxId;
@@ -273,4 +295,5 @@ bool QueueReplicator::unbind(boost::shared_ptr<Queue>, const std::string&, const
bool QueueReplicator::isBound(boost::shared_ptr<Queue>, const std::string* const, const FieldTable* const) { return false; }
std::string QueueReplicator::getType() const { return TYPE_NAME; }
+
}} // namespace qpid::broker
diff --git a/qpid/cpp/src/qpid/ha/QueueReplicator.h b/qpid/cpp/src/qpid/ha/QueueReplicator.h
index 811ddba256..01abc88843 100644
--- a/qpid/cpp/src/qpid/ha/QueueReplicator.h
+++ b/qpid/cpp/src/qpid/ha/QueueReplicator.h
@@ -26,6 +26,7 @@
#include "hash.h"
#include "qpid/broker/Exchange.h"
#include <boost/enable_shared_from_this.hpp>
+#include <boost/function.hpp>
#include <iosfwd>
namespace qpid {
@@ -56,30 +57,24 @@ class QueueReplicator : public broker::Exchange,
public boost::enable_shared_from_this<QueueReplicator>
{
public:
- static const std::string DEQUEUE_EVENT_KEY;
- static const std::string ID_EVENT_KEY;
static const std::string QPID_SYNC_FREQUENCY;
+ static const std::string REPLICATOR_PREFIX;
static std::string replicatorName(const std::string& queueName);
static bool isReplicatorName(const std::string&);
- /** Test if a string is an event key */
- static bool isEventKey(const std::string key);
-
QueueReplicator(HaBroker&,
boost::shared_ptr<broker::Queue> q,
boost::shared_ptr<broker::Link> l);
~QueueReplicator();
- void activate(); // Must be called immediately after constructor.
+ void activate(); // Must be called immediately after constructor.
+ void disconnect(); // Called when we are disconnected from the primary.
std::string getType() const;
- bool bind(boost::shared_ptr<broker::Queue
- >, const std::string&, const framing::FieldTable*);
- bool unbind(boost::shared_ptr<broker::Queue>, const std::string&, const framing::FieldTable*);
+
void route(broker::Deliverable&);
- bool isBound(boost::shared_ptr<broker::Queue>, const std::string* const, const framing::FieldTable* const);
// Set if the queue has ever been subscribed to, used for auto-delete cleanup.
void setSubscribed() { subscribed = true; }
@@ -89,27 +84,44 @@ class QueueReplicator : public broker::Exchange,
ReplicationId getMaxId();
- private:
- typedef qpid::sys::unordered_map<ReplicationId, QueuePosition, TrivialHasher<int32_t> > PositionMap;
+ // No-op unused Exchange virtual functions.
+ bool bind(boost::shared_ptr<broker::Queue>, const std::string&, const framing::FieldTable*);
+ bool unbind(boost::shared_ptr<broker::Queue>, const std::string&, const framing::FieldTable*);
+ bool isBound(boost::shared_ptr<broker::Queue>, const std::string* const, const framing::FieldTable* const);
+
+ protected:
+ typedef boost::function<void(const std::string&, sys::Mutex::ScopedLock&)> DispatchFn;
+ typedef qpid::sys::unordered_map<std::string, DispatchFn> DispatchMap;
+
+ virtual void deliver(const broker::Message&);
+ virtual void destroy(); // Called when the queue is destroyed.
+ sys::Mutex lock;
+ HaBroker& haBroker;
+ const BrokerInfo brokerInfo;
+ DispatchMap dispatch;
+ boost::shared_ptr<broker::Link> link;
+ boost::shared_ptr<broker::Bridge> bridge;
+ boost::shared_ptr<broker::Queue> queue;
+ broker::SessionHandler* sessionHandler;
+
+ private:
+ typedef qpid::sys::unordered_map<
+ ReplicationId, QueuePosition, Hasher<ReplicationId> > PositionMap;
class ErrorListener;
class QueueObserver;
void initializeBridge(broker::Bridge& bridge, broker::SessionHandler& sessionHandler);
- void destroy(); // Called when the queue is destroyed.
- void dequeue(const ReplicationIdSet&, sys::Mutex::ScopedLock&);
- HaBroker& haBroker;
+ // Dispatch functions
+ void dequeueEvent(const std::string& data, sys::Mutex::ScopedLock&);
+ void idEvent(const std::string& data, sys::Mutex::ScopedLock&);
+
std::string logPrefix;
std::string bridgeName;
- sys::Mutex lock;
- boost::shared_ptr<broker::Queue> queue;
- boost::shared_ptr<broker::Link> link;
- boost::shared_ptr<broker::Bridge> bridge;
- BrokerInfo brokerInfo;
+
bool subscribed;
const Settings& settings;
- bool destroyed;
PositionMap positions;
ReplicationIdSet idSet; // Set of replicationIds on the queue.
ReplicationId nextId; // ID for next message to arrive.
diff --git a/qpid/cpp/src/qpid/ha/QueueSnapshots.h b/qpid/cpp/src/qpid/ha/QueueSnapshots.h
index 258c406954..d067b983d1 100644
--- a/qpid/cpp/src/qpid/ha/QueueSnapshots.h
+++ b/qpid/cpp/src/qpid/ha/QueueSnapshots.h
@@ -27,7 +27,7 @@
#include "hash.h"
#include "qpid/assert.h"
-#include "qpid/broker/ConfigurationObserver.h"
+#include "qpid/broker/BrokerObserver.h"
#include "qpid/broker/Queue.h"
#include "qpid/sys/Mutex.h"
@@ -37,10 +37,10 @@ namespace qpid {
namespace ha {
/**
- * ConfigurationObserver that maintains a map of the QueueSnapshot for each queue.
+ * BrokerObserver that maintains a map of the QueueSnapshot for each queue.
* THREAD SAFE.
*/
-class QueueSnapshots : public broker::ConfigurationObserver
+class QueueSnapshots : public broker::BrokerObserver
{
public:
boost::shared_ptr<QueueSnapshot> get(const boost::shared_ptr<broker::Queue>& q) const {
@@ -49,7 +49,7 @@ class QueueSnapshots : public broker::ConfigurationObserver
return i != snapshots.end() ? i->second : boost::shared_ptr<QueueSnapshot>();
}
- // ConfigurationObserver overrides.
+ // BrokerObserver overrides.
void queueCreate(const boost::shared_ptr<broker::Queue>& q) {
sys::Mutex::ScopedLock l(lock);
boost::shared_ptr<QueueSnapshot> observer(new QueueSnapshot);
@@ -69,7 +69,7 @@ class QueueSnapshots : public broker::ConfigurationObserver
private:
typedef qpid::sys::unordered_map<boost::shared_ptr<broker::Queue>,
boost::shared_ptr<QueueSnapshot>,
- SharedPtrHasher<broker::Queue>
+ Hasher<boost::shared_ptr<broker::Queue> >
> SnapshotMap;
SnapshotMap snapshots;
mutable sys::Mutex lock;
diff --git a/qpid/cpp/src/qpid/ha/RemoteBackup.cpp b/qpid/cpp/src/qpid/ha/RemoteBackup.cpp
index c37d44fa08..0993c6ea39 100644
--- a/qpid/cpp/src/qpid/ha/RemoteBackup.cpp
+++ b/qpid/cpp/src/qpid/ha/RemoteBackup.cpp
@@ -20,6 +20,7 @@
*/
#include "RemoteBackup.h"
#include "QueueGuard.h"
+#include "TxReplicator.h"
#include "qpid/broker/Broker.h"
#include "qpid/broker/Connection.h"
#include "qpid/broker/Queue.h"
@@ -108,13 +109,13 @@ void RemoteBackup::ready(const QueuePtr& q) {
QPID_LOG(debug, logPrefix << "Caught up on queue: " << q->getName() );
}
-// Called via ConfigurationObserver::queueCreate and from catchupQueue
+// Called via BrokerObserver::queueCreate and from catchupQueue
void RemoteBackup::queueCreate(const QueuePtr& q) {
if (replicationTest.getLevel(*q) == ALL)
guards[q].reset(new QueueGuard(*q, brokerInfo));
}
-// Called via ConfigurationObserver
+// Called via BrokerObserver
void RemoteBackup::queueDestroy(const QueuePtr& q) {
catchupQueues.erase(q);
GuardMap::iterator i = guards.find(q);
diff --git a/qpid/cpp/src/qpid/ha/RemoteBackup.h b/qpid/cpp/src/qpid/ha/RemoteBackup.h
index e2c5032820..b9e2e1a496 100644
--- a/qpid/cpp/src/qpid/ha/RemoteBackup.h
+++ b/qpid/cpp/src/qpid/ha/RemoteBackup.h
@@ -71,10 +71,10 @@ class RemoteBackup
*/
void ready(const QueuePtr& queue);
- /** Called via ConfigurationObserver */
+ /** Called via BrokerObserver */
void queueCreate(const QueuePtr&);
- /** Called via ConfigurationObserver. Note: may set isReady() */
+ /** Called via BrokerObserver. Note: may set isReady() */
void queueDestroy(const QueuePtr&);
/**@return true when all catch-up queues for this backup are ready. */
@@ -96,8 +96,10 @@ class RemoteBackup
void startCatchup() { started = true; }
private:
- typedef qpid::sys::unordered_map<QueuePtr, GuardPtr,
- SharedPtrHasher<broker::Queue> > GuardMap;
+ typedef qpid::sys::unordered_map<
+ QueuePtr, GuardPtr, Hasher<boost::shared_ptr<broker::Queue> >
+ > GuardMap;
+
typedef std::set<QueuePtr> QueueSet;
std::string logPrefix;
diff --git a/qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp b/qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp
index 1ede47ed60..cdfe9dd888 100644
--- a/qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp
+++ b/qpid/cpp/src/qpid/ha/ReplicatingSubscription.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "makeMessage.h"
+#include "Event.h"
#include "IdSetter.h"
#include "QueueGuard.h"
#include "QueueReplicator.h"
@@ -111,7 +111,8 @@ ReplicatingSubscription::ReplicatingSubscription(
) : ConsumerImpl(parent, name, queue, ack, REPLICATOR, exclusive, tag,
resumeId, resumeTtl, arguments),
position(0), ready(false), cancelled(false),
- haBroker(hb)
+ haBroker(hb),
+ primary(boost::dynamic_pointer_cast<Primary>(haBroker.getRole()))
{
try {
FieldTable ft;
@@ -137,7 +138,7 @@ ReplicatingSubscription::ReplicatingSubscription(
}
// If there's already a guard (we are in failover) use it, else create one.
- if (Primary::get()) guard = Primary::get()->getGuard(queue, info);
+ if (primary) guard = primary->getGuard(queue, info);
if (!guard) guard.reset(new QueueGuard(*queue, info));
// NOTE: Once the observer is attached we can have concurrent
@@ -148,20 +149,19 @@ ReplicatingSubscription::ReplicatingSubscription(
// between the snapshot and attaching the observer.
observer.reset(new QueueObserver(*this));
queue->addObserver(observer);
- ReplicationIdSet primary = haBroker.getQueueSnapshots()->get(queue)->snapshot();
+ ReplicationIdSet primaryIds = haBroker.getQueueSnapshots()->get(queue)->snapshot();
std::string backupStr = arguments.getAsString(ReplicatingSubscription::QPID_ID_SET);
- ReplicationIdSet backup;
- if (!backupStr.empty()) backup = decodeStr<ReplicationIdSet>(backupStr);
+ ReplicationIdSet backupIds;
+ if (!backupStr.empty()) backupIds = decodeStr<ReplicationIdSet>(backupStr);
// Initial dequeues are messages on backup but not on primary.
- ReplicationIdSet initDequeues = backup - primary;
+ ReplicationIdSet initDequeues = backupIds - primaryIds;
QueuePosition front,back;
queue->getRange(front, back, broker::REPLICATOR); // Outside lock, getRange locks queue
{
sys::Mutex::ScopedLock l(lock); // Concurrent calls to dequeued()
dequeues += initDequeues; // Messages on backup that are not on primary.
- skip = backup - initDequeues; // Messages already on the backup.
-
+ skip = backupIds - initDequeues; // Messages already on the backup.
// Queue front is moving but we know this subscriptions will start at a
// position >= front so if front is safe then position must be.
position = front;
@@ -189,6 +189,7 @@ ReplicatingSubscription::~ReplicatingSubscription() {}
//
void ReplicatingSubscription::initialize() {
try {
+ if (primary) primary->addReplica(*this);
Mutex::ScopedLock l(lock); // Note dequeued() can be called concurrently.
// Send initial dequeues to the backup.
// There must be a shared_ptr(this) when sending.
@@ -216,9 +217,8 @@ bool ReplicatingSubscription::deliver(
try {
bool result = false;
if (skip.contains(id)) {
+ QPID_LOG(trace, logPrefix << "Skip " << LogMessageId(*getQueue(), m));
skip -= id;
- QPID_LOG(trace, logPrefix << "On backup, skip " <<
- LogMessageId(*getQueue(), m));
guard->complete(id); // This will never be acknowledged.
notify();
result = true;
@@ -238,16 +238,13 @@ bool ReplicatingSubscription::deliver(
}
}
-/**
- *@param position: must be <= last position seen by subscription.
- */
void ReplicatingSubscription::checkReady(sys::Mutex::ScopedLock& l) {
if (!ready && isGuarded(l) && unready.empty()) {
ready = true;
sys::Mutex::ScopedUnlock u(lock);
// Notify Primary that a subscription is ready.
QPID_LOG(debug, logPrefix << "Caught up");
- if (Primary::get()) Primary::get()->readyReplica(*this);
+ if (primary) primary->readyReplica(*this);
}
}
@@ -260,6 +257,7 @@ void ReplicatingSubscription::cancel()
cancelled = true;
}
QPID_LOG(debug, logPrefix << "Cancelled");
+ if (primary) primary->removeReplica(*this);
getQueue()->removeObserver(observer);
guard->cancel();
ConsumerImpl::cancel();
@@ -285,9 +283,7 @@ void ReplicatingSubscription::sendDequeueEvent(Mutex::ScopedLock& l)
{
if (dequeues.empty()) return;
QPID_LOG(trace, logPrefix << "Sending dequeues " << dequeues);
- string buffer = encodeStr(dequeues);
- dequeues.clear();
- sendEvent(QueueReplicator::DEQUEUE_EVENT_KEY, buffer, l);
+ sendEvent(DequeueEvent(dequeues), l);
}
// Called after the message has been removed
@@ -307,23 +303,16 @@ void ReplicatingSubscription::dequeued(ReplicationId id)
// Called with lock held. Called in subscription's connection thread.
void ReplicatingSubscription::sendIdEvent(ReplicationId pos, Mutex::ScopedLock& l)
{
- sendEvent(QueueReplicator::ID_EVENT_KEY, encodeStr(pos), l);
+ sendEvent(IdEvent(pos), l);
}
-void ReplicatingSubscription::sendEvent(const std::string& key,
- const std::string& buffer,
- Mutex::ScopedLock&)
+void ReplicatingSubscription::sendEvent(const Event& event, Mutex::ScopedLock&)
{
Mutex::ScopedUnlock u(lock);
- broker::Message message = makeMessage(buffer);
- MessageTransfer& transfer = MessageTransfer::get(message);
- DeliveryProperties* props =
- transfer.getFrames().getHeaders()->get<DeliveryProperties>(true);
- props->setRoutingKey(key);
// Send the event directly to the base consumer implementation. The dummy
// consumer prevents acknowledgements being handled, which is what we want
// for events
- ConsumerImpl::deliver(QueueCursor(), message, boost::shared_ptr<Consumer>());
+ ConsumerImpl::deliver(QueueCursor(), event.message(), boost::shared_ptr<Consumer>());
}
// Called in subscription's connection thread.
@@ -342,4 +331,9 @@ bool ReplicatingSubscription::doDispatch()
}
}
+void ReplicatingSubscription::addSkip(const ReplicationIdSet& ids) {
+ Mutex::ScopedLock l(lock);
+ skip += ids;
+}
+
}} // namespace qpid::ha
diff --git a/qpid/cpp/src/qpid/ha/ReplicatingSubscription.h b/qpid/cpp/src/qpid/ha/ReplicatingSubscription.h
index c202089e91..71993bcb12 100644
--- a/qpid/cpp/src/qpid/ha/ReplicatingSubscription.h
+++ b/qpid/cpp/src/qpid/ha/ReplicatingSubscription.h
@@ -25,7 +25,6 @@
#include "BrokerInfo.h"
#include "qpid/broker/SemanticState.h"
#include "qpid/broker/ConsumerFactory.h"
-#include "qpid/types/Uuid.h"
#include <iosfwd>
namespace qpid {
@@ -44,6 +43,8 @@ class Buffer;
namespace ha {
class QueueGuard;
class HaBroker;
+class Event;
+class Primary;
/**
* A susbcription that replicates to a remote backup.
@@ -118,6 +119,9 @@ class ReplicatingSubscription : public broker::SemanticState::ConsumerImpl
BrokerInfo getBrokerInfo() const { return info; }
+ /** Skip replicating enqueue of of ids. */
+ void addSkip(const ReplicationIdSet& ids);
+
protected:
bool doDispatch();
@@ -128,7 +132,7 @@ class ReplicatingSubscription : public broker::SemanticState::ConsumerImpl
std::string logPrefix;
QueuePosition position;
ReplicationIdSet dequeues; // Dequeues to be sent in next dequeue event.
- ReplicationIdSet skip; // Messages already on backup will be skipped.
+ ReplicationIdSet skip; // Skip enqueues: messages already on backup and tx enqueues.
ReplicationIdSet unready; // Unguarded, replicated and un-acknowledged.
bool ready;
bool cancelled;
@@ -136,12 +140,13 @@ class ReplicatingSubscription : public broker::SemanticState::ConsumerImpl
boost::shared_ptr<QueueGuard> guard;
HaBroker& haBroker;
boost::shared_ptr<QueueObserver> observer;
+ boost::shared_ptr<Primary> primary;
bool isGuarded(sys::Mutex::ScopedLock&);
void dequeued(ReplicationId);
void sendDequeueEvent(sys::Mutex::ScopedLock&);
void sendIdEvent(ReplicationId, sys::Mutex::ScopedLock&);
- void sendEvent(const std::string& key, const std::string& data, sys::Mutex::ScopedLock&);
+ void sendEvent(const Event&, sys::Mutex::ScopedLock&);
void checkReady(sys::Mutex::ScopedLock&);
friend class Factory;
};
diff --git a/qpid/cpp/src/qpid/ha/ReplicationTest.h b/qpid/cpp/src/qpid/ha/ReplicationTest.h
index 7d44d82a21..c157385ce6 100644
--- a/qpid/cpp/src/qpid/ha/ReplicationTest.h
+++ b/qpid/cpp/src/qpid/ha/ReplicationTest.h
@@ -41,6 +41,13 @@ namespace ha {
/**
* Test whether something is replicated, taking into account the
* default replication level.
+ *
+ * The primary uses a ReplicationTest with default based on configuration
+ * settings, and marks objects to be replicated with an explict replication
+ * argument.
+ *
+ * The backup uses a default of NONE, so it always accepts what the primary has
+ * marked on the object.
*/
class ReplicationTest
{
diff --git a/qpid/cpp/src/qpid/ha/StatusCheck.cpp b/qpid/cpp/src/qpid/ha/StatusCheck.cpp
index d73f2cf8b5..fdc256d5a2 100644
--- a/qpid/cpp/src/qpid/ha/StatusCheck.cpp
+++ b/qpid/cpp/src/qpid/ha/StatusCheck.cpp
@@ -20,6 +20,8 @@
*/
#include "StatusCheck.h"
#include "ConnectionObserver.h"
+#include "HaBroker.h"
+#include "qpid/broker/Broker.h"
#include "qpid/log/Statement.h"
#include "qpid/messaging/Address.h"
#include "qpid/messaging/Connection.h"
@@ -41,27 +43,32 @@ const string HA_BROKER = "org.apache.qpid.ha:habroker:ha-broker";
class StatusCheckThread : public sys::Runnable {
public:
- StatusCheckThread(StatusCheck& sc, const qpid::Address& addr, const BrokerInfo& self)
- : url(addr), statusCheck(sc), brokerInfo(self) {}
+ StatusCheckThread(StatusCheck& sc, const qpid::Address& addr)
+ : url(addr), statusCheck(sc) {}
void run();
private:
Url url;
StatusCheck& statusCheck;
- BrokerInfo brokerInfo;
};
void StatusCheckThread::run() {
- QPID_LOG(debug, statusCheck.logPrefix << "Checking status of " << url);
+ string logPrefix("Status check " + url.str() + ": ");
Connection c;
try {
+ // Check for self connections
Variant::Map options, clientProperties;
- clientProperties = brokerInfo.asMap(); // Detect self connections.
clientProperties[ConnectionObserver::ADMIN_TAG] = 1; // Allow connection to backups.
clientProperties[ConnectionObserver::ADDRESS_TAG] = url.str();
- clientProperties[ConnectionObserver::BACKUP_TAG] = brokerInfo.asMap();
+ clientProperties[ConnectionObserver::BACKUP_TAG] = statusCheck.haBroker.getBrokerInfo().asMap();
+ // Set connection options
+ Settings settings(statusCheck.haBroker.getSettings());
+ if (settings.username.size()) options["username"] = settings.username;
+ if (settings.password.size()) options["password"] = settings.password;
+ if (settings.mechanism.size()) options["sasl_mechanisms"] = settings.mechanism;
options["client-properties"] = clientProperties;
- options["heartbeat"] = statusCheck.linkHeartbeatInterval/sys::TIME_SEC;
+ sys::Duration heartbeat(statusCheck.haBroker.getBroker().getOptions().linkHeartbeatInterval);
+ options["heartbeat"] = heartbeat/sys::TIME_SEC;
c = Connection(url.str(), options);
c.open();
@@ -81,7 +88,7 @@ void StatusCheckThread::run() {
content["_object_id"] = oid;
encode(content, request);
s.send(request);
- messaging::Duration timeout(statusCheck.linkHeartbeatInterval/sys::TIME_MSEC);
+ messaging::Duration timeout(heartbeat/sys::TIME_MSEC);
Message response = r.fetch(timeout);
session.acknowledge();
Variant::List contentIn;
@@ -89,29 +96,24 @@ void StatusCheckThread::run() {
if (contentIn.size() == 1) {
Variant::Map details = contentIn.front().asMap()["_values"].asMap();
string status = details["status"].getString();
+ QPID_LOG(debug, logPrefix << status);
if (status != "joining") {
statusCheck.setPromote(false);
- QPID_LOG(info, statusCheck.logPrefix << "Status of " << url << " is "
- << status << ", this broker will refuse promotion.");
+ QPID_LOG(info, logPrefix << "Joining established cluster");
}
- QPID_LOG(debug, statusCheck.logPrefix << "Status of " << url << ": " << status);
}
+ else
+ QPID_LOG(error, logPrefix << "Invalid response " << response.getContent())
} catch(const exception& error) {
- QPID_LOG(info, statusCheck.logPrefix << "Checking status of " << url << ": " << error.what());
- }
- try { c.close(); }
- catch(const exception&) {
- QPID_LOG(warning, statusCheck.logPrefix << "Error closing status check connection to " << url);
- }
- try { c.close(); }
- catch(const exception&) {
- QPID_LOG(warning, "Error closing status check connection to " << url);
+ // Its not an error to fail to connect to self.
+ if (statusCheck.haBroker.getBrokerInfo().getAddress() != url[0])
+ QPID_LOG(warning, logPrefix << error.what());
}
+ try { c.close(); } catch(...) {}
delete this;
}
-StatusCheck::StatusCheck(const string& lp, sys::Duration lh, const BrokerInfo& self)
- : logPrefix(lp), promote(true), linkHeartbeatInterval(lh), brokerInfo(self)
+StatusCheck::StatusCheck(HaBroker& hb) : promote(true), haBroker(hb)
{}
StatusCheck::~StatusCheck() {
@@ -122,7 +124,7 @@ StatusCheck::~StatusCheck() {
void StatusCheck::setUrl(const Url& url) {
Mutex::ScopedLock l(lock);
for (size_t i = 0; i < url.size(); ++i)
- threads.push_back(Thread(new StatusCheckThread(*this, url[i], brokerInfo)));
+ threads.push_back(Thread(new StatusCheckThread(*this, url[i])));
}
bool StatusCheck::canPromote() {
diff --git a/qpid/cpp/src/qpid/ha/StatusCheck.h b/qpid/cpp/src/qpid/ha/StatusCheck.h
index 65ad3cefcf..8896969f55 100644
--- a/qpid/cpp/src/qpid/ha/StatusCheck.h
+++ b/qpid/cpp/src/qpid/ha/StatusCheck.h
@@ -23,6 +23,7 @@
*/
#include "BrokerInfo.h"
+#include "Settings.h"
#include "qpid/Url.h"
#include "qpid/sys/Thread.h"
#include "qpid/sys/Mutex.h"
@@ -33,6 +34,8 @@
namespace qpid {
namespace ha {
+class HaBroker;
+
// TODO aconway 2012-12-21: This solution is incomplete. It will only protect
// against bad promotion if there are READY brokers when this broker starts.
// It will not help the situation where brokers became READY after this one starts.
@@ -51,7 +54,7 @@ namespace ha {
class StatusCheck
{
public:
- StatusCheck(const std::string& logPrefix, sys::Duration linkHeartbeatInterval, const BrokerInfo& self);
+ StatusCheck(HaBroker&);
~StatusCheck();
void setUrl(const Url&);
bool canPromote();
@@ -59,12 +62,11 @@ class StatusCheck
private:
void setPromote(bool p);
- std::string logPrefix;
sys::Mutex lock;
std::vector<sys::Thread> threads;
bool promote;
- sys::Duration linkHeartbeatInterval;
- BrokerInfo brokerInfo;
+ HaBroker& haBroker;
+
friend class StatusCheckThread;
};
}} // namespace qpid::ha
diff --git a/qpid/cpp/src/qpid/ha/TxReplicator.cpp b/qpid/cpp/src/qpid/ha/TxReplicator.cpp
new file mode 100644
index 0000000000..63301a92f5
--- /dev/null
+++ b/qpid/cpp/src/qpid/ha/TxReplicator.cpp
@@ -0,0 +1,247 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+
+#include "TxReplicator.h"
+#include "Role.h"
+#include "Backup.h"
+#include "BrokerReplicator.h"
+#include "Event.h"
+#include "HaBroker.h"
+#include "types.h"
+#include "qpid/broker/Broker.h"
+#include "qpid/broker/Link.h"
+#include "qpid/broker/QueueRegistry.h"
+#include "qpid/broker/Queue.h"
+#include "qpid/broker/SessionHandler.h"
+#include "qpid/broker/TxBuffer.h"
+#include "qpid/broker/TxAccept.h"
+#include "qpid/broker/amqp_0_10/Connection.h"
+#include "qpid/broker/DeliverableMessage.h"
+#include "qpid/framing/BufferTypes.h"
+#include "qpid/log/Statement.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+#include "qpid/broker/amqp_0_10/MessageTransfer.h"
+#include "qpid/framing/MessageTransferBody.h"
+
+namespace qpid {
+namespace ha {
+
+using namespace std;
+using namespace qpid::broker;
+using namespace qpid::framing;
+using qpid::broker::amqp_0_10::MessageTransfer;
+using qpid::types::Uuid;
+
+namespace {
+const string QPID_HA(QPID_HA_PREFIX);
+const string TYPE_NAME(QPID_HA+"tx-replicator");
+const string PREFIX(TRANSACTION_REPLICATOR_PREFIX);
+
+} // namespace
+
+
+
+bool TxReplicator::isTxQueue(const string& q) {
+ return startsWith(q, PREFIX);
+}
+
+string TxReplicator::getTxId(const string& q) {
+ assert(isTxQueue(q));
+ return q.substr(PREFIX.size());
+}
+
+string TxReplicator::getType() const { return TYPE_NAME; }
+
+TxReplicator::TxReplicator(
+ HaBroker& hb,
+ const boost::shared_ptr<broker::Queue>& txQueue,
+ const boost::shared_ptr<broker::Link>& link) :
+ QueueReplicator(hb, txQueue, link),
+ txBuffer(new broker::TxBuffer),
+ store(hb.getBroker().hasStore() ? &hb.getBroker().getStore() : 0),
+ channel(link->nextChannel()),
+ complete(false), ignore(false),
+ dequeueState(hb.getBroker().getQueues())
+{
+ string id(getTxId(txQueue->getName()));
+ string shortId = id.substr(0, 8);
+ logPrefix = "Backup of transaction "+shortId+": ";
+ QPID_LOG(debug, logPrefix << "Started TX " << id);
+ if (!store) throw Exception(QPID_MSG(logPrefix << "No message store loaded."));
+
+ // Dispatch transaction events.
+ dispatch[TxEnqueueEvent::KEY] =
+ boost::bind(&TxReplicator::enqueue, this, _1, _2);
+ dispatch[TxDequeueEvent::KEY] =
+ boost::bind(&TxReplicator::dequeue, this, _1, _2);
+ dispatch[TxPrepareEvent::KEY] =
+ boost::bind(&TxReplicator::prepare, this, _1, _2);
+ dispatch[TxCommitEvent::KEY] =
+ boost::bind(&TxReplicator::commit, this, _1, _2);
+ dispatch[TxRollbackEvent::KEY] =
+ boost::bind(&TxReplicator::rollback, this, _1, _2);
+ dispatch[TxMembersEvent::KEY] =
+ boost::bind(&TxReplicator::members, this, _1, _2);
+}
+
+TxReplicator::~TxReplicator() {
+ link->returnChannel(channel);
+}
+
+// Send a message to the primary tx.
+void TxReplicator::sendMessage(const broker::Message& msg, sys::Mutex::ScopedLock&) {
+ assert(sessionHandler);
+ const MessageTransfer& transfer(MessageTransfer::get(msg));
+ for (FrameSet::const_iterator i = transfer.getFrames().begin();
+ i != transfer.getFrames().end();
+ ++i)
+ {
+ sessionHandler->out.handle(const_cast<AMQFrame&>(*i));
+ }
+}
+
+void TxReplicator::route(broker::Deliverable& deliverable) {
+ if (!ignore) QueueReplicator::route(deliverable);
+}
+
+void TxReplicator::deliver(const broker::Message& m_) {
+ sys::Mutex::ScopedLock l(lock);
+ // Deliver message to the target queue, not the tx-queue.
+ broker::Message m(m_);
+ m.setReplicationId(enq.id); // Use replicated id.
+ boost::shared_ptr<broker::Queue> queue =
+ haBroker.getBroker().getQueues().get(enq.queue);
+ QPID_LOG(trace, logPrefix << "Deliver " << LogMessageId(*queue, m));
+ DeliverableMessage dm(m, txBuffer.get());
+ dm.deliverTo(queue);
+}
+
+void TxReplicator::enqueue(const string& data, sys::Mutex::ScopedLock&) {
+ sys::Mutex::ScopedLock l(lock);
+ TxEnqueueEvent e;
+ decodeStr(data, e);
+ QPID_LOG(trace, logPrefix << "Enqueue: " << e);
+ enq = e;
+}
+
+void TxReplicator::dequeue(const string& data, sys::Mutex::ScopedLock&) {
+ sys::Mutex::ScopedLock l(lock);
+ TxDequeueEvent e;
+ decodeStr(data, e);
+ QPID_LOG(trace, logPrefix << "Dequeue: " << e);
+ // NOTE: Backup does not see transactional dequeues until the transaction is
+ // prepared, then they are all receieved before the prepare event.
+ // We collect the events here so we can do a single scan of the queue in prepare.
+ dequeueState.add(e);
+}
+
+void TxReplicator::DequeueState::add(const TxDequeueEvent& event) {
+ events[event.queue] += event.id;
+}
+
+// Use this function as a seek() predicate to find the dequeued messages.
+bool TxReplicator::DequeueState::addRecord(
+ const broker::Message& m, const boost::shared_ptr<Queue>& queue,
+ const ReplicationIdSet& rids)
+{
+ if (rids.contains(m.getReplicationId())) {
+ DeliveryRecord dr(cursor, m.getSequence(), m.getReplicationId(), queue,
+ string() /*tag*/,
+ boost::shared_ptr<Consumer>(),
+ true /*acquired*/,
+ false /*accepted*/,
+ false /*credit.isWindowMode()*/,
+ 0 /*credit*/);
+ // Generate record ids, unique within this transaction.
+ dr.setId(nextId++);
+ records.push_back(dr);
+ recordIds += dr.getId();
+ }
+ return false;
+}
+
+void TxReplicator::DequeueState::addRecords(const EventMap::value_type& entry) {
+ // Process all the dequeues for a single queue, in one pass of seek()
+ boost::shared_ptr<broker::Queue> q = queues.get(entry.first);
+ q->seek(cursor, boost::bind(&TxReplicator::DequeueState::addRecord,
+ this, _1, q, entry.second));
+}
+
+boost::shared_ptr<TxAccept> TxReplicator::DequeueState::makeAccept() {
+ for_each(events.begin(), events.end(),
+ boost::bind(&TxReplicator::DequeueState::addRecords, this, _1));
+ return boost::shared_ptr<TxAccept>(
+ new TxAccept(boost::cref(recordIds), boost::ref(records)));
+}
+
+void TxReplicator::prepare(const string&, sys::Mutex::ScopedLock& l) {
+ txBuffer->enlist(dequeueState.makeAccept());
+ context = store->begin();
+ if (txBuffer->prepare(context.get())) {
+ QPID_LOG(debug, logPrefix << "Prepared OK");
+ sendMessage(TxPrepareOkEvent(haBroker.getSystemId()).message(queue->getName()), l);
+ } else {
+ QPID_LOG(debug, logPrefix << "Prepare failed");
+ sendMessage(TxPrepareFailEvent(haBroker.getSystemId()).message(queue->getName()), l);
+ }
+}
+
+void TxReplicator::commit(const string&, sys::Mutex::ScopedLock& l) {
+ QPID_LOG(debug, logPrefix << "Commit");
+ if (context.get()) store->commit(*context);
+ txBuffer->commit();
+ end(l);
+}
+
+void TxReplicator::rollback(const string&, sys::Mutex::ScopedLock& l) {
+ QPID_LOG(debug, logPrefix << "Rollback");
+ if (context.get()) store->abort(*context);
+ txBuffer->rollback();
+ end(l);
+}
+
+void TxReplicator::members(const string& data, sys::Mutex::ScopedLock&) {
+ TxMembersEvent e;
+ decodeStr(data, e);
+ QPID_LOG(debug, logPrefix << "Members: " << e.members);
+ if (!e.members.count(haBroker.getMembership().getSelf().getSystemId())) {
+ QPID_LOG(info, logPrefix << "Not participating in transaction");
+ ignore = true;
+ }
+}
+
+void TxReplicator::end(sys::Mutex::ScopedLock&) {
+ complete = true;
+ if (!getQueue()) return; // Already destroyed
+ // Destroy will cancel the subscription to the primary tx-queue which
+ // informs the primary that we have completed the transaction.
+ destroy();
+}
+
+void TxReplicator::destroy() {
+ QueueReplicator::destroy();
+ sys::Mutex::ScopedLock l(lock);
+ if (!ignore && !complete) rollback(string(), l);
+}
+
+}} // namespace qpid::ha
diff --git a/qpid/cpp/src/qpid/ha/TxReplicator.h b/qpid/cpp/src/qpid/ha/TxReplicator.h
new file mode 100644
index 0000000000..214b2a8a5f
--- /dev/null
+++ b/qpid/cpp/src/qpid/ha/TxReplicator.h
@@ -0,0 +1,131 @@
+#ifndef QPID_HA_TRANSACTIONREPLICATOR_H
+#define QPID_HA_TRANSACTIONREPLICATOR_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "QueueReplicator.h"
+#include "Event.h"
+#include "qpid/broker/DeliveryRecord.h"
+#include "qpid/broker/TransactionalStore.h"
+#include "qpid/sys/Mutex.h"
+
+namespace qpid {
+
+namespace broker {
+class TxBuffer;
+class TxAccept;
+class DtxBuffer;
+class Broker;
+class MessageStore;
+class Deliverable;
+}
+
+namespace ha {
+class BrokerReplicator;
+
+/**
+ * Exchange created on a backup broker to replicate a transaction on the primary.
+ *
+ * Subscribes to a tx-queue like a normal queue but puts replicated messages and
+ * transaction events into a local TxBuffer.
+ *
+ * THREAD SAFE: Called in different connection threads.
+ */
+class TxReplicator : public QueueReplicator {
+ public:
+ typedef boost::shared_ptr<broker::Queue> QueuePtr;
+ typedef boost::shared_ptr<broker::Link> LinkPtr;
+
+ static bool isTxQueue(const std::string& queue);
+ static std::string getTxId(const std::string& queue);
+
+ TxReplicator(HaBroker&, const QueuePtr& txQueue, const LinkPtr& link);
+ ~TxReplicator();
+
+ std::string getType() const;
+
+ // QueueReplicator overrides
+ void route(broker::Deliverable& deliverable);
+ void destroy();
+
+ protected:
+
+ void deliver(const broker::Message&);
+
+ private:
+
+ typedef void (TxReplicator::*DispatchFunction)(
+ const std::string&, sys::Mutex::ScopedLock&);
+ typedef qpid::sys::unordered_map<std::string, DispatchFunction> DispatchMap;
+ typedef qpid::sys::unordered_map<std::string, ReplicationIdSet> DequeueMap;
+
+ void sendMessage(const broker::Message&, sys::Mutex::ScopedLock&);
+ void enqueue(const std::string& data, sys::Mutex::ScopedLock&);
+ void dequeue(const std::string& data, sys::Mutex::ScopedLock&);
+ void prepare(const std::string& data, sys::Mutex::ScopedLock&);
+ void commit(const std::string& data, sys::Mutex::ScopedLock&);
+ void rollback(const std::string& data, sys::Mutex::ScopedLock&);
+ void members(const std::string& data, sys::Mutex::ScopedLock&);
+ void end(sys::Mutex::ScopedLock&);
+
+ std::string logPrefix;
+ TxEnqueueEvent enq; // Enqueue data for next deliver.
+ boost::shared_ptr<broker::TxBuffer> txBuffer;
+ broker::MessageStore* store;
+ std::auto_ptr<broker::TransactionContext> context;
+ framing::ChannelId channel; // Channel to send prepare-complete.
+ bool complete, ignore;
+
+ // Class to process dequeues and create DeliveryRecords to populate a
+ // TxAccept.
+ class DequeueState {
+ public:
+ DequeueState(broker::QueueRegistry& qr) : queues(qr) {}
+ void add(const TxDequeueEvent&);
+ boost::shared_ptr<broker::TxAccept> makeAccept();
+
+ private:
+ // Delivery record IDs are command IDs from the session.
+ // On a backup we will just fake these Ids.
+ typedef framing::SequenceNumber Id;
+ typedef framing::SequenceSet IdSet;
+ typedef qpid::sys::unordered_map<std::string, ReplicationIdSet> EventMap;
+
+ bool addRecord(const broker::Message& m,
+ const boost::shared_ptr<broker::Queue>&,
+ const ReplicationIdSet& );
+ void addRecords(const DequeueMap::value_type& entry);
+
+ broker::QueueRegistry& queues;
+ EventMap events;
+ broker::DeliveryRecords records;
+ broker::QueueCursor cursor;
+ framing::SequenceNumber nextId;
+ IdSet recordIds;
+ };
+ DequeueState dequeueState;
+};
+
+
+}} // namespace qpid::ha
+
+#endif /*!QPID_HA_TRANSACTIONREPLICATOR_H*/
diff --git a/qpid/cpp/src/qpid/ha/hash.h b/qpid/cpp/src/qpid/ha/hash.h
index a513673cce..8a7f3c00fe 100644
--- a/qpid/cpp/src/qpid/ha/hash.h
+++ b/qpid/cpp/src/qpid/ha/hash.h
@@ -22,19 +22,48 @@
*
*/
+#include "qpid/types/Uuid.h"
#include <boost/shared_ptr.hpp>
+#include <utility>
namespace qpid {
namespace ha {
-template<class T> struct TrivialHasher {
- size_t operator()(T value) const { return static_cast<size_t>(value); }
-};
+// TODO aconway 2013-08-06: would like to use boost::hash or std::hash here
+// but not available/working on some older compilers.
+// Add overloads as needed.
+
+inline std::size_t hashValue(bool v) { return static_cast<std::size_t>(v); }
+inline std::size_t hashValue(char v) { return static_cast<std::size_t>(v); }
+inline std::size_t hashValue(unsigned char v) { return static_cast<std::size_t>(v); }
+inline std::size_t hashValue(signed char v) { return static_cast<std::size_t>(v); }
+inline std::size_t hashValue(short v) { return static_cast<std::size_t>(v); }
+inline std::size_t hashValue(unsigned short v) { return static_cast<std::size_t>(v); }
+inline std::size_t hashValue(int v) { return static_cast<std::size_t>(v); }
+inline std::size_t hashValue(unsigned int v) { return static_cast<std::size_t>(v); }
+inline std::size_t hashValue(long v) { return static_cast<std::size_t>(v); }
+inline std::size_t hashValue(unsigned long v) { return static_cast<std::size_t>(v); }
+
+inline std::size_t hashValue(const types::Uuid& v) { return v.hash(); }
+
+template <class T> inline std::size_t hashValue(T* v) {
+ std::size_t x = static_cast<std::size_t>(reinterpret_cast<std::ptrdiff_t>(v));
+ return x + (x >> 3);
+}
+
+template <class T> inline void hashCombine(std::size_t& seed, const T& v) {
+ seed ^= hashValue(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
+}
+
+template <class T, class U> inline size_t hashValue(const std::pair<T,U>& v) {
+ std::size_t seed = 0;
+ hashCombine(seed, v.first);
+ hashCombine(seed, v.second);
+ return seed;
+}
-template<class T> struct SharedPtrHasher {
- size_t operator()(const boost::shared_ptr<T>& ptr) const {
- return reinterpret_cast<size_t>(ptr.get());
- }
+template<class T> struct Hasher {
+ size_t operator()(const T& v) const { return hashValue(v); }
};
}} // namespace qpid::ha
diff --git a/qpid/cpp/src/qpid/ha/makeMessage.h b/qpid/cpp/src/qpid/ha/makeMessage.h
deleted file mode 100644
index 4427cdd948..0000000000
--- a/qpid/cpp/src/qpid/ha/makeMessage.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef QPID_HA_MAKEMESSAGE_H
-#define QPID_HA_MAKEMESSAGE_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/broker/Message.h"
-#include "qpid/framing/Buffer.h"
-#include <string>
-
-/** Utilities for creating messages used by HA internally. */
-
-namespace qpid {
-namespace framing {
-class Buffer;
-}
-namespace ha {
-
-/**
- * Create internal messages used by HA components.
- */
-broker::Message makeMessage(
- const framing::Buffer& content,
- const std::string& destination=std::string()
-);
-
-broker::Message makeMessage(const std::string& content,
- const std::string& destination=std::string());
-
-/** Encode value as a string. */
-template <class T> std::string encodeStr(const T& value) {
- std::string encoded(value.encodedSize(), '\0');
- framing::Buffer buffer(&encoded[0], encoded.size());
- value.encode(buffer);
- return encoded;
-}
-
-/** Decode value from a string. */
-template <class T> T decodeStr(const std::string& encoded) {
- framing::Buffer buffer(const_cast<char*>(&encoded[0]), encoded.size());
- T value;
- value.decode(buffer);
- return value;
-}
-
-}} // namespace qpid::ha
-
-#endif /*!QPID_HA_MAKEMESSAGE_H*/
diff --git a/qpid/cpp/src/qpid/ha/types.cpp b/qpid/cpp/src/qpid/ha/types.cpp
index 2246355339..c02ae33470 100644
--- a/qpid/cpp/src/qpid/ha/types.cpp
+++ b/qpid/cpp/src/qpid/ha/types.cpp
@@ -37,6 +37,14 @@ using namespace std;
const string QPID_REPLICATE("qpid.replicate");
const string QPID_HA_UUID("qpid.ha-uuid");
+const char* QPID_HA_PREFIX = "qpid.ha-";
+const char* QUEUE_REPLICATOR_PREFIX = "qpid.ha-q:";
+const char* TRANSACTION_REPLICATOR_PREFIX = "qpid.ha-tx:";
+
+bool startsWith(const string& name, const string& prefix) {
+ return name.compare(0, prefix.size(), prefix) == 0;
+}
+
string EnumBase::str() const {
assert(value < count);
return names[value];
@@ -79,9 +87,11 @@ istream& operator>>(istream& i, EnumBase& e) {
return i;
}
-ostream& operator<<(ostream& o, const IdSet& ids) {
+ostream& operator<<(ostream& o, const UuidSet& ids) {
ostream_iterator<qpid::types::Uuid> out(o, " ");
+ o << "{ ";
copy(ids.begin(), ids.end(), out);
+ o << "}";
return o;
}
@@ -98,6 +108,24 @@ std::ostream& operator<<(std::ostream& o, const LogMessageId& m) {
return o << m.queue << "[" << m.position << "]=" << m.replicationId;
}
+void UuidSet::encode(framing::Buffer& b) const {
+ b.putLong(size());
+ for (const_iterator i = begin(); i != end(); ++i)
+ b.putRawData(i->data(), i->size());
+}
+
+void UuidSet::decode(framing::Buffer& b) {
+ size_t n = b.getLong();
+ for ( ; n > 0; --n) {
+ types::Uuid id;
+ b.getRawData(const_cast<unsigned char*>(id.data()), id.size());
+ insert(id);
+ }
+}
+
+size_t UuidSet::encodedSize() const {
+ return sizeof(uint32_t) + size()*16;
+}
}} // namespace qpid::ha
diff --git a/qpid/cpp/src/qpid/ha/types.h b/qpid/cpp/src/qpid/ha/types.h
index 9a7e97c66d..92157d411b 100644
--- a/qpid/cpp/src/qpid/ha/types.h
+++ b/qpid/cpp/src/qpid/ha/types.h
@@ -105,14 +105,26 @@ inline bool isPrimary(BrokerStatus s) {
inline bool isBackup(BrokerStatus s) { return !isPrimary(s); }
-// String constants.
+// String constants, defined as char* to avoid initialization order problems.
extern const std::string QPID_REPLICATE;
extern const std::string QPID_HA_UUID;
-/** Define IdSet type, not a typedef so we can overload operator << */
-class IdSet : public std::set<types::Uuid> {};
+// Strings used as prefixes, defined as char* to avoid link order problems.
+extern const char* QPID_HA_PREFIX;
+extern const char* QUEUE_REPLICATOR_PREFIX;
+extern const char* TRANSACTION_REPLICATOR_PREFIX;
-std::ostream& operator<<(std::ostream& o, const IdSet& ids);
+bool startsWith(const std::string& name, const std::string& prefix);
+
+/** Define IdSet type, not a typedef so we can overload operator << and add encoding.*/
+class UuidSet : public std::set<types::Uuid> {
+ public:
+ void encode(framing::Buffer&) const;
+ void decode(framing::Buffer&);
+ size_t encodedSize() const;
+};
+
+std::ostream& operator<<(std::ostream& o, const UuidSet& ids);
// Use type names to distinguish Positions from Replication Ids
typedef framing::SequenceNumber QueuePosition;
@@ -132,5 +144,8 @@ struct LogMessageId {
};
std::ostream& operator<<(std::ostream&, const LogMessageId&);
+/** Return short version of human-readable UUID. */
+inline std::string shortStr(const types::Uuid& uuid) { return uuid.str().substr(0,8); }
+
}} // qpid::ha
#endif /*!QPID_HA_ENUM_H*/
diff --git a/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp b/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp
index 3b42c7bd5d..7863940534 100644
--- a/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp
+++ b/qpid/cpp/src/qpid/legacystore/MessageStoreImpl.cpp
@@ -21,6 +21,7 @@
#include "qpid/legacystore/MessageStoreImpl.h"
+#include "db-inc.h"
#include "qpid/broker/QueueSettings.h"
#include "qpid/legacystore/BindingDbt.h"
#include "qpid/legacystore/BufferValue.h"
@@ -31,7 +32,6 @@
#include "qmf/org/apache/qpid/legacystore/Package.h"
#include "qpid/legacystore/StoreException.h"
#include <dirent.h>
-#include <db.h>
#define MAX_AIO_SLEEPS 100000 // tot: ~1 sec
#define AIO_SLEEP_TIME_US 10 // 0.01 ms
@@ -448,6 +448,8 @@ void MessageStoreImpl::closeDbs()
MessageStoreImpl::~MessageStoreImpl()
{
+ if (mgmtObject.get() != 0)
+ mgmtObject->debugStats("destroying");
finalize();
try {
closeDbs();
diff --git a/qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h b/qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h
index 0a0d0df28d..01d92ee985 100644
--- a/qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h
+++ b/qpid/cpp/src/qpid/legacystore/jrnl/jcfg.h
@@ -33,13 +33,13 @@
#ifndef QPID_LEGACYSTORE_JRNL_JCFG_H
#define QPID_LEGACYSTORE_JRNL_JCFG_H
-#if defined(__i386__) /* little endian, 32 bits */
+#if defined(__i386__) || (__arm__) /* little endian, 32 bits */
#define JRNL_LITTLE_ENDIAN
#define JRNL_32_BIT
#elif defined(__PPC__) || defined(__s390__) /* big endian, 32 bits */
#define JRNL_BIG_ENDIAN
#define JRNL_32_BIT
-#elif defined(__ia64__) || defined(__x86_64__) || defined(__alpha__) /* little endian, 64 bits */
+#elif defined(__ia64__) || defined(__x86_64__) || defined(__alpha__) || (__arm64__) /* little endian, 64 bits */
#define JRNL_LITTLE_ENDIAN
#define JRNL_64_BIT
#elif defined(__powerpc64__) || defined(__s390x__) /* big endian, 64 bits */
diff --git a/qpid/cpp/src/qpid/log/Logger.cpp b/qpid/cpp/src/qpid/log/Logger.cpp
index 16b2f56049..8242acc87e 100644
--- a/qpid/cpp/src/qpid/log/Logger.cpp
+++ b/qpid/cpp/src/qpid/log/Logger.cpp
@@ -24,6 +24,7 @@
#include "qpid/sys/Time.h"
#include "qpid/DisableExceptionLogging.h"
+#include "boost/version.hpp"
#if (BOOST_VERSION >= 104000)
#include <boost/serialization/singleton.hpp>
#else
diff --git a/qpid/cpp/src/qpid/log/Logger.h b/qpid/cpp/src/qpid/log/Logger.h
new file mode 100644
index 0000000000..8c4beb0785
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Logger.h
@@ -0,0 +1,122 @@
+#ifndef QPID_LOG_LOGGER_H
+#define QPID_LOG_LOGGER_H
+
+/*
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/log/Selector.h"
+#include "qpid/log/Options.h"
+#include "qpid/sys/Mutex.h"
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/noncopyable.hpp>
+#include <set>
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+namespace log {
+
+/**
+ * Central logging agent.
+ *
+ * Thread safe, singleton.
+ *
+ * The Logger provides all needed functionality for selecting and
+ * formatting logging output. The actual outputting of log records
+ * is handled by Logger::Output-derived classes instantiated by the
+ * platform's sink-related options.
+ */
+class QPID_COMMON_CLASS_EXTERN Logger : private boost::noncopyable {
+ public:
+ /** Flags indicating what to include in the log output */
+ enum FormatFlag { FILE=1, LINE=2, FUNCTION=4, LEVEL=8, TIME=16, THREAD=32, HIRES=64, CATEGORY=128};
+
+ /**
+ * Logging output sink.
+ *
+ * The Output sink provides an interface to direct logging output to.
+ * Logging sinks are primarily platform-specific as provided for on
+ * each platform.
+ *
+ * Implementations of Output must be thread safe.
+ */
+ class Output {
+ public:
+ QPID_COMMON_EXTERN Output();
+ QPID_COMMON_EXTERN virtual ~Output();
+ /** Receives the statemnt of origin and formatted message to log. */
+ virtual void log(const Statement&, const std::string&) =0;
+ };
+
+ QPID_COMMON_EXTERN static Logger& instance();
+
+ QPID_COMMON_EXTERN Logger();
+ QPID_COMMON_EXTERN ~Logger();
+
+ /** Select the messages to be logged. */
+ QPID_COMMON_EXTERN void select(const Selector& s);
+
+ /** Set the formatting flags, bitwise OR of FormatFlag values. */
+ QPID_COMMON_EXTERN void format(int formatFlags);
+
+ /** Set format flags from options object.
+ *@returns computed flags.
+ */
+ QPID_COMMON_EXTERN int format(const Options&);
+
+ /** Configure logger from Options */
+ QPID_COMMON_EXTERN void configure(const Options& o);
+
+ /** Reset the log selectors */
+ QPID_COMMON_EXTERN void reconfigure(const std::vector<std::string>& selectors);
+
+ /** Add a statement. */
+ QPID_COMMON_EXTERN void add(Statement& s);
+
+ /** Log a message. */
+ QPID_COMMON_EXTERN void log(const Statement&, const std::string&);
+
+ /** Add an output destination for messages */
+ QPID_COMMON_EXTERN void output(std::auto_ptr<Output> out);
+
+ /** Set a prefix for all messages */
+ QPID_COMMON_EXTERN void setPrefix(const std::string& prefix);
+
+ /** Reset the logger. */
+ QPID_COMMON_EXTERN void clear();
+
+ /** Get the options used to configure the logger. */
+ QPID_COMMON_INLINE_EXTERN const Options& getOptions() const { return options; }
+
+ /** Get the hires timestamp setting */
+ QPID_COMMON_EXTERN bool getHiresTimestamp();
+
+ /** Set the hires timestamp setting */
+ QPID_COMMON_EXTERN void setHiresTimestamp(bool setting);
+
+ private:
+ typedef boost::ptr_vector<Output> Outputs;
+ typedef std::set<Statement*> Statements;
+
+ sys::Mutex lock;
+ inline void enable_unlocked(Statement* s);
+
+ Statements statements;
+ Outputs outputs;
+ Selector selector;
+ int flags;
+ std::string prefix;
+ Options options;
+};
+
+}} // namespace qpid::log
+
+
+#endif /*!QPID_LOG_LOGGER_H*/
diff --git a/qpid/cpp/src/qpid/log/Options.h b/qpid/cpp/src/qpid/log/Options.h
new file mode 100644
index 0000000000..42a8fb40fe
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Options.h
@@ -0,0 +1,51 @@
+#ifndef QPID_LOG_OPTIONS_H
+#define QPID_LOG_OPTIONS_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "qpid/Options.h"
+#include "qpid/CommonImportExport.h"
+#include "qpid/log/SinkOptions.h"
+#include <iosfwd>
+#include <memory>
+
+namespace qpid {
+namespace log {
+
+/** Logging options for config parser. */
+struct Options : public qpid::Options {
+ /** Pass argv[0] for use in syslog output */
+ QPID_COMMON_EXTERN Options(const std::string& argv0_=std::string(),
+ const std::string& name_="Logging options");
+ QPID_COMMON_EXTERN Options(const Options &);
+
+ QPID_COMMON_EXTERN Options& operator=(const Options&);
+
+ std::string argv0;
+ std::string name;
+ std::vector<std::string> selectors;
+ std::vector<std::string> deselectors;
+ bool time, level, thread, source, function, hiresTs, category;
+ bool trace;
+ std::string prefix;
+ std::auto_ptr<SinkOptions> sinkOptions;
+};
+
+}} // namespace qpid::log
+
+#endif /*!QPID_LOG_OPTIONS_H*/
diff --git a/qpid/cpp/src/qpid/log/Selector.h b/qpid/cpp/src/qpid/log/Selector.h
new file mode 100644
index 0000000000..1d025e9646
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Selector.h
@@ -0,0 +1,99 @@
+#ifndef SELECTOR_H
+#define SELECTOR_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/log/Statement.h"
+#include "qpid/CommonImportExport.h"
+#include <vector>
+
+namespace qpid {
+namespace log {
+struct Options;
+
+/**
+ * SelectorElement parses a cli/mgmt enable/disable entry into usable fields
+ * where cliEntry = [!]LEVEL[+-][:PATTERN]
+ */
+struct SelectorElement {
+ QPID_COMMON_EXTERN SelectorElement(const std::string cliEntry);
+ std::string levelStr;
+ std::string patternStr;
+ Level level;
+ Category category;
+ bool isDisable;
+ bool isCategory;
+ bool isLevelAndAbove;
+ bool isLevelAndBelow;
+};
+
+/**
+ * A selector identifies the set of log messages to enable.
+ *
+ * Thread object unsafe, pass-by-value type.
+ */
+class Selector {
+ public:
+ /** Empty selector selects nothing */
+ QPID_COMMON_EXTERN Selector();
+
+ /** Set selector from Options */
+ QPID_COMMON_EXTERN Selector(const Options&);
+
+ /** Equavlient to: Selector s; s.enable(l, s) */
+ QPID_COMMON_EXTERN Selector(Level l, const std::string& s=std::string());
+
+ /** Selector from string */
+ QPID_COMMON_EXTERN Selector(const std::string& selector);
+
+ /** push option settings into runtime lookup structs */
+ QPID_COMMON_EXTERN void enable(const std::string& enableStr);
+ QPID_COMMON_EXTERN void disable(const std::string& disableStr);
+
+ /**
+ * Enable/disable messages with level in levels where the file
+ * name contains substring. Empty string matches all.
+ */
+ QPID_COMMON_EXTERN void enable(Level level, const std::string& substring=std::string());
+ QPID_COMMON_EXTERN void disable(Level level, const std::string& substring=std::string());
+
+ /** Tests to determine if function names are in enable/disable tables */
+ QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function);
+ QPID_COMMON_EXTERN bool isDisabled(Level level, const char* function);
+
+ /** Test to determine if log Statement is enabled */
+ QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function, Category category);
+
+ private:
+ typedef std::vector<std::string> FunctionNameTable [LevelTraits::COUNT];
+ FunctionNameTable enabledFunctions; // log function names explicitly enabled
+ FunctionNameTable disabledFunctions; // log function names explicitly disabled
+ bool enableFlags[LevelTraits::COUNT][CategoryTraits::COUNT];
+ bool disableFlags[LevelTraits::COUNT][CategoryTraits::COUNT];
+
+ bool lookupFuncName(Level level, const char* function, FunctionNameTable& table);
+ /** Reset the category enable flags */
+ QPID_COMMON_EXTERN void reset();
+};
+
+
+}} // namespace qpid::log
+
+
+#endif /*!SELECTOR_H*/
diff --git a/qpid/cpp/src/qpid/log/SinkOptions.h b/qpid/cpp/src/qpid/log/SinkOptions.h
new file mode 100644
index 0000000000..7ec2cfbc17
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/SinkOptions.h
@@ -0,0 +1,64 @@
+#ifndef QPID_LOG_SINKOPTIONS_H
+#define QPID_LOG_SINKOPTIONS_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/Options.h"
+#include <string>
+
+namespace qpid {
+namespace log {
+
+class Logger;
+
+/**
+ * Logging sink options.
+ *
+ * Most logging sink options will be platform-specific, even if some are
+ * duplicated. The range of platforms to which this code may be ported
+ * can't be assumed to all have C++ iostreams or files. Thus, this class
+ * is primarily for implementing in a platform-specific way.
+ */
+struct SinkOptions : public qpid::Options {
+
+ // Create a platform's SinkOptions. Pass argv0 as the program name,
+ // useful for syslog-type logging.
+ static SinkOptions *create(const std::string& argv0=std::string());
+
+ SinkOptions(const std::string& name="Logging sink options")
+ : qpid::Options(name)
+ {}
+ virtual ~SinkOptions() {}
+
+ virtual SinkOptions& operator=(const SinkOptions&) = 0;
+
+ // This allows the caller to indicate that there's no normal outputs
+ // available. For example, when running as a daemon. In these cases, the
+ // platform's "syslog"-type output should replace the default stderr
+ // unless some other sink has been selected.
+ virtual void detached(void) = 0;
+
+ // The Logger acting on these options calls setup() to request any
+ // Sinks be set up and fed back to the logger.
+ virtual void setup(Logger *logger) = 0;
+};
+
+}} // namespace qpid::log
+
+#endif /*!QPID_LOG_OPTIONS_H*/
diff --git a/qpid/cpp/src/qpid/log/Statement.h b/qpid/cpp/src/qpid/log/Statement.h
new file mode 100644
index 0000000000..e928e19f22
--- /dev/null
+++ b/qpid/cpp/src/qpid/log/Statement.h
@@ -0,0 +1,242 @@
+#ifndef STATEMENT_H
+#define STATEMENT_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/Msg.h"
+#include "qpid/CommonImportExport.h"
+#include <boost/current_function.hpp>
+
+namespace qpid {
+namespace log {
+
+/** Debugging severity levels
+ * - trace: High-volume debugging messages.
+ * - debug: Debugging messages.
+ * - info: Informational messages.
+ * - notice: Normal but significant condition.
+ * - warning: Warn of a possible problem.
+ * - error: A definite error has occured.
+ * - critical: System in danger of severe failure.
+ */
+enum Level { trace, debug, info, notice, warning, error, critical };
+struct LevelTraits {
+ static const int COUNT=critical+1;
+
+ /** Get level from string name.
+ *@exception if name invalid.
+ */
+ static Level level(const char* name);
+
+ /** Get level from string name.
+ *@exception if name invalid.
+ */
+ static Level level(const std::string& name) {
+ return level(name.c_str());
+ }
+
+ /** String name of level */
+ static const char* name(Level);
+};
+
+/** Formal message categories
+ * https://issues.apache.org/jira/browse/QPID-3902
+ *
+ * Category Source code directory
+ * -------- ---------------------
+ * Security acl ssl gssapi sasl cyrus
+ * Broker broker
+ * Management agent console qmf
+ * Protocol amqp_0_10 framing
+ * System log sys types xml thread mutex fork pipe time ...
+ * HA cluster ha replication
+ * Messaging messaging
+ * Client client
+ * Store store
+ * Network tcp rdma AsynchIO socket epoll
+ * Test
+ * Model <not related to a directory>
+ * Unspecified <must be last in enum>
+ */
+enum Category { security, broker, management, protocol, system, ha, messaging,
+ store, network, test, client, model, unspecified };
+struct CategoryTraits {
+ static const int COUNT=unspecified+1;
+
+ /** Test if given name is a Category name
+ */
+ static bool isCategory(const std::string& name);
+
+ /** Get category from string name
+ * @exception if name invalid.
+ */
+ static Category category(const char* name);
+
+ /** Get category from string name.
+ * @exception if name invalid.
+ */
+ static Category category(const std::string& name) {
+ return category(name.c_str());
+ }
+
+ /** String name of category */
+ static const char* name(Category);
+};
+
+ /** POD struct representing a logging statement in source code. */
+struct Statement {
+ bool enabled;
+ const char* file;
+ int line;
+ const char* function;
+ Level level;
+ Category category;
+
+ QPID_COMMON_EXTERN void log(const std::string& message);
+ QPID_COMMON_EXTERN static void categorize(Statement& s);
+
+ struct Initializer {
+ QPID_COMMON_EXTERN Initializer(Statement& s);
+ Statement& statement;
+ };
+};
+
+///@internal static initializer for a Statement.
+#define QPID_LOG_STATEMENT_INIT_CAT(LEVEL, CATEGORY) \
+{ 0, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (::qpid::log::LEVEL), \
+(::qpid::log::CATEGORY) }
+
+
+///@internal static initializer for a Statement with unspecified category
+#define QPID_LOG_STATEMENT_INIT(LEVEL) \
+QPID_LOG_STATEMENT_INIT_CAT ( LEVEL , unspecified )
+
+/**
+ * Like QPID_LOG but computes an additional boolean test expression
+ * to determine if the message should be logged. Evaluation of both
+ * the test and message expressions occurs only if the requested log level
+ * is enabled.
+ *@param LEVEL severity Level for message, should be one of:
+ * debug, info, notice, warning, error, critical. NB no qpid::log:: prefix.
+ *@param TEST message is logged only if expression TEST evaluates to true.
+ *@param MESSAGE any object with an @eostream operator<<, or a sequence
+ * like of ostreamable objects separated by @e<<.
+ */
+#define QPID_LOG_IF(LEVEL, TEST, MESSAGE) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT(LEVEL); \
+ static Statement::Initializer init_(stmt_); \
+ if (stmt_.enabled && (TEST)) \
+ stmt_.log(::qpid::Msg() << MESSAGE); \
+ } while(0)
+
+/**
+ * Line QPID_LOG_IF but with the additional specification of a category.
+ * @param CATEGORY message category.
+ */
+#define QPID_LOG_IF_CAT(LEVEL, CATEGORY, TEST, MESSAGE) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT_CAT(LEVEL, CATEGORY); \
+ static Statement::Initializer init_(stmt_); \
+ if (stmt_.enabled && (TEST)) \
+ stmt_.log(::qpid::Msg() << MESSAGE); \
+ } while(0)
+
+/**
+ * FLAG must be a boolean variable. Assigns FLAG to true iff logging
+ * is enabled for LEVEL in the calling context. Use when extra
+ * support code is needed to generate log messages, to ensure that it
+ * is only run if the logging level is enabled.
+ * e.g.
+ * bool logWarning;
+ * QPID_LOG_TEST(warning, logWarning);
+ * if (logWarning) { do stuff needed for warning log messages }
+ */
+#define QPID_LOG_TEST(LEVEL, FLAG) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT(LEVEL); \
+ static Statement::Initializer init_(stmt_); \
+ FLAG = stmt_.enabled; \
+ } while(0)
+
+ /**
+ * FLAG must be a boolean variable. Assigns FLAG to true iff logging
+ * is enabled for LEVEL in the calling context. Use when extra
+ * support code is needed to generate log messages, to ensure that it
+ * is only run if the logging level is enabled.
+ * e.g.
+ * bool logWarning;
+ * QPID_LOG_TEST_CAT(warning, System, logWarning);
+ * if (logWarning) { do stuff needed for warning log messages }
+ */
+ #define QPID_LOG_TEST_CAT(LEVEL, CATEGORY, FLAG) \
+ do { \
+ using ::qpid::log::Statement; \
+ static Statement stmt_= QPID_LOG_STATEMENT_INIT_CAT(LEVEL, CATEGORY); \
+ static Statement::Initializer init_(stmt_); \
+ FLAG = stmt_.enabled; \
+ } while(0)
+
+/**
+ * Macro for log statements. Example of use:
+ * @code
+ * QPID_LOG(debug, "There are " << foocount << " foos in the bar.");
+ * QPID_LOG(error, boost::format("Dohickey %s exploded") % dohicky.name());
+ * @endcode
+ * Using QPID_LOG implies a category of Unspecified.
+ *
+ * You can subscribe to log messages by level, by component, by filename
+ * or a combination @see Configuration.
+
+ *@param LEVEL severity Level for message, should be one of:
+ * debug, info, notice, warning, error, critical. NB no qpid::log:: prefix.
+ *@param MESSAGE any object with an @eostream operator<<, or a sequence
+ * like of ostreamable objects separated by @e<<.
+ */
+#define QPID_LOG(LEVEL, MESSAGE) QPID_LOG_IF(LEVEL, true, MESSAGE);
+
+/**
+ * Macro for log statements. Example of use:
+ * @code
+ * QPID_LOG_CAT(debug, System, "There are " << foocount << " foos in the bar.");
+ * QPID_LOG_CAT(error, System, boost::format("Dohickey %s exploded") % dohicky.name());
+ * @endcode
+ * Using QPID_LOG_CAT requires the specification of a category.
+ *
+ * You can subscribe to log messages by level, by component, by filename
+ * or a combination @see Configuration.
+ *
+ *@param LEVEL severity Level for message, should be one of:
+ * debug, info, notice, warning, error, critical. NB no qpid::log:: prefix.
+ *@param CATEGORY basic Category for the message.
+ *@param MESSAGE any object with an @eostream operator<<, or a sequence
+ * like of ostreamable objects separated by @e<<.
+ */
+#define QPID_LOG_CAT(LEVEL, CATEGORY, MESSAGE) QPID_LOG_IF_CAT(LEVEL, CATEGORY, true, MESSAGE);
+
+}} // namespace qpid::log
+
+
+
+
+#endif /*!STATEMENT_H*/
+
diff --git a/qpid/cpp/src/qpid/management/Args.h b/qpid/cpp/src/qpid/management/Args.h
new file mode 100644
index 0000000000..5d1cb7e01d
--- /dev/null
+++ b/qpid/cpp/src/qpid/management/Args.h
@@ -0,0 +1,44 @@
+#ifndef _Args_
+#define _Args_
+
+//
+// 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.
+//
+
+
+namespace qpid {
+namespace management {
+
+class Args
+{
+ public:
+
+ virtual ~Args (void) = 0;
+
+};
+
+inline Args::~Args (void) {}
+
+class ArgsNone : public Args
+{
+};
+
+}}
+
+
+#endif /*!_Args_*/
diff --git a/qpid/cpp/src/qpid/management/Buffer.h b/qpid/cpp/src/qpid/management/Buffer.h
new file mode 100644
index 0000000000..1ac52bf276
--- /dev/null
+++ b/qpid/cpp/src/qpid/management/Buffer.h
@@ -0,0 +1,105 @@
+#ifndef _Management_Buffer_
+#define _Management_Buffer_
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/CommonImportExport.h"
+#include "qpid/types/Exception.h"
+#include "qpid/types/Variant.h"
+#include <string>
+
+namespace qpid {
+namespace framing {
+ class Buffer;
+}
+
+namespace management {
+
+struct OutOfBounds : qpid::types::Exception {
+ OutOfBounds() : qpid::types::Exception(std::string("Out of Bounds")) {}
+};
+
+
+/**
+ * This class is a wrapper around qpid::framing::Buffer that does not include any dependencies
+ * from boost or from qpid::framing.
+ */
+class Buffer
+{
+public:
+ QPID_COMMON_EXTERN Buffer(char* data=0, uint32_t size=0);
+ QPID_COMMON_EXTERN ~Buffer();
+
+ QPID_COMMON_EXTERN void reset();
+
+ QPID_COMMON_EXTERN uint32_t available();
+ QPID_COMMON_EXTERN uint32_t getSize();
+ QPID_COMMON_EXTERN uint32_t getPosition();
+ QPID_COMMON_EXTERN void setPosition(uint32_t);
+ QPID_COMMON_EXTERN char* getPointer();
+
+ QPID_COMMON_EXTERN void putOctet(uint8_t i);
+ QPID_COMMON_EXTERN void putShort(uint16_t i);
+ QPID_COMMON_EXTERN void putLong(uint32_t i);
+ QPID_COMMON_EXTERN void putLongLong(uint64_t i);
+ QPID_COMMON_EXTERN void putInt8(int8_t i);
+ QPID_COMMON_EXTERN void putInt16(int16_t i);
+ QPID_COMMON_EXTERN void putInt32(int32_t i);
+ QPID_COMMON_EXTERN void putInt64(int64_t i);
+ QPID_COMMON_EXTERN void putFloat(float f);
+ QPID_COMMON_EXTERN void putDouble(double f);
+ QPID_COMMON_EXTERN void putBin128(const uint8_t* b);
+
+ QPID_COMMON_EXTERN uint8_t getOctet();
+ QPID_COMMON_EXTERN uint16_t getShort();
+ QPID_COMMON_EXTERN uint32_t getLong();
+ QPID_COMMON_EXTERN uint64_t getLongLong();
+ QPID_COMMON_EXTERN int8_t getInt8();
+ QPID_COMMON_EXTERN int16_t getInt16();
+ QPID_COMMON_EXTERN int32_t getInt32();
+ QPID_COMMON_EXTERN int64_t getInt64();
+ QPID_COMMON_EXTERN float getFloat();
+ QPID_COMMON_EXTERN double getDouble();
+
+ QPID_COMMON_EXTERN void putShortString(const std::string& s);
+ QPID_COMMON_EXTERN void putMediumString(const std::string& s);
+ QPID_COMMON_EXTERN void putLongString(const std::string& s);
+ QPID_COMMON_EXTERN void getShortString(std::string& s);
+ QPID_COMMON_EXTERN void getMediumString(std::string& s);
+ QPID_COMMON_EXTERN void getLongString(std::string& s);
+ QPID_COMMON_EXTERN void getBin128(uint8_t* b);
+
+ QPID_COMMON_EXTERN void putMap(const types::Variant::Map& map);
+ QPID_COMMON_EXTERN void putList(const types::Variant::List& list);
+ QPID_COMMON_EXTERN void getMap(types::Variant::Map& map);
+ QPID_COMMON_EXTERN void getList(types::Variant::List& list);
+
+ QPID_COMMON_EXTERN void putRawData(const std::string& s);
+ QPID_COMMON_EXTERN void getRawData(std::string& s, uint32_t size);
+
+ QPID_COMMON_EXTERN void putRawData(const uint8_t* data, size_t size);
+ QPID_COMMON_EXTERN void getRawData(uint8_t* data, size_t size);
+
+private:
+ framing::Buffer* impl;
+};
+
+}} // namespace qpid::management
+
+#endif
diff --git a/qpid/cpp/src/qpid/management/ConnectionSettings.h b/qpid/cpp/src/qpid/management/ConnectionSettings.h
new file mode 100644
index 0000000000..b631ffa658
--- /dev/null
+++ b/qpid/cpp/src/qpid/management/ConnectionSettings.h
@@ -0,0 +1,118 @@
+#ifndef _management_ConnectionSettings_h
+#define _management_ConnectionSettings_h
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/CommonImportExport.h"
+#include "qpid/types/Variant.h"
+#include <string>
+
+namespace qpid {
+namespace management {
+
+/**
+ * Settings for a Connection.
+ */
+struct ConnectionSettings {
+
+ QPID_COMMON_EXTERN ConnectionSettings();
+ QPID_COMMON_EXTERN virtual ~ConnectionSettings();
+
+ /**
+ * The protocol used for the connection (defaults to 'tcp')
+ */
+ std::string protocol;
+
+ /**
+ * The host (or ip address) to connect to (defaults to 'localhost').
+ */
+ std::string host;
+ /**
+ * The port to connect to (defaults to 5672).
+ */
+ uint16_t port;
+ /**
+ * Allows an AMQP 'virtual host' to be specified for the
+ * connection.
+ */
+ std::string virtualhost;
+
+ /**
+ * The username to use when authenticating the connection. If not
+ * specified the current users login is used if available.
+ */
+ std::string username;
+ /**
+ * The password to use when authenticating the connection.
+ */
+ std::string password;
+ /**
+ * The SASL mechanism to use when authenticating the connection;
+ * the options are currently PLAIN or ANONYMOUS.
+ */
+ std::string mechanism;
+ /**
+ * Allows a locale to be specified for the connection.
+ */
+ std::string locale;
+ /**
+ * Allows a heartbeat frequency to be specified
+ */
+ uint16_t heartbeat;
+ /**
+ * The maximum number of channels that the client will request for
+ * use on this connection.
+ */
+ uint16_t maxChannels;
+ /**
+ * The maximum frame size that the client will request for this
+ * connection.
+ */
+ uint16_t maxFrameSize;
+ /**
+ * Limit the size of the connections send buffer . The buffer
+ * is limited to bounds * maxFrameSize.
+ */
+ unsigned int bounds;
+ /**
+ * If true, TCP_NODELAY will be set for the connection.
+ */
+ bool tcpNoDelay;
+ /**
+ * SASL service name
+ */
+ std::string service;
+ /**
+ * Minimum acceptable strength of any SASL negotiated security
+ * layer. 0 means no security layer required.
+ */
+ unsigned int minSsf;
+ /**
+ * Maximum acceptable strength of any SASL negotiated security
+ * layer. 0 means no security layer allowed.
+ */
+ unsigned int maxSsf;
+};
+
+}}
+
+#endif
+
diff --git a/qpid/cpp/src/qpid/management/Manageable.h b/qpid/cpp/src/qpid/management/Manageable.h
new file mode 100644
index 0000000000..ede5c29e43
--- /dev/null
+++ b/qpid/cpp/src/qpid/management/Manageable.h
@@ -0,0 +1,81 @@
+#ifndef _Manageable_
+#define _Manageable_
+
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+#include "qpid/management/ManagementObject.h"
+#include "qpid/management/Args.h"
+#include <string>
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+namespace management {
+
+class QPID_COMMON_EXTERN Manageable
+{
+ public:
+
+ virtual ~Manageable(void) = 0;
+
+ // status_t is a type used to pass completion status from the method handler.
+ //
+ typedef uint32_t status_t;
+ static std::string StatusText(status_t status, std::string text = std::string());
+
+ static const status_t STATUS_OK = 0;
+ static const status_t STATUS_UNKNOWN_OBJECT = 1;
+ static const status_t STATUS_UNKNOWN_METHOD = 2;
+ static const status_t STATUS_NOT_IMPLEMENTED = 3;
+ static const status_t STATUS_PARAMETER_INVALID = 4;
+ static const status_t STATUS_FEATURE_NOT_IMPLEMENTED = 5;
+ static const status_t STATUS_FORBIDDEN = 6;
+ static const status_t STATUS_EXCEPTION = 7;
+ static const status_t STATUS_USER = 0x00010000;
+
+ // Every "Manageable" object must hold a reference to exactly one
+ // management object. This object is always of a class derived from
+ // the pure-virtual "ManagementObject".
+ //
+ // This accessor function returns a pointer to the management object.
+ //
+#ifdef _IN_QPID_BROKER
+ virtual ManagementObject::shared_ptr GetManagementObject() const = 0;
+#else
+ virtual ManagementObject* GetManagementObject() const = 0;
+#endif
+
+ // Every "Manageable" object must implement ManagementMethod. This
+ // function is called when a remote management client invokes a method
+ // on this object. The input and output arguments are specific to the
+ // method being called and must be down-cast to the appropriate sub class
+ // before use.
+ virtual status_t ManagementMethod(uint32_t methodId, Args& args, std::string& text);
+
+ // This optional method can be overridden to allow the agent application to
+ // authorize method invocations. Return true iff the authenticated user identified
+ // in userId us authorized to execute the method.
+ virtual bool AuthorizeMethod(uint32_t methodId, Args& args, const std::string& userId);
+};
+
+inline Manageable::~Manageable(void) {}
+
+}}
+
+#endif /*!_Manageable_*/
diff --git a/qpid/cpp/src/qpid/management/ManagementAgent.cpp b/qpid/cpp/src/qpid/management/ManagementAgent.cpp
index 5f653939ec..d80dd6e6a3 100644
--- a/qpid/cpp/src/qpid/management/ManagementAgent.cpp
+++ b/qpid/cpp/src/qpid/management/ManagementAgent.cpp
@@ -39,6 +39,7 @@
#include "qpid/sys/PollableQueue.h"
#include "qpid/broker/Connection.h"
#include "qpid/broker/AclModule.h"
+#include "qpid/broker/Protocol.h"
#include "qpid/types/Variant.h"
#include "qpid/types/Uuid.h"
#include "qpid/framing/List.h"
@@ -169,7 +170,7 @@ ManagementAgent::RemoteAgent::~RemoteAgent ()
}
ManagementAgent::ManagementAgent (const bool qmfV1, const bool qmfV2) :
- threadPoolSize(1), publish(true), interval(10), broker(0), timer(0),
+ threadPoolSize(1), publish(true), interval(10), broker(0), timer(0), protocols(0),
startTime(sys::now()),
suppressed(false), disallowAllV1Methods(false),
vendorNameKey(defaultVendorName), productNameKey(defaultProductName),
@@ -221,6 +222,7 @@ void ManagementAgent::configure(const string& _dataDir, bool _publish, uint16_t
timer = &broker->getTimer();
timer->add(new Periodic(boost::bind(&ManagementAgent::periodicProcessing, this), timer, interval));
+ protocols = &broker->getProtocolRegistry();
// Get from file or generate and save to file.
if (dataDir.empty())
{
@@ -2132,9 +2134,9 @@ bool ManagementAgent::authorizeAgentMessage(Message& msg)
uint32_t bufferLen = inBuffer.getPosition();
inBuffer.reset();
- qpid::broker::amqp_0_10::MessageTransfer& transfer(qpid::broker::amqp_0_10::MessageTransfer::get(msg));
+ boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> transfer = protocols->translate(msg);
const framing::MessageProperties* p =
- transfer.getFrames().getHeaders()->get<framing::MessageProperties>();
+ transfer ? transfer->getFrames().getHeaders()->get<framing::MessageProperties>() : 0;
const framing::FieldTable *headers = p ? &p->getApplicationHeaders() : 0;
@@ -2229,9 +2231,9 @@ bool ManagementAgent::authorizeAgentMessage(Message& msg)
// authorization failed, send reply if replyTo present
- qpid::broker::amqp_0_10::MessageTransfer& transfer(qpid::broker::amqp_0_10::MessageTransfer::get(msg));
+ boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> transfer = protocols->translate(msg);
const framing::MessageProperties* p =
- transfer.getFrames().getHeaders()->get<framing::MessageProperties>();
+ transfer ? transfer->getFrames().getHeaders()->get<framing::MessageProperties>() : 0;
if (p && p->hasReplyTo()) {
const framing::ReplyTo& rt = p->getReplyTo();
string rte = rt.getExchange();
@@ -2266,9 +2268,10 @@ void ManagementAgent::dispatchAgentCommand(Message& msg, bool viaLocal)
{
string rte;
string rtk;
- qpid::broker::amqp_0_10::MessageTransfer& transfer(qpid::broker::amqp_0_10::MessageTransfer::get(msg));
- const framing::MessageProperties* p =
- transfer.getFrames().getHeaders()->get<framing::MessageProperties>();
+
+ boost::intrusive_ptr<const qpid::broker::amqp_0_10::MessageTransfer> transfer = protocols->translate(msg);
+ const framing::MessageProperties* p = transfer ?
+ transfer->getFrames().getHeaders()->get<framing::MessageProperties>() : 0;
if (p && p->hasReplyTo()) {
const framing::ReplyTo& rt = p->getReplyTo();
rte = rt.getExchange();
diff --git a/qpid/cpp/src/qpid/management/ManagementAgent.h b/qpid/cpp/src/qpid/management/ManagementAgent.h
index d2869a705f..c2eb5d4a31 100644
--- a/qpid/cpp/src/qpid/management/ManagementAgent.h
+++ b/qpid/cpp/src/qpid/management/ManagementAgent.h
@@ -44,6 +44,7 @@
namespace qpid {
namespace broker {
class Connection;
+class ProtocolRegistry;
}
namespace sys {
class Timer;
@@ -256,6 +257,7 @@ private:
uint16_t interval;
qpid::broker::Broker* broker;
qpid::sys::Timer* timer;
+ qpid::broker::ProtocolRegistry* protocols;
uint16_t bootSequence;
uint32_t nextObjectId;
uint32_t brokerBank;
diff --git a/qpid/cpp/src/qpid/management/ManagementEvent.h b/qpid/cpp/src/qpid/management/ManagementEvent.h
new file mode 100644
index 0000000000..e80175096f
--- /dev/null
+++ b/qpid/cpp/src/qpid/management/ManagementEvent.h
@@ -0,0 +1,53 @@
+#ifndef _ManagementEvent_
+#define _ManagementEvent_
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/management/ManagementObject.h"
+#include "qpid/types/Variant.h"
+#include <string>
+
+namespace qpid {
+namespace management {
+
+class ManagementAgent;
+
+class ManagementEvent : public ManagementItem {
+ public:
+ static const uint8_t MD5_LEN = 16;
+ //typedef void (*writeSchemaCall_t)(qpid::framing::Buffer&);
+ typedef void (*writeSchemaCall_t)(std::string&);
+ virtual ~ManagementEvent() {}
+
+ virtual writeSchemaCall_t getWriteSchemaCall(void) = 0;
+ //virtual mapEncodeSchemaCall_t getMapEncodeSchemaCall(void) = 0;
+ virtual std::string& getEventName() const = 0;
+ virtual std::string& getPackageName() const = 0;
+ virtual uint8_t* getMd5Sum() const = 0;
+ virtual uint8_t getSeverity() const = 0;
+ virtual void encode(std::string&) const = 0;
+ virtual void mapEncode(qpid::types::Variant::Map&) const = 0;
+};
+
+}}
+
+#endif /*!_ManagementEvent_*/
diff --git a/qpid/cpp/src/qpid/management/ManagementObject.h b/qpid/cpp/src/qpid/management/ManagementObject.h
new file mode 100644
index 0000000000..93fbec7bc7
--- /dev/null
+++ b/qpid/cpp/src/qpid/management/ManagementObject.h
@@ -0,0 +1,246 @@
+#ifndef _ManagementObject_
+#define _ManagementObject_
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/CommonImportExport.h"
+
+#include "qpid/management/Mutex.h"
+#include "qpid/types/Variant.h"
+#include <map>
+#include <vector>
+
+#ifdef _IN_QPID_BROKER
+#include <boost/shared_ptr.hpp>
+#endif
+
+namespace qpid {
+namespace management {
+
+class Manageable;
+class ObjectId;
+class ManagementObject;
+
+
+class AgentAttachment {
+ friend class ObjectId;
+private:
+ uint64_t first;
+public:
+ AgentAttachment() : first(0) {}
+ QPID_COMMON_EXTERN void setBanks(uint32_t broker, uint32_t bank);
+ uint64_t getFirst() const { return first; }
+};
+
+
+class ObjectId {
+protected:
+ const AgentAttachment* agent;
+ uint64_t first;
+ uint64_t second;
+ uint64_t agentEpoch;
+ std::string v2Key;
+ std::string agentName;
+ void fromString(const std::string&);
+public:
+ QPID_COMMON_INLINE_EXTERN ObjectId() : agent(0), first(0), second(0), agentEpoch(0) {}
+ QPID_COMMON_INLINE_EXTERN ObjectId(const types::Variant& map) :
+ agent(0), first(0), second(0), agentEpoch(0) { mapDecode(map.asMap()); }
+ QPID_COMMON_EXTERN ObjectId(uint8_t flags, uint16_t seq, uint32_t broker);
+ QPID_COMMON_EXTERN ObjectId(AgentAttachment* _agent, uint8_t flags, uint16_t seq);
+ QPID_COMMON_EXTERN ObjectId(std::istream&);
+ QPID_COMMON_EXTERN ObjectId(const std::string&);
+ QPID_COMMON_INLINE_EXTERN ObjectId(const std::string& agentAddress, const std::string& key,
+ uint64_t epoch=0) : agent(0), first(0), second(0),
+ agentEpoch(epoch), v2Key(key), agentName(agentAddress) {}
+
+ // Deprecated:
+ QPID_COMMON_EXTERN ObjectId(uint8_t flags, uint16_t seq, uint32_t broker, uint64_t object);
+ QPID_COMMON_EXTERN bool operator==(const ObjectId &other) const;
+ QPID_COMMON_EXTERN bool operator<(const ObjectId &other) const;
+ QPID_COMMON_EXTERN void mapEncode(types::Variant::Map& map) const;
+ QPID_COMMON_EXTERN void mapDecode(const types::Variant::Map& map);
+ QPID_COMMON_EXTERN operator types::Variant::Map() const;
+ QPID_COMMON_INLINE_EXTERN uint32_t encodedSize() const { return 16; };
+ QPID_COMMON_EXTERN void encode(std::string& buffer) const;
+ QPID_COMMON_EXTERN void decode(const std::string& buffer);
+ QPID_COMMON_EXTERN bool equalV1(const ObjectId &other) const;
+ QPID_COMMON_INLINE_EXTERN void setV2Key(const std::string& _key) { v2Key = _key; }
+ QPID_COMMON_EXTERN void setV2Key(const ManagementObject& object);
+ QPID_COMMON_INLINE_EXTERN void setAgentName(const std::string& _name) { agentName = _name; }
+ QPID_COMMON_INLINE_EXTERN const std::string& getAgentName() const { return agentName; }
+ QPID_COMMON_INLINE_EXTERN const std::string& getV2Key() const { return v2Key; }
+ friend QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const ObjectId&);
+};
+
+class ManagementItem {
+public:
+ static const uint8_t TYPE_U8 = 1;
+ static const uint8_t TYPE_U16 = 2;
+ static const uint8_t TYPE_U32 = 3;
+ static const uint8_t TYPE_U64 = 4;
+ static const uint8_t TYPE_SSTR = 6;
+ static const uint8_t TYPE_LSTR = 7;
+ static const uint8_t TYPE_ABSTIME = 8;
+ static const uint8_t TYPE_DELTATIME = 9;
+ static const uint8_t TYPE_REF = 10;
+ static const uint8_t TYPE_BOOL = 11;
+ static const uint8_t TYPE_FLOAT = 12;
+ static const uint8_t TYPE_DOUBLE = 13;
+ static const uint8_t TYPE_UUID = 14;
+ static const uint8_t TYPE_FTABLE = 15;
+ static const uint8_t TYPE_S8 = 16;
+ static const uint8_t TYPE_S16 = 17;
+ static const uint8_t TYPE_S32 = 18;
+ static const uint8_t TYPE_S64 = 19;
+ static const uint8_t TYPE_LIST = 21;
+
+ static const uint8_t ACCESS_RC = 1;
+ static const uint8_t ACCESS_RW = 2;
+ static const uint8_t ACCESS_RO = 3;
+
+ static const uint8_t DIR_I = 1;
+ static const uint8_t DIR_O = 2;
+ static const uint8_t DIR_IO = 3;
+
+ static const uint8_t FLAG_CONFIG = 0x01;
+ static const uint8_t FLAG_INDEX = 0x02;
+ static const uint8_t FLAG_END = 0x80;
+
+ const static uint8_t CLASS_KIND_TABLE = 1;
+ const static uint8_t CLASS_KIND_EVENT = 2;
+
+
+
+public:
+ virtual ~ManagementItem() {}
+};
+
+class QPID_COMMON_CLASS_EXTERN ManagementObject : public ManagementItem
+{
+protected:
+
+ uint64_t createTime;
+ uint64_t destroyTime;
+ uint64_t updateTime;
+ ObjectId objectId;
+ mutable bool configChanged;
+ mutable bool instChanged;
+ bool deleted;
+ Manageable* coreObject;
+ mutable Mutex accessLock;
+ uint32_t flags;
+
+ static int nextThreadIndex;
+ bool forcePublish;
+
+ QPID_COMMON_EXTERN int getThreadIndex();
+ QPID_COMMON_EXTERN void writeTimestamps(std::string& buf) const;
+ QPID_COMMON_EXTERN void readTimestamps(const std::string& buf);
+ QPID_COMMON_EXTERN uint32_t writeTimestampsSize() const;
+
+ public:
+#ifdef _IN_QPID_BROKER
+ typedef boost::shared_ptr<ManagementObject> shared_ptr;
+#endif
+
+ QPID_COMMON_EXTERN static const uint8_t MD5_LEN = 16;
+ QPID_COMMON_EXTERN static int maxThreads;
+ //typedef void (*writeSchemaCall_t) (qpid::framing::Buffer&);
+ typedef void (*writeSchemaCall_t) (std::string&);
+
+ QPID_COMMON_EXTERN ManagementObject(Manageable* _core);
+ virtual ~ManagementObject() {}
+
+ virtual writeSchemaCall_t getWriteSchemaCall() = 0;
+ virtual std::string getKey() const = 0;
+
+ // Encode & Decode the property and statistics values
+ // for this object.
+ virtual void mapEncodeValues(types::Variant::Map& map,
+ bool includeProperties,
+ bool includeStatistics) = 0;
+ virtual void mapDecodeValues(const types::Variant::Map& map) = 0;
+ virtual void doMethod(std::string& methodName,
+ const types::Variant::Map& inMap,
+ types::Variant::Map& outMap,
+ const std::string& userId) = 0;
+ QPID_COMMON_EXTERN void writeTimestamps(types::Variant::Map& map) const;
+ QPID_COMMON_EXTERN void readTimestamps(const types::Variant::Map& buf);
+
+ /**
+ * The following five methods are not pure-virtual because they will only
+ * be overridden in cases where QMFv1 is to be supported.
+ */
+ virtual uint32_t writePropertiesSize() const { return 0; }
+ virtual void readProperties(const std::string&) {}
+ virtual void writeProperties(std::string&) const {}
+ virtual void writeStatistics(std::string&, bool = false) {}
+ virtual void doMethod(std::string&, const std::string&, std::string&, const std::string&) {}
+
+ QPID_COMMON_EXTERN virtual void setReference(ObjectId objectId);
+
+ virtual std::string& getClassName() const = 0;
+ virtual std::string& getPackageName() const = 0;
+ virtual uint8_t* getMd5Sum() const = 0;
+
+ void setObjectId(ObjectId oid) { objectId = oid; }
+ ObjectId getObjectId() { return objectId; }
+ inline bool getConfigChanged() { return configChanged; }
+ virtual bool getInstChanged() { return instChanged; }
+ virtual bool hasInst() { return true; }
+ inline void setForcePublish(bool f) { forcePublish = f; }
+ inline bool getForcePublish() { return forcePublish; }
+ QPID_COMMON_EXTERN void setUpdateTime();
+ QPID_COMMON_EXTERN void resourceDestroy();
+ inline bool isDeleted() { return deleted; }
+ inline void setFlags(uint32_t f) { flags = f; }
+ inline uint32_t getFlags() { return flags; }
+ bool isSameClass(ManagementObject& other) {
+ for (int idx = 0; idx < MD5_LEN; idx++)
+ if (other.getMd5Sum()[idx] != getMd5Sum()[idx])
+ return false;
+ return other.getClassName() == getClassName() &&
+ other.getPackageName() == getPackageName();
+ }
+
+ // QPID_COMMON_EXTERN void encode(qpid::framing::Buffer& buf) const { writeProperties(buf); }
+ // QPID_COMMON_EXTERN void decode(qpid::framing::Buffer& buf) { readProperties(buf); }
+ //QPID_COMMON_EXTERN uint32_t encodedSize() const { return writePropertiesSize(); }
+
+ // Encode/Decode the entire object as a map
+ //QPID_COMMON_EXTERN void mapEncode(types::Variant::Map& map,
+ //bool includeProperties=true,
+ //bool includeStatistics=true);
+
+ //QPID_COMMON_EXTERN void mapDecode(const types::Variant::Map& map);
+};
+
+#ifdef _IN_QPID_BROKER
+typedef std::map<ObjectId, ManagementObject::shared_ptr> ManagementObjectMap;
+typedef std::vector<ManagementObject::shared_ptr> ManagementObjectVector;
+#endif
+
+}}
+
+
+
+#endif /*!_ManagementObject_*/
diff --git a/qpid/cpp/src/qpid/management/Mutex.h b/qpid/cpp/src/qpid/management/Mutex.h
new file mode 100644
index 0000000000..67ae04bae9
--- /dev/null
+++ b/qpid/cpp/src/qpid/management/Mutex.h
@@ -0,0 +1,67 @@
+#ifndef _management_Mutex_h
+#define _management_Mutex_h
+
+/*
+ *
+ * Copyright (c) 2008 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/CommonImportExport.h"
+
+namespace qpid {
+ namespace sys {
+ class Mutex;
+ }
+
+ namespace management {
+
+ /**
+ * Scoped lock template: calls lock() in ctor, unlock() in dtor.
+ * L can be any class with lock() and unlock() functions.
+ */
+ template <class L> class ScopedLockTemplate {
+ public:
+ ScopedLockTemplate(L& l) : mutex(l) { mutex.lock(); }
+ ~ScopedLockTemplate() { mutex.unlock(); }
+ private:
+ L& mutex;
+ };
+
+ template <class L> class ScopedUnlockTemplate {
+ public:
+ ScopedUnlockTemplate(L& l) : mutex(l) { mutex.unlock(); }
+ ~ScopedUnlockTemplate() { mutex.lock(); }
+ private:
+ L& mutex;
+ };
+
+ class Mutex {
+ public:
+ typedef ScopedLockTemplate<Mutex> ScopedLock;
+ typedef ScopedUnlockTemplate<Mutex> ScopedUnlock;
+
+ QPID_COMMON_EXTERN Mutex();
+ QPID_COMMON_EXTERN ~Mutex();
+ QPID_COMMON_EXTERN void lock();
+ QPID_COMMON_EXTERN void unlock();
+ private:
+ sys::Mutex* impl;
+ };
+ }
+}
+
+#endif
+
diff --git a/qpid/cpp/src/qpid/messaging/Connection.cpp b/qpid/cpp/src/qpid/messaging/Connection.cpp
index fde931038b..71618d1057 100644
--- a/qpid/cpp/src/qpid/messaging/Connection.cpp
+++ b/qpid/cpp/src/qpid/messaging/Connection.cpp
@@ -68,7 +68,7 @@ Connection::Connection(const std::string& url, const Variant::Map& options)
Connection::Connection()
{
Variant::Map options;
- std::string url = "amqp:tcp:127.0.0.1:5672";
+ std::string url = "127.0.0.1:5672";
PI::ctor(*this, new qpid::client::amqp0_10::ConnectionImpl(url, options));
}
@@ -90,4 +90,18 @@ std::string Connection::getAuthenticatedUsername()
{
return impl->getAuthenticatedUsername();
}
+
+void Connection::reconnect(const std::string& url)
+{
+ impl->reconnect(url);
+}
+void Connection::reconnect()
+{
+ impl->reconnect();
+}
+std::string Connection::getUrl() const
+{
+ return impl->getUrl();
+}
+
}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/ConnectionImpl.h b/qpid/cpp/src/qpid/messaging/ConnectionImpl.h
index 1e11d9a6d5..92c6d91b10 100644
--- a/qpid/cpp/src/qpid/messaging/ConnectionImpl.h
+++ b/qpid/cpp/src/qpid/messaging/ConnectionImpl.h
@@ -45,6 +45,9 @@ class ConnectionImpl : public virtual qpid::RefCounted
virtual Session getSession(const std::string& name) const = 0;
virtual void setOption(const std::string& name, const qpid::types::Variant& value) = 0;
virtual std::string getAuthenticatedUsername() = 0;
+ virtual void reconnect(const std::string& url) = 0;
+ virtual void reconnect() = 0;
+ virtual std::string getUrl() const = 0;
private:
};
}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp b/qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp
index 746666a79c..e534920876 100644
--- a/qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp
+++ b/qpid/cpp/src/qpid/messaging/ConnectionOptions.cpp
@@ -52,7 +52,7 @@ void merge(const qpid::types::Variant::List& from, std::vector<std::string>& to)
ConnectionOptions::ConnectionOptions(const std::map<std::string, qpid::types::Variant>& options)
: replaceUrls(false), reconnect(false), timeout(FOREVER), limit(-1), minReconnectInterval(0.001), maxReconnectInterval(2),
- retries(0), reconnectOnLimitExceeded(true)
+ retries(0), reconnectOnLimitExceeded(true), nestAnnotations(false)
{
for (qpid::types::Variant::Map::const_iterator i = options.begin(); i != options.end(); ++i) {
set(i->first, i->second);
@@ -115,6 +115,8 @@ void ConnectionOptions::set(const std::string& name, const qpid::types::Variant&
reconnectOnLimitExceeded = value;
} else if (name == "container-id" || name == "container_id") {
identifier = value.asString();
+ } else if (name == "nest-annotations" || name == "nest_annotations") {
+ nestAnnotations = value;
} else {
throw qpid::messaging::MessagingException(QPID_MSG("Invalid option: " << name << " not recognised"));
}
diff --git a/qpid/cpp/src/qpid/messaging/ConnectionOptions.h b/qpid/cpp/src/qpid/messaging/ConnectionOptions.h
index 7a701fce65..5942592d78 100644
--- a/qpid/cpp/src/qpid/messaging/ConnectionOptions.h
+++ b/qpid/cpp/src/qpid/messaging/ConnectionOptions.h
@@ -21,6 +21,8 @@
* under the License.
*
*/
+#include "qpid/messaging/ImportExport.h"
+
#include "qpid/client/ConnectionSettings.h"
#include <map>
#include <vector>
@@ -43,9 +45,10 @@ struct ConnectionOptions : qpid::client::ConnectionSettings
int32_t retries;
bool reconnectOnLimitExceeded;
std::string identifier;
+ bool nestAnnotations;
- ConnectionOptions(const std::map<std::string, qpid::types::Variant>&);
- void set(const std::string& name, const qpid::types::Variant& value);
+ QPID_MESSAGING_EXTERN ConnectionOptions(const std::map<std::string, qpid::types::Variant>&);
+ QPID_MESSAGING_EXTERN void set(const std::string& name, const qpid::types::Variant& value);
};
}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/Message.cpp b/qpid/cpp/src/qpid/messaging/Message.cpp
index 0f03bc8ca3..62ee93b6c2 100644
--- a/qpid/cpp/src/qpid/messaging/Message.cpp
+++ b/qpid/cpp/src/qpid/messaging/Message.cpp
@@ -31,6 +31,10 @@ using namespace qpid::types;
Message::Message(const std::string& bytes) : impl(new MessageImpl(bytes)) {}
Message::Message(const char* bytes, size_t count) : impl(new MessageImpl(bytes, count)) {}
+Message::Message(qpid::types::Variant& c) : impl(new MessageImpl(std::string()))
+{
+ setContentObject(c);
+}
Message::Message(const Message& m) : impl(new MessageImpl(*m.impl)) {}
Message::~Message() { delete impl; }
@@ -69,12 +73,20 @@ void Message::setRedelivered(bool redelivered) { impl->setRedelivered(redelivere
const Variant::Map& Message::getProperties() const { return impl->getHeaders(); }
Variant::Map& Message::getProperties() { return impl->getHeaders(); }
+void Message::setProperties(const Variant::Map& p) { getProperties() = p; }
void Message::setProperty(const std::string& k, const qpid::types::Variant& v) { impl->setHeader(k,v); }
void Message::setContent(const std::string& c) { impl->setBytes(c); }
void Message::setContent(const char* chars, size_t count) { impl->setBytes(chars, count); }
std::string Message::getContent() const { return impl->getBytes(); }
+void Message::setContentBytes(const std::string& c) { impl->setBytes(c); }
+std::string Message::getContentBytes() const { return impl->getBytes(); }
+
+qpid::types::Variant& Message::getContentObject() { return impl->getContent(); }
+void Message::setContentObject(const qpid::types::Variant& c) { impl->getContent() = c; }
+const qpid::types::Variant& Message::getContentObject() const { return impl->getContent(); }
+
const char* Message::getContentPtr() const
{
return impl->getBytes().data();
diff --git a/qpid/cpp/src/qpid/messaging/MessageImpl.cpp b/qpid/cpp/src/qpid/messaging/MessageImpl.cpp
index fc9bc5dfa1..e9232804d8 100644
--- a/qpid/cpp/src/qpid/messaging/MessageImpl.cpp
+++ b/qpid/cpp/src/qpid/messaging/MessageImpl.cpp
@@ -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,21 +30,44 @@ const std::string EMPTY_STRING = "";
using namespace qpid::types;
-MessageImpl::MessageImpl(const std::string& c) :
+MessageImpl::MessageImpl(const std::string& c) :
priority(0),
ttl(0),
durable(false),
redelivered(false),
bytes(c),
+ contentDecoded(false),
internalId(0) {}
-MessageImpl::MessageImpl(const char* chars, size_t count) :
+MessageImpl::MessageImpl(const char* chars, size_t count) :
priority(0),
ttl(0),
durable (false),
redelivered(false),
bytes(chars, count),
+ contentDecoded(false),
internalId(0) {}
+void MessageImpl::clear()
+{
+ replyTo = Address();
+ subject = std::string();
+ contentType = std::string();
+ messageId = std::string();
+ userId= std::string();
+ correlationId = std::string();
+ priority = 0;
+ ttl = 0;
+ durable = false;
+ redelivered = false;
+ headers = qpid::types::Variant::Map();
+
+ bytes = std::string();
+ content = qpid::types::Variant();
+ contentDecoded = false;
+ encoded = boost::shared_ptr<const qpid::messaging::amqp::EncodedMessage>();
+ internalId = 0;
+}
+
void MessageImpl::setReplyTo(const Address& d)
{
replyTo = d;
@@ -167,21 +190,35 @@ void MessageImpl::setBytes(const char* chars, size_t count)
bytes.assign(chars, count);
updated();
}
-void MessageImpl::appendBytes(const char* chars, size_t count)
-{
- bytes.append(chars, count);
- updated();
-}
const std::string& MessageImpl::getBytes() const
{
- if (!bytes.size() && encoded) encoded->getBody(bytes);
- return bytes;
+ if (encoded && !contentDecoded) {
+ encoded->getBody(bytes, content);
+ contentDecoded = true;
+ }
+ if (bytes.empty() && !content.isVoid()) return content.getString();
+ else return bytes;
}
std::string& MessageImpl::getBytes()
{
- if (!bytes.size() && encoded) encoded->getBody(bytes);
updated();//have to assume body may be edited, invalidating our message
- return bytes;
+ if (bytes.empty() && !content.isVoid()) return content.getString();
+ else return bytes;
+}
+
+qpid::types::Variant& MessageImpl::getContent()
+{
+ updated();//have to assume content may be edited, invalidating our message
+ return content;
+}
+
+const qpid::types::Variant& MessageImpl::getContent() const
+{
+ if (encoded && !contentDecoded) {
+ encoded->getBody(bytes, content);
+ contentDecoded = true;
+ }
+ return content;
}
void MessageImpl::setInternalId(qpid::framing::SequenceNumber i) { internalId = i; }
@@ -197,7 +234,10 @@ void MessageImpl::updated()
if (!userId.size() && encoded) encoded->getUserId(userId);
if (!correlationId.size() && encoded) encoded->getCorrelationId(correlationId);
if (!headers.size() && encoded) encoded->populate(headers);
- if (!bytes.size() && encoded) encoded->getBody(bytes);
+ if (encoded && !contentDecoded) {
+ encoded->getBody(bytes, content);
+ contentDecoded = true;
+ }
encoded.reset();
}
@@ -210,5 +250,4 @@ const MessageImpl& MessageImplAccess::get(const Message& msg)
{
return *msg.impl;
}
-
}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/MessageImpl.h b/qpid/cpp/src/qpid/messaging/MessageImpl.h
index 915c790153..647972de16 100644
--- a/qpid/cpp/src/qpid/messaging/MessageImpl.h
+++ b/qpid/cpp/src/qpid/messaging/MessageImpl.h
@@ -10,9 +10,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,6 +21,9 @@
* under the License.
*
*/
+
+#include "qpid/messaging/ImportExport.h"
+
#include "qpid/messaging/Address.h"
#include "qpid/types/Variant.h"
#include "qpid/framing/SequenceNumber.h"
@@ -47,6 +50,8 @@ class MessageImpl
mutable qpid::types::Variant::Map headers;
mutable std::string bytes;
+ mutable qpid::types::Variant content;
+ mutable bool contentDecoded;
boost::shared_ptr<const qpid::messaging::amqp::EncodedMessage> encoded;
qpid::framing::SequenceNumber internalId;
@@ -56,43 +61,45 @@ class MessageImpl
MessageImpl(const std::string& c);
MessageImpl(const char* chars, size_t count);
+ void clear();
void setReplyTo(const Address& d);
- const Address& getReplyTo() const;
+ QPID_MESSAGING_EXTERN const Address& getReplyTo() const;
void setSubject(const std::string& s);
- const std::string& getSubject() const;
+ QPID_MESSAGING_EXTERN const std::string& getSubject() const;
void setContentType(const std::string& s);
- const std::string& getContentType() const;
+ QPID_MESSAGING_EXTERN const std::string& getContentType() const;
void setMessageId(const std::string&);
- const std::string& getMessageId() const;
+ QPID_MESSAGING_EXTERN const std::string& getMessageId() const;
void setUserId(const std::string& );
- const std::string& getUserId() const;
+ QPID_MESSAGING_EXTERN const std::string& getUserId() const;
void setCorrelationId(const std::string& );
- const std::string& getCorrelationId() const;
+ QPID_MESSAGING_EXTERN const std::string& getCorrelationId() const;
void setPriority(uint8_t);
- uint8_t getPriority() const;
+ QPID_MESSAGING_EXTERN uint8_t getPriority() const;
void setTtl(uint64_t);
- uint64_t getTtl() const;
+ QPID_MESSAGING_EXTERN uint64_t getTtl() const;
void setDurable(bool);
- bool isDurable() const;
+ QPID_MESSAGING_EXTERN bool isDurable() const;
void setRedelivered(bool);
- bool isRedelivered() const;
+ QPID_MESSAGING_EXTERN bool isRedelivered() const;
- const qpid::types::Variant::Map& getHeaders() const;
+ QPID_MESSAGING_EXTERN const qpid::types::Variant::Map& getHeaders() const;
qpid::types::Variant::Map& getHeaders();
void setHeader(const std::string& key, const qpid::types::Variant& val);
void setBytes(const std::string& bytes);
void setBytes(const char* chars, size_t count);
- void appendBytes(const char* chars, size_t count);
- const std::string& getBytes() const;
+ QPID_MESSAGING_EXTERN const std::string& getBytes() const;
std::string& getBytes();
+ qpid::types::Variant& getContent();
+ QPID_MESSAGING_EXTERN const qpid::types::Variant& getContent() const;
- void setInternalId(qpid::framing::SequenceNumber id);
- qpid::framing::SequenceNumber getInternalId();
+ QPID_MESSAGING_EXTERN void setInternalId(qpid::framing::SequenceNumber id);
+ QPID_MESSAGING_EXTERN qpid::framing::SequenceNumber getInternalId();
void setEncoded(boost::shared_ptr<const qpid::messaging::amqp::EncodedMessage> e) { encoded = e; }
boost::shared_ptr<const qpid::messaging::amqp::EncodedMessage> getEncoded() const { return encoded; }
};
@@ -106,8 +113,8 @@ class Message;
*/
struct MessageImplAccess
{
- static MessageImpl& get(Message&);
- static const MessageImpl& get(const Message&);
+ QPID_MESSAGING_EXTERN static MessageImpl& get(Message&);
+ QPID_MESSAGING_EXTERN static const MessageImpl& get(const Message&);
};
}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/ProtocolRegistry.h b/qpid/cpp/src/qpid/messaging/ProtocolRegistry.h
index bcb62248a5..25e8bd4ec8 100644
--- a/qpid/cpp/src/qpid/messaging/ProtocolRegistry.h
+++ b/qpid/cpp/src/qpid/messaging/ProtocolRegistry.h
@@ -21,6 +21,9 @@
* under the License.
*
*/
+
+#include "qpid/messaging/ImportExport.h"
+
#include "qpid/types/Variant.h"
namespace qpid {
@@ -34,7 +37,7 @@ class ProtocolRegistry
public:
typedef ConnectionImpl* Factory(const std::string& url, const qpid::types::Variant::Map& options);
static ConnectionImpl* create(const std::string& url, const qpid::types::Variant::Map& options);
- static void add(const std::string& name, Factory* factory);
+ QPID_MESSAGING_EXTERN static void add(const std::string& name, Factory* factory);
private:
};
}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/Receiver.cpp b/qpid/cpp/src/qpid/messaging/Receiver.cpp
index c45ebd6760..f60e5f55b3 100644
--- a/qpid/cpp/src/qpid/messaging/Receiver.cpp
+++ b/qpid/cpp/src/qpid/messaging/Receiver.cpp
@@ -21,6 +21,7 @@
#include "qpid/messaging/Receiver.h"
#include "qpid/messaging/Address.h"
#include "qpid/messaging/Message.h"
+#include "qpid/messaging/MessageImpl.h"
#include "qpid/messaging/ReceiverImpl.h"
#include "qpid/messaging/Session.h"
#include "qpid/messaging/PrivateImplRef.h"
@@ -36,7 +37,11 @@ Receiver::~Receiver() { PI::dtor(*this); }
Receiver& Receiver::operator=(const Receiver& s) { return PI::assign(*this, s); }
bool Receiver::get(Message& message, Duration timeout) { return impl->get(message, timeout); }
Message Receiver::get(Duration timeout) { return impl->get(timeout); }
-bool Receiver::fetch(Message& message, Duration timeout) { return impl->fetch(message, timeout); }
+bool Receiver::fetch(Message& message, Duration timeout)
+{
+ MessageImplAccess::get(message).clear();
+ return impl->fetch(message, timeout);
+}
Message Receiver::fetch(Duration timeout) { return impl->fetch(timeout); }
void Receiver::setCapacity(uint32_t c) { impl->setCapacity(c); }
uint32_t Receiver::getCapacity() { return impl->getCapacity(); }
diff --git a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp
index 9ecb46d872..beac50cdac 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.cpp
@@ -57,6 +57,7 @@ const std::string PROPERTIES("properties");
const std::string MODE("mode");
const std::string BROWSE("browse");
const std::string CONSUME("consume");
+const std::string TIMEOUT("timeout");
const std::string TYPE("type");
const std::string TOPIC("topic");
@@ -69,6 +70,14 @@ const std::string FILTER("filter");
const std::string DESCRIPTOR("descriptor");
const std::string VALUE("value");
const std::string SUBJECT_FILTER("subject-filter");
+const std::string SOURCE("sender-source");
+const std::string TARGET("receiver-target");
+
+//reliability options:
+const std::string UNRELIABLE("unreliable");
+const std::string AT_MOST_ONCE("at-most-once");
+const std::string AT_LEAST_ONCE("at-least-once");
+const std::string EXACTLY_ONCE("exactly-once");
//distribution modes:
const std::string MOVE("move");
@@ -83,12 +92,11 @@ const std::string DELETE_IF_EMPTY("delete-if-empty");
const std::string DELETE_IF_UNUSED_AND_EMPTY("delete-if-unused-and-empty");
const std::string CREATE_ON_DEMAND("create-on-demand");
-const std::string DUMMY(".");
-
const std::string X_DECLARE("x-declare");
const std::string X_BINDINGS("x-bindings");
const std::string X_SUBSCRIBE("x-subscribe");
const std::string ARGUMENTS("arguments");
+const std::string EXCHANGE_TYPE("exchange-type");
const std::vector<std::string> RECEIVER_MODES = boost::assign::list_of<std::string>(ALWAYS) (RECEIVER);
const std::vector<std::string> SENDER_MODES = boost::assign::list_of<std::string>(ALWAYS) (SENDER);
@@ -144,6 +152,16 @@ bool test(const Variant::Map& options, const std::string& name)
}
}
+template <typename T> T get(const Variant::Map& options, const std::string& name, T defaultValue)
+{
+ Variant::Map::const_iterator j = options.find(name);
+ if (j == options.end()) {
+ return defaultValue;
+ } else {
+ return j->second;
+ }
+}
+
bool bind(const Variant::Map& options, const std::string& name, std::string& variable)
{
Variant::Map::const_iterator j = options.find(name);
@@ -208,6 +226,18 @@ void flatten(Variant::Map& base, const std::string& nested)
base.erase(i);
}
}
+bool replace(Variant::Map& map, const std::string& original, const std::string& desired)
+{
+ Variant::Map::iterator i = map.find(original);
+ if (i != map.end()) {
+ map[desired] = i->second;
+ map.erase(original);
+ return true;
+ } else {
+ return false;
+ }
+}
+
void write(pn_data_t* data, const Variant& value);
void write(pn_data_t* data, const Variant::Map& map)
@@ -260,6 +290,8 @@ void write(pn_data_t* data, const Variant& value)
break;
}
}
+const uint32_t DEFAULT_DURABLE_TIMEOUT(15*60);//15 minutes
+const uint32_t DEFAULT_TIMEOUT(0);
}
AddressHelper::AddressHelper(const Address& address) :
@@ -268,6 +300,7 @@ AddressHelper::AddressHelper(const Address& address) :
type(address.getType()),
durableNode(false),
durableLink(false),
+ timeout(0),
browse(false)
{
verifier.verify(address);
@@ -279,13 +312,14 @@ AddressHelper::AddressHelper(const Address& address) :
bind(address, LINK, link);
bind(node, PROPERTIES, properties);
bind(node, CAPABILITIES, capabilities);
+ bind(link, RELIABILITY, reliability);
durableNode = test(node, DURABLE);
durableLink = test(link, DURABLE);
+ timeout = get(link, TIMEOUT, durableLink ? DEFAULT_DURABLE_TIMEOUT : DEFAULT_TIMEOUT);
std::string mode;
if (bind(address, MODE, mode)) {
if (mode == BROWSE) {
browse = true;
- throw qpid::messaging::AddressError("Browse mode not yet supported over AMQP 1.0.");
} else if (mode != CONSUME) {
throw qpid::messaging::AddressError("Invalid value for mode; must be 'browse' or 'consume'.");
}
@@ -310,6 +344,7 @@ AddressHelper::AddressHelper(const Address& address) :
Variant::Map::iterator i = node.find(X_DECLARE);
if (i != node.end()) {
Variant::Map x_declare = i->second.asMap();
+ replace(x_declare, TYPE, EXCHANGE_TYPE);
flatten(x_declare, ARGUMENTS);
add(properties, x_declare);
node.erase(i);
@@ -391,16 +426,23 @@ void AddressHelper::checkAssertion(pn_terminus_t* terminus, CheckMode mode)
QPID_LOG(debug, "checking assertions: " << capabilities);
//ensure all desired capabilities have been offered
std::set<std::string> desired;
- if (type.size()) desired.insert(type);
- if (durableNode) desired.insert(DURABLE);
for (Variant::List::const_iterator i = capabilities.begin(); i != capabilities.end(); ++i) {
- desired.insert(i->asString());
+ if (*i != CREATE_ON_DEMAND) desired.insert(i->asString());
}
pn_data_t* data = pn_terminus_capabilities(terminus);
- while (pn_data_next(data)) {
- pn_bytes_t c = pn_data_get_symbol(data);
- std::string s(c.start, c.size);
- desired.erase(s);
+ if (pn_data_next(data)) {
+ pn_type_t type = pn_data_type(data);
+ if (type == PN_ARRAY) {
+ pn_data_enter(data);
+ while (pn_data_next(data)) {
+ desired.erase(convert(pn_data_get_symbol(data)));
+ }
+ pn_data_exit(data);
+ } else if (type == PN_SYMBOL) {
+ desired.erase(convert(pn_data_get_symbol(data)));
+ } else {
+ QPID_LOG(error, "Skipping capabilities field of type " << pn_type_name(type));
+ }
}
if (desired.size()) {
@@ -492,6 +534,11 @@ bool AddressHelper::enabled(const std::string& policy, CheckMode mode) const
return result;
}
+bool AddressHelper::isUnreliable() const
+{
+ return reliability == AT_MOST_ONCE || reliability == UNRELIABLE;
+}
+
const qpid::types::Variant::Map& AddressHelper::getNodeProperties() const
{
return node;
@@ -501,12 +548,32 @@ const qpid::types::Variant::Map& AddressHelper::getLinkProperties() const
return link;
}
-void AddressHelper::configure(pn_terminus_t* terminus, CheckMode mode)
+bool AddressHelper::getLinkSource(std::string& out) const
+{
+ return getLinkOption(SOURCE, out);
+}
+
+bool AddressHelper::getLinkTarget(std::string& out) const
+{
+ return getLinkOption(TARGET, out);
+}
+
+bool AddressHelper::getLinkOption(const std::string& name, std::string& out) const
+{
+ qpid::types::Variant::Map::const_iterator i = link.find(name);
+ if (i != link.end()) {
+ out = i->second.asString();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void AddressHelper::configure(pn_link_t* link, pn_terminus_t* terminus, CheckMode mode)
{
bool createOnDemand(false);
if (isTemporary) {
//application expects a name to be generated
- pn_terminus_set_address(terminus, DUMMY.c_str());//workaround for PROTON-277
pn_terminus_set_dynamic(terminus, true);
setNodeProperties(terminus);
} else {
@@ -517,43 +584,57 @@ void AddressHelper::configure(pn_terminus_t* terminus, CheckMode mode)
createOnDemand = true;
}
}
+
setCapabilities(terminus, createOnDemand);
if (durableLink) {
pn_terminus_set_durability(terminus, PN_DELIVERIES);
}
- if (mode == FOR_RECEIVER && browse) {
- //when PROTON-139 is resolved, set the required delivery-mode
- }
- //set filter(s):
- if (mode == FOR_RECEIVER && !filters.empty()) {
- pn_data_t* filter = pn_terminus_filter(terminus);
- pn_data_put_map(filter);
- pn_data_enter(filter);
- for (std::vector<Filter>::const_iterator i = filters.begin(); i != filters.end(); ++i) {
- pn_data_put_symbol(filter, convert(i->name));
- pn_data_put_described(filter);
+ if (mode == FOR_RECEIVER) {
+ if (timeout) pn_terminus_set_timeout(terminus, timeout);
+ if (browse) {
+ pn_terminus_set_distribution_mode(terminus, PN_DIST_MODE_COPY);
+ }
+ //set filter(s):
+ if (!filters.empty()) {
+ pn_data_t* filter = pn_terminus_filter(terminus);
+ pn_data_put_map(filter);
pn_data_enter(filter);
- if (i->descriptorSymbol.size()) {
- pn_data_put_symbol(filter, convert(i->descriptorSymbol));
- } else {
- pn_data_put_ulong(filter, i->descriptorCode);
+ for (std::vector<Filter>::const_iterator i = filters.begin(); i != filters.end(); ++i) {
+ pn_data_put_symbol(filter, convert(i->name));
+ pn_data_put_described(filter);
+ pn_data_enter(filter);
+ if (i->descriptorSymbol.size()) {
+ pn_data_put_symbol(filter, convert(i->descriptorSymbol));
+ } else {
+ pn_data_put_ulong(filter, i->descriptorCode);
+ }
+ write(filter, i->value);
+ pn_data_exit(filter);
}
- write(filter, i->value);
pn_data_exit(filter);
}
- pn_data_exit(filter);
}
-
+ if (isUnreliable()) {
+ pn_link_set_snd_settle_mode(link, PN_SND_SETTLED);
+ }
}
void AddressHelper::setCapabilities(pn_terminus_t* terminus, bool create)
{
+ if (create) capabilities.push_back(CREATE_ON_DEMAND);
+ if (!type.empty()) capabilities.push_back(type);
+ if (durableNode) capabilities.push_back(DURABLE);
+
pn_data_t* data = pn_terminus_capabilities(terminus);
- if (create) pn_data_put_symbol(data, convert(CREATE_ON_DEMAND));
- if (type.size()) pn_data_put_symbol(data, convert(type));
- if (durableNode) pn_data_put_symbol(data, convert(DURABLE));
- for (qpid::types::Variant::List::const_iterator i = capabilities.begin(); i != capabilities.end(); ++i) {
- pn_data_put_symbol(data, convert(i->asString()));
+ if (capabilities.size() == 1) {
+ pn_data_put_symbol(data, convert(capabilities.front().asString()));
+ } else if (capabilities.size() > 1) {
+ pn_data_put_array(data, false, PN_SYMBOL);
+ pn_data_enter(data);
+ for (qpid::types::Variant::List::const_iterator i = capabilities.begin(); i != capabilities.end(); ++i) {
+ pn_data_put_symbol(data, convert(i->asString()));
+ }
+ pn_data_exit(data);
}
}
std::string AddressHelper::getLinkName(const Address& address)
@@ -632,6 +713,9 @@ Verifier::Verifier()
link[NAME] = true;
link[DURABLE] = true;
link[RELIABILITY] = true;
+ link[TIMEOUT] = true;
+ link[SOURCE] = true;
+ link[TARGET] = true;
link[X_SUBSCRIBE] = true;
link[X_DECLARE] = true;
link[X_BINDINGS] = true;
diff --git a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h
index 4608981a69..3ee58cad8d 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/AddressHelper.h
@@ -24,6 +24,7 @@
#include "qpid/types/Variant.h"
#include <vector>
+struct pn_link_t;
struct pn_terminus_t;
namespace qpid {
@@ -36,10 +37,13 @@ class AddressHelper
enum CheckMode {FOR_RECEIVER, FOR_SENDER};
AddressHelper(const Address& address);
- void configure(pn_terminus_t* terminus, CheckMode mode);
+ void configure(pn_link_t* link, pn_terminus_t* terminus, CheckMode mode);
void checkAssertion(pn_terminus_t* terminus, CheckMode mode);
+ bool isUnreliable() const;
const qpid::types::Variant::Map& getNodeProperties() const;
+ bool getLinkSource(std::string& out) const;
+ bool getLinkTarget(std::string& out) const;
const qpid::types::Variant::Map& getLinkProperties() const;
static std::string getLinkName(const Address& address);
private:
@@ -66,8 +70,10 @@ class AddressHelper
qpid::types::Variant::List capabilities;
std::string name;
std::string type;
+ std::string reliability;
bool durableNode;
bool durableLink;
+ uint32_t timeout;
bool browse;
std::vector<Filter> filters;
@@ -82,6 +88,7 @@ class AddressHelper
void addFilters(const qpid::types::Variant::List&);
void confirmFilter(const std::string& descriptor);
void confirmFilter(uint64_t descriptor);
+ bool getLinkOption(const std::string& name, std::string& out) const;
};
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
index 72bba608d1..dba5cb1e1c 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.cpp
@@ -45,18 +45,17 @@ namespace qpid {
namespace messaging {
namespace amqp {
-ConnectionContext::ConnectionContext(const std::string& u, const qpid::types::Variant::Map& o)
+ConnectionContext::ConnectionContext(const std::string& url, const qpid::types::Variant::Map& o)
: qpid::messaging::ConnectionOptions(o),
- url(u, protocol.empty() ? qpid::Address::TCP : protocol),
engine(pn_transport()),
connection(pn_connection()),
//note: disabled read/write of header as now handled by engine
writeHeader(false),
readHeader(false),
haveOutput(false),
- state(DISCONNECTED),
- codecSwitch(*this)
+ state(DISCONNECTED)
{
+ urls.insert(urls.begin(), url);
if (pn_transport_bind(engine, connection)) {
//error
}
@@ -77,84 +76,28 @@ ConnectionContext::~ConnectionContext()
pn_connection_free(connection);
}
-namespace {
-const std::string COLON(":");
-}
-void ConnectionContext::open()
-{
- qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
- if (state != DISCONNECTED) throw qpid::messaging::ConnectionError("Connection was already opened!");
- if (!driver) driver = DriverImpl::getDefault();
- if (url.getUser().size()) username = url.getUser();
- if (url.getPass().size()) password = url.getPass();
-
- for (Url::const_iterator i = url.begin(); state != CONNECTED && i != url.end(); ++i) {
- transport = driver->getTransport(i->protocol, *this);
- std::stringstream port;
- port << i->port;
- id = i->host + COLON + port.str();
- if (useSasl()) {
- sasl = std::auto_ptr<Sasl>(new Sasl(id, *this, i->host));
- }
- state = CONNECTING;
- try {
- QPID_LOG(debug, id << " Connecting ...");
- transport->connect(i->host, port.str());
- } catch (const std::exception& e) {
- QPID_LOG(info, id << " Error while connecting: " << e.what());
- }
- while (state == CONNECTING) {
- lock.wait();
- }
- if (state == DISCONNECTED) {
- QPID_LOG(debug, id << " Failed to connect");
- transport = boost::shared_ptr<Transport>();
- } else {
- QPID_LOG(debug, id << " Connected");
- }
- }
-
- if (state != CONNECTED) throw qpid::messaging::TransportFailure(QPID_MSG("Could not connect to " << url));
-
- if (sasl.get()) {
- wakeupDriver();
- while (!sasl->authenticated()) {
- QPID_LOG(debug, id << " Waiting to be authenticated...");
- wait();
- }
- QPID_LOG(debug, id << " Authenticated");
- }
-
- QPID_LOG(debug, id << " Opening...");
- setProperties();
- pn_connection_open(connection);
- wakeupDriver(); //want to write
- while (pn_connection_state(connection) & PN_REMOTE_UNINIT) {
- wait();
- }
- if (!(pn_connection_state(connection) & PN_REMOTE_ACTIVE)) {
- throw qpid::messaging::ConnectionError("Failed to open connection");
- }
- QPID_LOG(debug, id << " Opened");
-}
-
bool ConnectionContext::isOpen() const
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
- return pn_connection_state(connection) & (PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE);
+ return state == CONNECTED && pn_connection_state(connection) & (PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE);
}
void ConnectionContext::endSession(boost::shared_ptr<SessionContext> ssn)
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
- //wait for outstanding sends to settle
- while (!ssn->settled()) {
- QPID_LOG(debug, "Waiting for sends to settle before closing");
- wait(ssn);//wait until message has been confirmed
+ if (pn_session_state(ssn->session) & PN_REMOTE_ACTIVE) {
+ //wait for outstanding sends to settle
+ while (!ssn->settled()) {
+ QPID_LOG(debug, "Waiting for sends to settle before closing");
+ wait(ssn);//wait until message has been confirmed
+ }
+ }
+
+ if (pn_session_state(ssn->session) & PN_REMOTE_ACTIVE) {
+ pn_session_close(ssn->session);
}
+ sessions.erase(ssn->getName());
- pn_session_close(ssn->session);
- //TODO: need to destroy session and remove context from map
wakeupDriver();
}
@@ -260,6 +203,7 @@ bool ConnectionContext::get(boost::shared_ptr<SessionContext> ssn, boost::shared
if (current) {
qpid::messaging::MessageImpl& impl = MessageImplAccess::get(message);
boost::shared_ptr<EncodedMessage> encoded(new EncodedMessage(pn_delivery_pending(current)));
+ encoded->setNestAnnotationsOption(nestAnnotations);
ssize_t read = pn_link_recv(lnk->receiver, encoded->getData(), encoded->getSize());
if (read < 0) throw qpid::messaging::MessagingException("Failed to read message");
encoded->trim((size_t) read);
@@ -290,55 +234,61 @@ void ConnectionContext::acknowledge(boost::shared_ptr<SessionContext> ssn, qpid:
wakeupDriver();
}
+void ConnectionContext::detach(boost::shared_ptr<SessionContext> ssn, boost::shared_ptr<SenderContext> lnk)
+{
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
+ if (pn_link_state(lnk->sender) & PN_LOCAL_ACTIVE) {
+ lnk->close();
+ }
+ wakeupDriver();
+ while (pn_link_state(lnk->sender) & PN_REMOTE_ACTIVE) {
+ wait();
+ }
+ ssn->removeSender(lnk->getName());
+}
+
+void ConnectionContext::detach(boost::shared_ptr<SessionContext> ssn, boost::shared_ptr<ReceiverContext> lnk)
+{
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
+ if (pn_link_state(lnk->receiver) & PN_LOCAL_ACTIVE) {
+ lnk->close();
+ }
+ wakeupDriver();
+ while (pn_link_state(lnk->receiver) & PN_REMOTE_ACTIVE) {
+ wait();
+ }
+ ssn->removeReceiver(lnk->getName());
+}
void ConnectionContext::attach(boost::shared_ptr<SessionContext> ssn, boost::shared_ptr<SenderContext> lnk)
{
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
lnk->configure();
- attach(ssn->session, (pn_link_t*) lnk->sender);
- pn_terminus_t* t = pn_link_remote_target(lnk->sender);
- if (!pn_terminus_get_address(t)) {
- std::string msg("No such target : ");
- msg += lnk->getTarget();
- QPID_LOG(debug, msg);
- throw qpid::messaging::NotFound(msg);
- } else if (AddressImpl::isTemporary(lnk->address)) {
- lnk->address.setName(pn_terminus_get_address(t));
- QPID_LOG(debug, "Dynamic target name set to " << lnk->address.getName());
- }
- lnk->verify(t);
+ attach(ssn, lnk->sender);
checkClosed(ssn, lnk);
+ lnk->verify();
QPID_LOG(debug, "Attach succeeded to " << lnk->getTarget());
}
void ConnectionContext::attach(boost::shared_ptr<SessionContext> ssn, boost::shared_ptr<ReceiverContext> lnk)
{
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
lnk->configure();
- attach(ssn->session, lnk->receiver, lnk->capacity);
- pn_terminus_t* s = pn_link_remote_source(lnk->receiver);
- if (!pn_terminus_get_address(s)) {
- std::string msg("No such source : ");
- msg += lnk->getSource();
- QPID_LOG(debug, msg);
- throw qpid::messaging::NotFound(msg);
- } else if (AddressImpl::isTemporary(lnk->address)) {
- lnk->address.setName(pn_terminus_get_address(s));
- QPID_LOG(debug, "Dynamic source name set to " << lnk->address.getName());
- }
- lnk->verify(s);
+ attach(ssn, lnk->receiver, lnk->capacity);
checkClosed(ssn, lnk);
+ lnk->verify();
QPID_LOG(debug, "Attach succeeded from " << lnk->getSource());
}
-void ConnectionContext::attach(pn_session_t* /*session*/, pn_link_t* link, int credit)
+void ConnectionContext::attach(boost::shared_ptr<SessionContext> ssn, pn_link_t* link, int credit)
{
- qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
pn_link_open(link);
QPID_LOG(debug, "Link attach sent for " << link << ", state=" << pn_link_state(link));
if (credit) pn_link_flow(link, credit);
wakeupDriver();
while (pn_link_state(link) & PN_REMOTE_UNINIT) {
QPID_LOG(debug, "Waiting for confirmation of link attach for " << link << ", state=" << pn_link_state(link) << "...");
- wait();
+ wait(ssn);
}
}
@@ -347,12 +297,12 @@ void ConnectionContext::send(boost::shared_ptr<SessionContext> ssn, boost::share
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
checkClosed(ssn);
SenderContext::Delivery* delivery(0);
- while (!(delivery = snd->send(message))) {
+ while (!snd->send(message, &delivery)) {
QPID_LOG(debug, "Waiting for capacity...");
wait(ssn, snd);//wait for capacity
}
wakeupDriver();
- if (sync) {
+ if (sync && delivery) {
while (!delivery->accepted()) {
QPID_LOG(debug, "Waiting for confirmation...");
wait(ssn, snd);//wait until message has been confirmed
@@ -427,10 +377,32 @@ pn_state_t REQUIRES_CLOSE = PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED;
pn_state_t IS_CLOSED = PN_LOCAL_CLOSED | PN_REMOTE_CLOSED;
}
+void ConnectionContext::reset()
+{
+ pn_transport_free(engine);
+ pn_connection_free(connection);
+
+ engine = pn_transport();
+ connection = pn_connection();
+ pn_connection_set_container(connection, identifier.c_str());
+ bool enableTrace(false);
+ QPID_LOG_TEST_CAT(trace, protocol, enableTrace);
+ if (enableTrace) pn_transport_trace(engine, PN_TRACE_FRM);
+ for (SessionMap::iterator i = sessions.begin(); i != sessions.end(); ++i) {
+ i->second->reset(connection);
+ }
+ pn_transport_bind(engine, connection);
+}
+
void ConnectionContext::check()
{
if (state == DISCONNECTED) {
- throw qpid::messaging::TransportFailure("Disconnected");
+ if (ConnectionOptions::reconnect) {
+ reset();
+ autoconnect();
+ } else {
+ throw qpid::messaging::TransportFailure("Disconnected (reconnect disabled)");
+ }
}
if ((pn_connection_state(connection) & REQUIRES_CLOSE) == REQUIRES_CLOSE) {
pn_connection_close(connection);
@@ -480,9 +452,17 @@ void ConnectionContext::waitUntil(boost::shared_ptr<SessionContext> ssn, boost::
}
void ConnectionContext::checkClosed(boost::shared_ptr<SessionContext> ssn)
{
+ check();
if ((pn_session_state(ssn->session) & REQUIRES_CLOSE) == REQUIRES_CLOSE) {
+ pn_condition_t* error = pn_session_remote_condition(ssn->session);
+ std::stringstream text;
+ if (pn_condition_is_set(error)) {
+ text << "Session ended by peer with " << pn_condition_get_name(error) << ": " << pn_condition_get_description(error);
+ } else {
+ text << "Session ended by peer";
+ }
pn_session_close(ssn->session);
- throw qpid::messaging::SessionError("Session ended by peer");
+ throw qpid::messaging::SessionError(text.str());
} else if ((pn_session_state(ssn->session) & IS_CLOSED) == IS_CLOSED) {
throw qpid::messaging::SessionError("Session has ended");
}
@@ -513,6 +493,31 @@ void ConnectionContext::checkClosed(boost::shared_ptr<SessionContext> ssn, pn_li
throw qpid::messaging::LinkError("Link is not attached");
}
}
+
+void ConnectionContext::restartSession(boost::shared_ptr<SessionContext> s)
+{
+ pn_session_open(s->session);
+ wakeupDriver();
+ while (pn_session_state(s->session) & PN_REMOTE_UNINIT) {
+ wait();
+ }
+
+ for (SessionContext::SenderMap::iterator i = s->senders.begin(); i != s->senders.end(); ++i) {
+ QPID_LOG(debug, id << " reattaching sender " << i->first);
+ attach(s, i->second->sender);
+ i->second->verify();
+ QPID_LOG(debug, id << " sender " << i->first << " reattached");
+ i->second->resend();
+ }
+ for (SessionContext::ReceiverMap::iterator i = s->receivers.begin(); i != s->receivers.end(); ++i) {
+ QPID_LOG(debug, id << " reattaching receiver " << i->first);
+ attach(s, i->second->receiver, i->second->capacity);
+ i->second->verify();
+ QPID_LOG(debug, id << " receiver " << i->first << " reattached");
+ }
+ wakeupDriver();
+}
+
boost::shared_ptr<SessionContext> ConnectionContext::newSession(bool transactional, const std::string& n)
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
@@ -521,13 +526,14 @@ boost::shared_ptr<SessionContext> ConnectionContext::newSession(bool transaction
SessionMap::const_iterator i = sessions.find(name);
if (i == sessions.end()) {
boost::shared_ptr<SessionContext> s(new SessionContext(connection));
+ s->setName(name);
s->session = pn_session(connection);
pn_session_open(s->session);
- sessions[name] = s;
wakeupDriver();
while (pn_session_state(s->session) & PN_REMOTE_UNINIT) {
wait();
}
+ sessions[name] = s;
return s;
} else {
throw qpid::messaging::KeyError(std::string("Session already exists: ") + name);
@@ -554,7 +560,7 @@ std::string ConnectionContext::getAuthenticatedUsername()
return sasl.get() ? sasl->getAuthenticatedUsername() : std::string();
}
-std::size_t ConnectionContext::decode(const char* buffer, std::size_t size)
+std::size_t ConnectionContext::decodePlain(const char* buffer, std::size_t size)
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
QPID_LOG(trace, id << " decode(" << size << ")");
@@ -584,7 +590,7 @@ std::size_t ConnectionContext::decode(const char* buffer, std::size_t size)
}
}
-std::size_t ConnectionContext::encode(char* buffer, std::size_t size)
+std::size_t ConnectionContext::encodePlain(char* buffer, std::size_t size)
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
QPID_LOG(trace, id << " encode(" << size << ")");
@@ -611,7 +617,7 @@ std::size_t ConnectionContext::encode(char* buffer, std::size_t size)
return 0;
}
}
-bool ConnectionContext::canEncode()
+bool ConnectionContext::canEncodePlain()
{
qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
return haveOutput && state == CONNECTED;
@@ -685,47 +691,46 @@ bool ConnectionContext::useSasl()
qpid::sys::Codec& ConnectionContext::getCodec()
{
- return codecSwitch;
+ return *this;
}
-ConnectionContext::CodecSwitch::CodecSwitch(ConnectionContext& p) : parent(p) {}
-std::size_t ConnectionContext::CodecSwitch::decode(const char* buffer, std::size_t size)
+std::size_t ConnectionContext::decode(const char* buffer, std::size_t size)
{
- qpid::sys::ScopedLock<qpid::sys::Monitor> l(parent.lock);
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
size_t decoded = 0;
- if (parent.sasl.get() && !parent.sasl->authenticated()) {
- decoded = parent.sasl->decode(buffer, size);
- if (!parent.sasl->authenticated()) return decoded;
+ if (sasl.get() && !sasl->authenticated()) {
+ decoded = sasl->decode(buffer, size);
+ if (!sasl->authenticated()) return decoded;
}
if (decoded < size) {
- if (parent.sasl.get() && parent.sasl->getSecurityLayer()) decoded += parent.sasl->getSecurityLayer()->decode(buffer+decoded, size-decoded);
- else decoded += parent.decode(buffer+decoded, size-decoded);
+ if (sasl.get() && sasl->getSecurityLayer()) decoded += sasl->getSecurityLayer()->decode(buffer+decoded, size-decoded);
+ else decoded += decodePlain(buffer+decoded, size-decoded);
}
return decoded;
}
-std::size_t ConnectionContext::CodecSwitch::encode(char* buffer, std::size_t size)
+std::size_t ConnectionContext::encode(char* buffer, std::size_t size)
{
- qpid::sys::ScopedLock<qpid::sys::Monitor> l(parent.lock);
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
size_t encoded = 0;
- if (parent.sasl.get() && parent.sasl->canEncode()) {
- encoded += parent.sasl->encode(buffer, size);
- if (!parent.sasl->authenticated()) return encoded;
+ if (sasl.get() && sasl->canEncode()) {
+ encoded += sasl->encode(buffer, size);
+ if (!sasl->authenticated()) return encoded;
}
if (encoded < size) {
- if (parent.sasl.get() && parent.sasl->getSecurityLayer()) encoded += parent.sasl->getSecurityLayer()->encode(buffer+encoded, size-encoded);
- else encoded += parent.encode(buffer+encoded, size-encoded);
+ if (sasl.get() && sasl->getSecurityLayer()) encoded += sasl->getSecurityLayer()->encode(buffer+encoded, size-encoded);
+ else encoded += encodePlain(buffer+encoded, size-encoded);
}
return encoded;
}
-bool ConnectionContext::CodecSwitch::canEncode()
+bool ConnectionContext::canEncode()
{
- qpid::sys::ScopedLock<qpid::sys::Monitor> l(parent.lock);
- if (parent.sasl.get()) {
- if (parent.sasl->canEncode()) return true;
- else if (!parent.sasl->authenticated()) return false;
- else if (parent.sasl->getSecurityLayer()) return parent.sasl->getSecurityLayer()->canEncode();
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
+ if (sasl.get()) {
+ if (sasl->canEncode()) return true;
+ else if (!sasl->authenticated()) return false;
+ else if (sasl->getSecurityLayer()) return sasl->getSecurityLayer()->canEncode();
}
- return parent.canEncode();
+ return canEncodePlain();
}
namespace {
@@ -742,10 +747,6 @@ pn_bytes_t convert(const std::string& s)
}
void ConnectionContext::setProperties()
{
- /**
- * Enable when proton 0.5 is released and qpidc has been updated
- * to use it
- *
pn_data_t* data = pn_connection_properties(connection);
pn_data_put_map(data);
pn_data_enter(data);
@@ -760,7 +761,206 @@ void ConnectionContext::setProperties()
pn_data_put_symbol(data, convert(CLIENT_PPID));
pn_data_put_int(data, sys::SystemInfo::getParentProcessId());
pn_data_exit(data);
- **/
}
+const qpid::sys::SecuritySettings* ConnectionContext::getTransportSecuritySettings()
+{
+ return transport ? transport->getSecuritySettings() : 0;
+}
+
+void ConnectionContext::open()
+{
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
+ if (state != DISCONNECTED) throw qpid::messaging::ConnectionError("Connection was already opened!");
+ if (!driver) driver = DriverImpl::getDefault();
+
+ autoconnect();
+}
+
+
+namespace {
+std::string asString(const std::vector<std::string>& v) {
+ std::stringstream os;
+ os << "[";
+ for(std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i ) {
+ if (i != v.begin()) os << ", ";
+ os << *i;
+ }
+ os << "]";
+ return os.str();
+}
+double FOREVER(std::numeric_limits<double>::max());
+bool expired(const sys::AbsTime& start, double timeout)
+{
+ if (timeout == 0) return true;
+ if (timeout == FOREVER) return false;
+ qpid::sys::Duration used(start, qpid::sys::now());
+ qpid::sys::Duration allowed((int64_t)(timeout*qpid::sys::TIME_SEC));
+ return allowed < used;
+}
+const std::string COLON(":");
+}
+
+void ConnectionContext::autoconnect()
+{
+ qpid::sys::AbsTime started(qpid::sys::now());
+ QPID_LOG(debug, "Starting connection, urls=" << asString(urls));
+ for (double i = minReconnectInterval; !tryConnect(); i = std::min(i*2, maxReconnectInterval)) {
+ if (!ConnectionOptions::reconnect) {
+ throw qpid::messaging::TransportFailure("Failed to connect (reconnect disabled)");
+ }
+ if (limit >= 0 && retries++ >= limit) {
+ throw qpid::messaging::TransportFailure("Failed to connect within reconnect limit");
+ }
+ if (expired(started, timeout)) {
+ throw qpid::messaging::TransportFailure("Failed to connect within reconnect timeout");
+ }
+ QPID_LOG(debug, "Connection retry in " << i*1000*1000 << " microseconds, urls="
+ << asString(urls));
+ qpid::sys::usleep(int64_t(i*1000*1000)); // Sleep in microseconds.
+ }
+ retries = 0;
+}
+
+bool ConnectionContext::tryConnect()
+{
+ for (std::vector<std::string>::const_iterator i = urls.begin(); i != urls.end(); ++i) {
+ try {
+ QPID_LOG(info, "Trying to connect to " << *i << "...");
+ if (tryConnect(qpid::Url(*i, protocol.empty() ? qpid::Address::TCP : protocol))) {
+ return true;
+ }
+ } catch (const qpid::messaging::TransportFailure& e) {
+ QPID_LOG(info, "Failed to connect to " << *i << ": " << e.what());
+ }
+ }
+ return false;
+}
+
+void ConnectionContext::reconnect(const std::string& url)
+{
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
+ if (state != DISCONNECTED) throw qpid::messaging::ConnectionError("Connection was already opened!");
+ if (!driver) driver = DriverImpl::getDefault();
+ reset();
+ if (!tryConnect(qpid::Url(url, protocol.empty() ? qpid::Address::TCP : protocol))) {
+ throw qpid::messaging::TransportFailure("Failed to connect");
+ }
+}
+
+void ConnectionContext::reconnect()
+{
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
+ if (state != DISCONNECTED) throw qpid::messaging::ConnectionError("Connection was already opened!");
+ if (!driver) driver = DriverImpl::getDefault();
+ reset();
+ if (!tryConnect()) {
+ throw qpid::messaging::TransportFailure("Failed to reconnect");
+ }
+}
+
+bool ConnectionContext::tryConnect(const Url& url)
+{
+ if (url.getUser().size()) username = url.getUser();
+ if (url.getPass().size()) password = url.getPass();
+
+ for (Url::const_iterator i = url.begin(); i != url.end(); ++i) {
+ if (tryConnect(*i)) {
+ QPID_LOG(info, "Connected to " << *i);
+ setCurrentUrl(*i);
+ if (sasl.get()) {
+ wakeupDriver();
+ while (!sasl->authenticated()) {
+ QPID_LOG(debug, id << " Waiting to be authenticated...");
+ wait();
+ }
+ QPID_LOG(debug, id << " Authenticated");
+ }
+
+ QPID_LOG(debug, id << " Opening...");
+ setProperties();
+ pn_connection_open(connection);
+ wakeupDriver(); //want to write
+ while (pn_connection_state(connection) & PN_REMOTE_UNINIT) {
+ wait();
+ }
+ if (!(pn_connection_state(connection) & PN_REMOTE_ACTIVE)) {
+ throw qpid::messaging::ConnectionError("Failed to open connection");
+ }
+ QPID_LOG(debug, id << " Opened");
+
+ return restartSessions();
+ }
+ }
+ return false;
+}
+
+void ConnectionContext::setCurrentUrl(const qpid::Address& a)
+{
+ std::stringstream u;
+ u << a;
+ currentUrl = u.str();
+}
+
+std::string ConnectionContext::getUrl() const
+{
+ qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock);
+ if (state == CONNECTED) {
+ return currentUrl;
+ } else {
+ return std::string();
+ }
+}
+
+
+bool ConnectionContext::tryConnect(const qpid::Address& address)
+{
+ transport = driver->getTransport(address.protocol, *this);
+ std::stringstream port;
+ port << address.port;
+ id = address.host + COLON + port.str();
+ if (useSasl()) {
+ sasl = std::auto_ptr<Sasl>(new Sasl(id, *this, address.host));
+ }
+ state = CONNECTING;
+ try {
+ QPID_LOG(debug, id << " Connecting ...");
+ transport->connect(address.host, port.str());
+ bool waiting(true);
+ while (waiting) {
+ switch (state) {
+ case CONNECTED:
+ QPID_LOG(debug, id << " Connected");
+ return true;
+ case CONNECTING:
+ lock.wait();
+ break;
+ case DISCONNECTED:
+ waiting = false;
+ QPID_LOG(debug, id << " Failed to connect");
+ break;
+ }
+ }
+ } catch (const std::exception& e) {
+ QPID_LOG(info, id << " Error while connecting: " << e.what());
+ state = DISCONNECTED;
+ }
+ transport = boost::shared_ptr<Transport>();
+ return false;
+}
+
+bool ConnectionContext::restartSessions()
+{
+ try {
+ for (SessionMap::iterator i = sessions.begin(); i != sessions.end(); ++i) {
+ restartSession(i->second);
+ }
+ return true;
+ } catch (const qpid::TransportFailure& e) {
+ QPID_LOG(debug, "Connection Failed to re-initialize sessions: " << e.what());
+ return false;
+ }
+}
+
+
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h
index 37d73ea456..2fdba7a3b2 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/ConnectionContext.h
@@ -44,6 +44,9 @@ namespace qpid {
namespace framing {
class ProtocolVersion;
}
+namespace sys {
+struct SecuritySettings;
+}
namespace messaging {
class Duration;
class Message;
@@ -72,6 +75,8 @@ class ConnectionContext : public qpid::sys::ConnectionCodec, public qpid::messag
void endSession(boost::shared_ptr<SessionContext>);
void attach(boost::shared_ptr<SessionContext>, boost::shared_ptr<SenderContext>);
void attach(boost::shared_ptr<SessionContext>, boost::shared_ptr<ReceiverContext>);
+ void detach(boost::shared_ptr<SessionContext>, boost::shared_ptr<SenderContext>);
+ void detach(boost::shared_ptr<SessionContext>, boost::shared_ptr<ReceiverContext>);
void send(boost::shared_ptr<SessionContext>, boost::shared_ptr<SenderContext> ctxt, const qpid::messaging::Message& message, bool sync);
bool fetch(boost::shared_ptr<SessionContext> ssn, boost::shared_ptr<ReceiverContext> lnk, qpid::messaging::Message& message, qpid::messaging::Duration timeout);
bool get(boost::shared_ptr<SessionContext> ssn, boost::shared_ptr<ReceiverContext> lnk, qpid::messaging::Message& message, qpid::messaging::Duration timeout);
@@ -101,10 +106,13 @@ class ConnectionContext : public qpid::sys::ConnectionCodec, public qpid::messag
framing::ProtocolVersion getVersion() const;
//additionally, Transport needs:
void opened();//signal successful connection
+ void reconnect(const std::string& url);
+ void reconnect();
+ std::string getUrl() const;
+ const qpid::sys::SecuritySettings* getTransportSecuritySettings();
private:
typedef std::map<std::string, boost::shared_ptr<SessionContext> > SessionMap;
- qpid::Url url;
boost::shared_ptr<DriverImpl> driver;
boost::shared_ptr<Transport> transport;
@@ -117,23 +125,13 @@ class ConnectionContext : public qpid::sys::ConnectionCodec, public qpid::messag
bool readHeader;
bool haveOutput;
std::string id;
+ std::string currentUrl;
enum {
DISCONNECTED,
CONNECTING,
CONNECTED
} state;
std::auto_ptr<Sasl> sasl;
- class CodecSwitch : public qpid::sys::Codec
- {
- public:
- CodecSwitch(ConnectionContext&);
- std::size_t decode(const char* buffer, std::size_t size);
- std::size_t encode(char* buffer, std::size_t size);
- bool canEncode();
- private:
- ConnectionContext& parent;
- };
- CodecSwitch codecSwitch;
void check();
void wait();
@@ -149,7 +147,19 @@ class ConnectionContext : public qpid::sys::ConnectionCodec, public qpid::messag
void checkClosed(boost::shared_ptr<SessionContext>, boost::shared_ptr<SenderContext>);
void checkClosed(boost::shared_ptr<SessionContext>, pn_link_t*);
void wakeupDriver();
- void attach(pn_session_t*, pn_link_t*, int credit=0);
+ void attach(boost::shared_ptr<SessionContext>, pn_link_t*, int credit=0);
+ void autoconnect();
+ bool tryConnect();
+ bool tryConnect(const qpid::Url& url);
+ bool tryConnect(const qpid::Address& address);
+ void reset();
+ bool restartSessions();
+ void restartSession(boost::shared_ptr<SessionContext>);
+ void setCurrentUrl(const qpid::Address&);
+
+ std::size_t decodePlain(const char* buffer, std::size_t size);
+ std::size_t encodePlain(char* buffer, std::size_t size);
+ bool canEncodePlain();
std::size_t readProtocolHeader(const char* buffer, std::size_t size);
std::size_t writeProtocolHeader(char* buffer, std::size_t size);
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.cpp b/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.cpp
index 0c4ec2bfcb..c1ab108a61 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.cpp
@@ -81,4 +81,17 @@ std::string ConnectionHandle::getAuthenticatedUsername()
return connection->getAuthenticatedUsername();
}
+void ConnectionHandle::reconnect(const std::string& url)
+{
+ connection->reconnect(url);
+}
+void ConnectionHandle::reconnect()
+{
+ connection->reconnect();
+}
+std::string ConnectionHandle::getUrl() const
+{
+ return connection->getUrl();
+}
+
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.h b/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.h
index d1eb27f6de..0238313f93 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/ConnectionHandle.h
@@ -49,6 +49,9 @@ class ConnectionHandle : public qpid::messaging::ConnectionImpl
Session getSession(const std::string& name) const;
void setOption(const std::string& name, const qpid::types::Variant& value);
std::string getAuthenticatedUsername();
+ void reconnect(const std::string& url);
+ void reconnect();
+ std::string getUrl() const;
private:
boost::shared_ptr<ConnectionContext> connection;
};
diff --git a/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.cpp b/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.cpp
index b4e0819980..266060c117 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.cpp
@@ -22,26 +22,31 @@
#include "qpid/messaging/Address.h"
#include "qpid/messaging/MessageImpl.h"
#include "qpid/amqp/Decoder.h"
+#include "qpid/amqp/DataBuilder.h"
+#include "qpid/amqp/ListBuilder.h"
+#include "qpid/amqp/MapBuilder.h"
+#include "qpid/amqp/typecodes.h"
+#include "qpid/types/encodings.h"
+#include "qpid/log/Statement.h"
#include <boost/lexical_cast.hpp>
#include <string.h>
namespace qpid {
namespace messaging {
namespace amqp {
-
using namespace qpid::amqp;
-EncodedMessage::EncodedMessage(size_t s) : size(s), data(size ? new char[size] : 0)
+EncodedMessage::EncodedMessage(size_t s) : size(s), data(size ? new char[size] : 0), nestAnnotations(false)
{
init();
}
-EncodedMessage::EncodedMessage() : size(0), data(0)
+EncodedMessage::EncodedMessage() : size(0), data(0), nestAnnotations(false)
{
init();
}
-EncodedMessage::EncodedMessage(const EncodedMessage& other) : size(other.size), data(size ? new char[size] : 0)
+EncodedMessage::EncodedMessage(const EncodedMessage& other) : size(other.size), data(size ? new char[size] : 0), nestAnnotations(false)
{
init();
}
@@ -105,6 +110,8 @@ void EncodedMessage::init(qpid::messaging::MessageImpl& impl)
}
}
+void EncodedMessage::setNestAnnotationsOption(bool b) { nestAnnotations = b; }
+
void EncodedMessage::populate(qpid::types::Variant::Map& map) const
{
//decode application properties
@@ -139,14 +146,20 @@ void EncodedMessage::populate(qpid::types::Variant::Map& map) const
}
//add in any annotations
if (deliveryAnnotations) {
- qpid::types::Variant::Map& annotations = map["x-amqp-delivery-annotations"].asMap();
qpid::amqp::Decoder decoder(deliveryAnnotations.data, deliveryAnnotations.size);
- decoder.readMap(annotations);
+ if (nestAnnotations) {
+ map["x-amqp-delivery-annotations"] = decoder.readMap();
+ } else {
+ decoder.readMap(map);
+ }
}
if (messageAnnotations) {
- qpid::types::Variant::Map& annotations = map["x-amqp-message-annotations"].asMap();
qpid::amqp::Decoder decoder(messageAnnotations.data, messageAnnotations.size);
- decoder.readMap(annotations);
+ if (nestAnnotations) {
+ map["x-amqp-message-annotations"] = decoder.readMap();
+ } else {
+ decoder.readMap(map);
+ }
}
}
qpid::amqp::CharSequence EncodedMessage::getBareMessage() const
@@ -178,9 +191,38 @@ void EncodedMessage::getCorrelationId(std::string& s) const
{
correlationId.assign(s);
}
-void EncodedMessage::getBody(std::string& s) const
+void EncodedMessage::getBody(std::string& raw, qpid::types::Variant& c) const
{
- s.assign(body.data, body.size);
+ if (!content.isVoid()) {
+ c = content;//integer types, floats, bool etc
+ //TODO: populate raw data?
+ } else {
+ if (bodyType.empty()
+ || bodyType == qpid::amqp::typecodes::BINARY_NAME
+ || bodyType == qpid::types::encodings::UTF8
+ || bodyType == qpid::types::encodings::ASCII)
+ {
+ c = std::string(body.data, body.size);
+ c.setEncoding(bodyType);
+ } else if (bodyType == qpid::amqp::typecodes::LIST_NAME) {
+ qpid::amqp::ListBuilder builder;
+ qpid::amqp::Decoder decoder(body.data, body.size);
+ decoder.read(builder);
+ c = builder.getList();
+ raw.assign(body.data, body.size);
+ } else if (bodyType == qpid::amqp::typecodes::MAP_NAME) {
+ qpid::amqp::DataBuilder builder = qpid::amqp::DataBuilder(qpid::types::Variant::Map());
+ qpid::amqp::Decoder decoder(body.data, body.size);
+ decoder.read(builder);
+ c = builder.getValue().asMap();
+ raw.assign(body.data, body.size);
+ } else if (bodyType == qpid::amqp::typecodes::UUID_NAME) {
+ if (body.size == qpid::types::Uuid::SIZE) c = qpid::types::Uuid(body.data);
+ raw.assign(body.data, body.size);
+ } else if (bodyType == qpid::amqp::typecodes::ARRAY_NAME) {
+ raw.assign(body.data, body.size);
+ }
+ }
}
qpid::amqp::CharSequence EncodedMessage::getBody() const
@@ -216,6 +258,7 @@ bool EncodedMessage::hasHeaderChanged(const qpid::messaging::MessageImpl& msg) c
}
+
EncodedMessage::InitialScan::InitialScan(EncodedMessage& e, qpid::messaging::MessageImpl& m) : em(e), mi(m)
{
//set up defaults as needed:
@@ -249,15 +292,35 @@ void EncodedMessage::InitialScan::onGroupId(const qpid::amqp::CharSequence& v) {
void EncodedMessage::InitialScan::onGroupSequence(uint32_t i) { em.groupSequence = i; }
void EncodedMessage::InitialScan::onReplyToGroupId(const qpid::amqp::CharSequence& v) { em.replyToGroupId = v; }
-void EncodedMessage::InitialScan::onApplicationProperties(const qpid::amqp::CharSequence& v) { em.applicationProperties = v; }
-void EncodedMessage::InitialScan::onDeliveryAnnotations(const qpid::amqp::CharSequence& v) { em.deliveryAnnotations = v; }
-void EncodedMessage::InitialScan::onMessageAnnotations(const qpid::amqp::CharSequence& v) { em.messageAnnotations = v; }
-void EncodedMessage::InitialScan::onBody(const qpid::amqp::CharSequence& v, const qpid::amqp::Descriptor&)
+void EncodedMessage::InitialScan::onApplicationProperties(const qpid::amqp::CharSequence& v, const qpid::amqp::CharSequence&) { em.applicationProperties = v; }
+void EncodedMessage::InitialScan::onDeliveryAnnotations(const qpid::amqp::CharSequence& v, const qpid::amqp::CharSequence&) { em.deliveryAnnotations = v; }
+void EncodedMessage::InitialScan::onMessageAnnotations(const qpid::amqp::CharSequence& v, const qpid::amqp::CharSequence&) { em.messageAnnotations = v; }
+
+void EncodedMessage::InitialScan::onData(const qpid::amqp::CharSequence& v)
+{
+ em.body = v;
+}
+void EncodedMessage::InitialScan::onAmqpSequence(const qpid::amqp::CharSequence& v)
{
- //TODO: how to communicate the type, i.e. descriptor?
em.body = v;
+ em.bodyType = qpid::amqp::typecodes::LIST_NAME;
}
-void EncodedMessage::InitialScan::onBody(const qpid::types::Variant&, const qpid::amqp::Descriptor&) {}
-void EncodedMessage::InitialScan::onFooter(const qpid::amqp::CharSequence& v) { em.footer = v; }
+void EncodedMessage::InitialScan::onAmqpValue(const qpid::amqp::CharSequence& v, const std::string& type)
+{
+ em.body = v;
+ if (type == qpid::amqp::typecodes::STRING_NAME) {
+ em.bodyType = qpid::types::encodings::UTF8;
+ } else if (type == qpid::amqp::typecodes::SYMBOL_NAME) {
+ em.bodyType = qpid::types::encodings::ASCII;
+ } else {
+ em.bodyType = type;
+ }
+}
+void EncodedMessage::InitialScan::onAmqpValue(const qpid::types::Variant& v)
+{
+ em.content = v;
+}
+
+void EncodedMessage::InitialScan::onFooter(const qpid::amqp::CharSequence& v, const qpid::amqp::CharSequence&) { em.footer = v; }
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.h b/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.h
index 09a9d948d5..16a43aecea 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/EncodedMessage.h
@@ -21,6 +21,9 @@
* under the License.
*
*/
+
+#include "qpid/messaging/ImportExport.h"
+
#include "qpid/amqp/CharSequence.h"
#include "qpid/amqp/MessageId.h"
#include "qpid/amqp/MessageReader.h"
@@ -71,34 +74,36 @@ namespace amqp {
class EncodedMessage
{
public:
- EncodedMessage();
- EncodedMessage(size_t);
- EncodedMessage(const EncodedMessage&);
- ~EncodedMessage();
+ QPID_MESSAGING_EXTERN EncodedMessage();
+ QPID_MESSAGING_EXTERN EncodedMessage(size_t);
+ QPID_MESSAGING_EXTERN EncodedMessage(const EncodedMessage&);
+ QPID_MESSAGING_EXTERN ~EncodedMessage();
- size_t getSize() const;
- char* getData();
- const char* getData() const;
- void trim(size_t);
- void resize(size_t);
+ QPID_MESSAGING_EXTERN size_t getSize() const;
+ QPID_MESSAGING_EXTERN char* getData();
+ QPID_MESSAGING_EXTERN const char* getData() const;
+ QPID_MESSAGING_EXTERN void trim(size_t);
+ QPID_MESSAGING_EXTERN void resize(size_t);
+ QPID_MESSAGING_EXTERN void setNestAnnotationsOption(bool);
void getReplyTo(qpid::messaging::Address&) const;
void getSubject(std::string&) const;
void getContentType(std::string&) const;
void getMessageId(std::string&) const;
void getUserId(std::string&) const;
void getCorrelationId(std::string&) const;
-
- void init(qpid::messaging::MessageImpl&);
void populate(qpid::types::Variant::Map&) const;
- void getBody(std::string&) const;
- qpid::amqp::CharSequence getBareMessage() const;
+ void getBody(std::string&, qpid::types::Variant&) const;
+
+ QPID_MESSAGING_EXTERN void init(qpid::messaging::MessageImpl&);
+ QPID_MESSAGING_EXTERN qpid::amqp::CharSequence getBareMessage() const;
qpid::amqp::CharSequence getBody() const;
- bool hasHeaderChanged(const qpid::messaging::MessageImpl&) const;
+ QPID_MESSAGING_EXTERN bool hasHeaderChanged(const qpid::messaging::MessageImpl&) const;
private:
size_t size;
char* data;
+ bool nestAnnotations;
class InitialScan : public qpid::amqp::MessageReader
{
@@ -127,12 +132,16 @@ class EncodedMessage
void onGroupSequence(uint32_t);
void onReplyToGroupId(const qpid::amqp::CharSequence&);
- void onApplicationProperties(const qpid::amqp::CharSequence&);
- void onDeliveryAnnotations(const qpid::amqp::CharSequence&);
- void onMessageAnnotations(const qpid::amqp::CharSequence&);
- void onBody(const qpid::amqp::CharSequence&, const qpid::amqp::Descriptor&);
- void onBody(const qpid::types::Variant&, const qpid::amqp::Descriptor&);
- void onFooter(const qpid::amqp::CharSequence&);
+ void onApplicationProperties(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&);
+ void onDeliveryAnnotations(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&);
+ void onMessageAnnotations(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&);
+
+ void onData(const qpid::amqp::CharSequence&);
+ void onAmqpSequence(const qpid::amqp::CharSequence&);
+ void onAmqpValue(const qpid::amqp::CharSequence&, const std::string& type);
+ void onAmqpValue(const qpid::types::Variant&);
+
+ void onFooter(const qpid::amqp::CharSequence&, const qpid::amqp::CharSequence&);
private:
EncodedMessage& em;
qpid::messaging::MessageImpl& mi;
@@ -164,7 +173,11 @@ class EncodedMessage
qpid::amqp::CharSequence replyToGroupId;
//application-properties:
qpid::amqp::CharSequence applicationProperties;
+ //application data:
qpid::amqp::CharSequence body;
+ std::string bodyType;
+ qpid::types::Variant content;
+
//footer:
qpid::amqp::CharSequence footer;
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp
index 081a0ae78b..473c120e27 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.cpp
@@ -89,8 +89,18 @@ const std::string& ReceiverContext::getSource() const
{
return address.getName();
}
-void ReceiverContext::verify(pn_terminus_t* source)
+void ReceiverContext::verify()
{
+ pn_terminus_t* source = pn_link_remote_source(receiver);
+ if (!pn_terminus_get_address(source)) {
+ std::string msg("No such source : ");
+ msg += getSource();
+ QPID_LOG(debug, msg);
+ throw qpid::messaging::NotFound(msg);
+ } else if (AddressImpl::isTemporary(address)) {
+ address.setName(pn_terminus_get_address(source));
+ QPID_LOG(debug, "Dynamic source name set to " << address.getName());
+ }
helper.checkAssertion(source, AddressHelper::FOR_RECEIVER);
}
void ReceiverContext::configure()
@@ -99,7 +109,13 @@ void ReceiverContext::configure()
}
void ReceiverContext::configure(pn_terminus_t* source)
{
- helper.configure(source, AddressHelper::FOR_RECEIVER);
+ helper.configure(receiver, source, AddressHelper::FOR_RECEIVER);
+ std::string option;
+ if (helper.getLinkTarget(option)) {
+ pn_terminus_set_address(pn_link_target(receiver), option.c_str());
+ } else {
+ pn_terminus_set_address(pn_link_target(receiver), pn_terminus_get_address(pn_link_source(receiver)));
+ }
}
Address ReceiverContext::getAddress() const
@@ -112,6 +128,10 @@ bool ReceiverContext::isClosed() const
return false;//TODO
}
-
+void ReceiverContext::reset(pn_session_t* session)
+{
+ receiver = pn_receiver(session, name.c_str());
+ configure();
+}
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h
index 79049d9263..fb8ea0d336 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/ReceiverContext.h
@@ -46,6 +46,7 @@ class ReceiverContext
public:
ReceiverContext(pn_session_t* session, const std::string& name, const qpid::messaging::Address& source);
~ReceiverContext();
+ void reset(pn_session_t* session);
void setCapacity(uint32_t);
uint32_t getCapacity();
uint32_t getAvailable();
@@ -56,7 +57,7 @@ class ReceiverContext
const std::string& getSource() const;
bool isClosed() const;
void configure();
- void verify(pn_terminus_t*);
+ void verify();
Address getAddress() const;
private:
friend class ConnectionContext;
diff --git a/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp b/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp
index c601d05ed0..177f47896b 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/ReceiverHandle.cpp
@@ -84,7 +84,7 @@ uint32_t ReceiverHandle::getUnsettled()
void ReceiverHandle::close()
{
- session->closeReceiver(getName());
+ connection->detach(session, receiver);
}
const std::string& ReceiverHandle::getName() const
diff --git a/qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp b/qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp
index 40f469cdcf..4b21f7b0d2 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/Sasl.cpp
@@ -93,7 +93,7 @@ void Sasl::mechanisms(const std::string& offered)
mechanisms = offered;
}
- if (sasl->start(mechanisms, response)) {
+ if (sasl->start(mechanisms, response, context.getTransportSecuritySettings())) {
init(sasl->getMechanism(), &response, hostname.size() ? &hostname : 0);
} else {
init(sasl->getMechanism(), 0, hostname.size() ? &hostname : 0);
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp
index d4a5ca4292..94851da273 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/SenderContext.cpp
@@ -42,7 +42,7 @@ SenderContext::SenderContext(pn_session_t* session, const std::string& n, const
: name(n),
address(a),
helper(address),
- sender(pn_sender(session, n.c_str())), capacity(1000) {}
+ sender(pn_sender(session, n.c_str())), capacity(1000), unreliable(helper.isUnreliable()) {}
SenderContext::~SenderContext()
{
@@ -67,7 +67,7 @@ uint32_t SenderContext::getCapacity()
uint32_t SenderContext::getUnsettled()
{
- return processUnsettled();
+ return processUnsettled(true/*always allow retrieval of unsettled count, even if link has failed*/);
}
const std::string& SenderContext::getName() const
@@ -80,16 +80,26 @@ const std::string& SenderContext::getTarget() const
return address.getName();
}
-SenderContext::Delivery* SenderContext::send(const qpid::messaging::Message& message)
+bool SenderContext::send(const qpid::messaging::Message& message, SenderContext::Delivery** out)
{
- if (processUnsettled() < capacity && pn_link_credit(sender)) {
- deliveries.push_back(Delivery(nextId++));
- Delivery& delivery = deliveries.back();
- delivery.encode(MessageImplAccess::get(message), address);
- delivery.send(sender);
- return &delivery;
+ resend();//if there are any messages needing to be resent at the front of the queue, send them first
+ if (processUnsettled(false) < capacity && pn_link_credit(sender)) {
+ if (unreliable) {
+ Delivery delivery(nextId++);
+ delivery.encode(MessageImplAccess::get(message), address);
+ delivery.send(sender, unreliable);
+ *out = 0;
+ return true;
+ } else {
+ deliveries.push_back(Delivery(nextId++));
+ Delivery& delivery = deliveries.back();
+ delivery.encode(MessageImplAccess::get(message), address);
+ delivery.send(sender, unreliable);
+ *out = &delivery;
+ return true;
+ }
} else {
- return 0;
+ return false;
}
}
@@ -108,11 +118,13 @@ void SenderContext::check()
}
}
-uint32_t SenderContext::processUnsettled()
+uint32_t SenderContext::processUnsettled(bool silent)
{
- check();
+ if (!silent) {
+ check();
+ }
//remove messages from front of deque once peer has confirmed receipt
- while (!deliveries.empty() && deliveries.front().delivered()) {
+ while (!deliveries.empty() && deliveries.front().delivered() && !(pn_link_state(sender) & PN_REMOTE_CLOSED)) {
deliveries.front().settle();
deliveries.pop_front();
}
@@ -122,6 +134,7 @@ namespace {
const std::string X_AMQP("x-amqp-");
const std::string X_AMQP_FIRST_ACQUIRER("x-amqp-first-acquirer");
const std::string X_AMQP_DELIVERY_COUNT("x-amqp-delivery-count");
+const std::string X_AMQP_0_10_APP_ID("x-amqp-0-10.app-id");
class HeaderAdapter : public qpid::amqp::MessageEncoder::Header
{
@@ -341,7 +354,7 @@ class ApplicationPropertiesAdapter : public qpid::amqp::MessageEncoder::Applicat
{
for (qpid::types::Variant::Map::const_iterator i = headers.begin(); i != headers.end(); ++i) {
//strip out values with special keys as they are sent in standard fields
- if (!startsWith(i->first, X_AMQP)) {
+ if (!startsWith(i->first, X_AMQP) || i->first == X_AMQP_0_10_APP_ID) {
qpid::amqp::CharSequence key(convert(i->first));
switch (i->second.getType()) {
case qpid::types::VAR_VOID:
@@ -413,7 +426,12 @@ bool changedSubject(const qpid::messaging::MessageImpl& msg, const qpid::messagi
}
-SenderContext::Delivery::Delivery(int32_t i) : id(i), token(0) {}
+SenderContext::Delivery::Delivery(int32_t i) : id(i), token(0), presettled(false) {}
+
+void SenderContext::Delivery::reset()
+{
+ token = 0;
+}
void SenderContext::Delivery::encode(const qpid::messaging::MessageImpl& msg, const qpid::messaging::Address& address)
{
@@ -440,7 +458,15 @@ void SenderContext::Delivery::encode(const qpid::messaging::MessageImpl& msg, co
PropertiesAdapter properties(msg, address.getSubject());
ApplicationPropertiesAdapter applicationProperties(msg.getHeaders());
//compute size:
- encoded.resize(qpid::amqp::MessageEncoder::getEncodedSize(header, properties, applicationProperties, msg.getBytes()));
+ size_t contentSize = qpid::amqp::MessageEncoder::getEncodedSize(header)
+ + qpid::amqp::MessageEncoder::getEncodedSize(properties)
+ + qpid::amqp::MessageEncoder::getEncodedSize(applicationProperties);
+ if (msg.getContent().isVoid()) {
+ contentSize += qpid::amqp::MessageEncoder::getEncodedSizeForContent(msg.getBytes());
+ } else {
+ contentSize += qpid::amqp::MessageEncoder::getEncodedSizeForValue(msg.getContent()) + 3/*descriptor*/;
+ }
+ encoded.resize(contentSize);
QPID_LOG(debug, "Sending message, buffer is " << encoded.getSize() << " bytes")
qpid::amqp::MessageEncoder encoder(encoded.getData(), encoded.getSize());
//write header:
@@ -451,7 +477,12 @@ void SenderContext::Delivery::encode(const qpid::messaging::MessageImpl& msg, co
//write application-properties
encoder.writeApplicationProperties(applicationProperties);
//write body
- if (msg.getBytes().size()) encoder.writeBinary(msg.getBytes(), &qpid::amqp::message::DATA);//structured content not yet directly supported
+ if (!msg.getContent().isVoid()) {
+ //write as AmqpValue
+ encoder.writeValue(msg.getContent(), &qpid::amqp::message::AMQP_VALUE);
+ } else if (msg.getBytes().size()) {
+ encoder.writeBinary(msg.getBytes(), &qpid::amqp::message::DATA);//structured content not yet directly supported
+ }
if (encoder.getPosition() < encoded.getSize()) {
QPID_LOG(debug, "Trimming buffer from " << encoded.getSize() << " to " << encoder.getPosition());
encoded.trim(encoder.getPosition());
@@ -459,19 +490,27 @@ void SenderContext::Delivery::encode(const qpid::messaging::MessageImpl& msg, co
//write footer (no annotations yet supported)
}
}
-void SenderContext::Delivery::send(pn_link_t* sender)
+void SenderContext::Delivery::send(pn_link_t* sender, bool unreliable)
{
pn_delivery_tag_t tag;
tag.size = sizeof(id);
tag.bytes = reinterpret_cast<const char*>(&id);
token = pn_delivery(sender, tag);
pn_link_send(sender, encoded.getData(), encoded.getSize());
+ if (unreliable) {
+ pn_delivery_settle(token);
+ presettled = true;
+ }
pn_link_advance(sender);
}
+bool SenderContext::Delivery::sent() const
+{
+ return presettled || token;
+}
bool SenderContext::Delivery::delivered()
{
- if (pn_delivery_remote_state(token) || pn_delivery_settled(token)) {
+ if (presettled || (token && (pn_delivery_remote_state(token) || pn_delivery_settled(token)))) {
//TODO: need a better means for signalling outcomes other than accepted
if (rejected()) {
QPID_LOG(warning, "delivery " << id << " was rejected by peer");
@@ -495,8 +534,19 @@ void SenderContext::Delivery::settle()
{
pn_delivery_settle(token);
}
-void SenderContext::verify(pn_terminus_t* target)
+void SenderContext::verify()
{
+ pn_terminus_t* target = pn_link_remote_target(sender);
+ if (!pn_terminus_get_address(target)) {
+ std::string msg("No such target : ");
+ msg += getTarget();
+ QPID_LOG(debug, msg);
+ throw qpid::messaging::NotFound(msg);
+ } else if (AddressImpl::isTemporary(address)) {
+ address.setName(pn_terminus_get_address(target));
+ QPID_LOG(debug, "Dynamic target name set to " << address.getName());
+ }
+
helper.checkAssertion(target, AddressHelper::FOR_SENDER);
}
void SenderContext::configure()
@@ -505,12 +555,18 @@ void SenderContext::configure()
}
void SenderContext::configure(pn_terminus_t* target)
{
- helper.configure(target, AddressHelper::FOR_SENDER);
+ helper.configure(sender, target, AddressHelper::FOR_SENDER);
+ std::string option;
+ if (helper.getLinkSource(option)) {
+ pn_terminus_set_address(pn_link_source(sender), option.c_str());
+ } else {
+ pn_terminus_set_address(pn_link_source(sender), pn_terminus_get_address(pn_link_target(sender)));
+ }
}
bool SenderContext::settled()
{
- return processUnsettled() == 0;
+ return processUnsettled(false) == 0;
}
Address SenderContext::getAddress() const
@@ -518,4 +574,22 @@ Address SenderContext::getAddress() const
return address;
}
+
+void SenderContext::reset(pn_session_t* session)
+{
+ sender = pn_sender(session, name.c_str());
+ configure();
+
+ for (Deliveries::iterator i = deliveries.begin(); i != deliveries.end(); ++i) {
+ i->reset();
+ }
+}
+
+void SenderContext::resend()
+{
+ for (Deliveries::iterator i = deliveries.begin(); i != deliveries.end() && pn_link_credit(sender) && !i->sent(); ++i) {
+ i->send(sender, false/*only resend reliable transfers*/);
+ }
+}
+
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SenderContext.h b/qpid/cpp/src/qpid/messaging/amqp/SenderContext.h
index e389cd2e35..27ffa1e81b 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SenderContext.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/SenderContext.h
@@ -52,28 +52,32 @@ class SenderContext
public:
Delivery(int32_t id);
void encode(const qpid::messaging::MessageImpl& message, const qpid::messaging::Address&);
- void send(pn_link_t*);
+ void send(pn_link_t*, bool unreliable);
bool delivered();
bool accepted();
bool rejected();
void settle();
+ void reset();
+ bool sent() const;
private:
int32_t id;
pn_delivery_t* token;
EncodedMessage encoded;
+ bool presettled;
};
SenderContext(pn_session_t* session, const std::string& name, const qpid::messaging::Address& target);
~SenderContext();
+ void reset(pn_session_t* session);
void close();
void setCapacity(uint32_t);
uint32_t getCapacity();
uint32_t getUnsettled();
const std::string& getName() const;
const std::string& getTarget() const;
- Delivery* send(const qpid::messaging::Message& message);
+ bool send(const qpid::messaging::Message& message, Delivery**);
void configure();
- void verify(pn_terminus_t*);
+ void verify();
void check();
bool settled();
Address getAddress() const;
@@ -88,9 +92,11 @@ class SenderContext
int32_t nextId;
Deliveries deliveries;
uint32_t capacity;
+ bool unreliable;
- uint32_t processUnsettled();
+ uint32_t processUnsettled(bool silent);
void configure(pn_terminus_t*);
+ void resend();
};
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp b/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp
index cda8c032aa..367db701cb 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/SenderHandle.cpp
@@ -44,7 +44,7 @@ void SenderHandle::send(const Message& message, bool sync)
void SenderHandle::close()
{
- session->closeSender(getName());
+ connection->detach(session, sender);
}
void SenderHandle::setCapacity(uint32_t capacity)
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp b/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp
index 9815721fa0..8f2a7d15d8 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/SessionContext.cpp
@@ -79,14 +79,14 @@ boost::shared_ptr<ReceiverContext> SessionContext::getReceiver(const std::string
}
}
-void SessionContext::closeReceiver(const std::string&)
+void SessionContext::removeReceiver(const std::string& n)
{
-
+ receivers.erase(n);
}
-void SessionContext::closeSender(const std::string&)
+void SessionContext::removeSender(const std::string& n)
{
-
+ senders.erase(n);
}
boost::shared_ptr<ReceiverContext> SessionContext::nextReceiver(qpid::messaging::Duration /*timeout*/)
@@ -153,4 +153,25 @@ bool SessionContext::settled()
}
return result;
}
+
+void SessionContext::setName(const std::string& n)
+{
+ name = n;
+}
+std::string SessionContext::getName() const
+{
+ return name;
+}
+
+void SessionContext::reset(pn_connection_t* connection)
+{
+ session = pn_session(connection);
+ unacked.clear();
+ for (SessionContext::SenderMap::iterator i = senders.begin(); i != senders.end(); ++i) {
+ i->second->reset(session);
+ }
+ for (SessionContext::ReceiverMap::iterator i = receivers.begin(); i != receivers.end(); ++i) {
+ i->second->reset(session);
+ }
+}
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.h b/qpid/cpp/src/qpid/messaging/amqp/SessionContext.h
index eca30a0e97..5d68f6d8de 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SessionContext.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/SessionContext.h
@@ -50,16 +50,19 @@ class SessionContext
public:
SessionContext(pn_connection_t*);
~SessionContext();
+ void reset(pn_connection_t*);
boost::shared_ptr<SenderContext> createSender(const qpid::messaging::Address& address);
boost::shared_ptr<ReceiverContext> createReceiver(const qpid::messaging::Address& address);
boost::shared_ptr<SenderContext> getSender(const std::string& name) const;
boost::shared_ptr<ReceiverContext> getReceiver(const std::string& name) const;
- void closeReceiver(const std::string&);
- void closeSender(const std::string&);
+ void removeReceiver(const std::string&);
+ void removeSender(const std::string&);
boost::shared_ptr<ReceiverContext> nextReceiver(qpid::messaging::Duration timeout);
uint32_t getReceivable();
uint32_t getUnsettledAcks();
bool settled();
+ void setName(const std::string&);
+ std::string getName() const;
private:
friend class ConnectionContext;
typedef std::map<std::string, boost::shared_ptr<SenderContext> > SenderMap;
@@ -70,6 +73,7 @@ class SessionContext
ReceiverMap receivers;
DeliveryMap unacked;
qpid::framing::SequenceNumber next;
+ std::string name;
qpid::framing::SequenceNumber record(pn_delivery_t*);
void acknowledge();
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp b/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp
index bf79771ca4..45635e4ced 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/SessionHandle.cpp
@@ -84,15 +84,25 @@ void SessionHandle::sync(bool /*block*/)
qpid::messaging::Sender SessionHandle::createSender(const qpid::messaging::Address& address)
{
boost::shared_ptr<SenderContext> sender = session->createSender(address);
- connection->attach(session, sender);
- return qpid::messaging::Sender(new SenderHandle(connection, session, sender));
+ try {
+ connection->attach(session, sender);
+ return qpid::messaging::Sender(new SenderHandle(connection, session, sender));
+ } catch (...) {
+ session->removeSender(sender->getName());
+ throw;
+ }
}
qpid::messaging::Receiver SessionHandle::createReceiver(const qpid::messaging::Address& address)
{
boost::shared_ptr<ReceiverContext> receiver = session->createReceiver(address);
- connection->attach(session, receiver);
- return qpid::messaging::Receiver(new ReceiverHandle(connection, session, receiver));
+ try {
+ connection->attach(session, receiver);
+ return qpid::messaging::Receiver(new ReceiverHandle(connection, session, receiver));
+ } catch (...) {
+ session->removeReceiver(receiver->getName());
+ throw;
+ }
}
bool SessionHandle::nextReceiver(Receiver& receiver, Duration timeout)
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp b/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp
index ea2375cb26..a62a553d90 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/SslTransport.cpp
@@ -157,4 +157,11 @@ void SslTransport::activateOutput()
if (aio) aio->notifyPendingWrite();
}
+const qpid::sys::SecuritySettings* SslTransport::getSecuritySettings()
+{
+ securitySettings.ssf = socket.getKeyLen();
+ securitySettings.authid = "dummy";//set to non-empty string to enable external authentication
+ return &securitySettings;
+}
+
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/SslTransport.h b/qpid/cpp/src/qpid/messaging/amqp/SslTransport.h
index aad82c2c2a..2972be4fac 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/SslTransport.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/SslTransport.h
@@ -23,6 +23,7 @@
*/
#include "qpid/messaging/amqp/Transport.h"
#include "qpid/sys/Mutex.h"
+#include "qpid/sys/SecuritySettings.h"
#include "qpid/sys/ssl/SslSocket.h"
#include <boost/shared_ptr.hpp>
@@ -50,6 +51,7 @@ class SslTransport : public Transport
void abort();
void connectionEstablished() {};
void close();
+ const qpid::sys::SecuritySettings* getSecuritySettings();
private:
qpid::sys::ssl::SslSocket socket;
@@ -59,6 +61,7 @@ class SslTransport : public Transport
boost::shared_ptr<qpid::sys::Poller> poller;
bool closed;
std::string id;
+ qpid::sys::SecuritySettings securitySettings;
void connected(const qpid::sys::Socket&);
void failed(const std::string& msg);
diff --git a/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp b/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp
index 98022d634c..c0a9560c6f 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp
+++ b/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.cpp
@@ -159,4 +159,8 @@ void TcpTransport::activateOutput()
if (aio) aio->notifyPendingWrite();
}
+const qpid::sys::SecuritySettings* TcpTransport::getSecuritySettings()
+{
+ return 0;
+}
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.h b/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.h
index d7adf64f3e..406791417c 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/TcpTransport.h
@@ -50,6 +50,7 @@ class TcpTransport : public Transport
void abort();
void connectionEstablished() {};
void close();
+ const qpid::sys::SecuritySettings* getSecuritySettings();
private:
boost::scoped_ptr<qpid::sys::Socket> socket;
diff --git a/qpid/cpp/src/qpid/messaging/amqp/Transport.h b/qpid/cpp/src/qpid/messaging/amqp/Transport.h
index ee021f645b..159916f9ae 100644
--- a/qpid/cpp/src/qpid/messaging/amqp/Transport.h
+++ b/qpid/cpp/src/qpid/messaging/amqp/Transport.h
@@ -21,12 +21,14 @@
* under the License.
*
*/
+#include "qpid/CommonImportExport.h"
#include "qpid/sys/OutputControl.h"
#include <boost/shared_ptr.hpp>
namespace qpid {
namespace sys {
class Poller;
+struct SecuritySettings;
}
namespace messaging {
namespace amqp {
@@ -38,10 +40,11 @@ class Transport : public qpid::sys::OutputControl
virtual ~Transport() {}
virtual void connect(const std::string& host, const std::string& port) = 0;
virtual void close() = 0;
+ virtual const qpid::sys::SecuritySettings* getSecuritySettings() = 0;
typedef Transport* Factory(TransportContext&, boost::shared_ptr<qpid::sys::Poller>);
- static Transport* create(const std::string& name, TransportContext&, boost::shared_ptr<qpid::sys::Poller>);
- static void add(const std::string& name, Factory* factory);
+ QPID_COMMON_EXTERN static Transport* create(const std::string& name, TransportContext&, boost::shared_ptr<qpid::sys::Poller>);
+ QPID_COMMON_EXTERN static void add(const std::string& name, Factory* factory);
};
}}} // namespace qpid::messaging::amqp
diff --git a/qpid/cpp/src/qpid/store/CMakeLists.txt b/qpid/cpp/src/qpid/store/CMakeLists.txt
index 31623f8e84..094ae9d5d0 100644
--- a/qpid/cpp/src/qpid/store/CMakeLists.txt
+++ b/qpid/cpp/src/qpid/store/CMakeLists.txt
@@ -32,7 +32,7 @@ set (store_SOURCES
MessageStorePlugin.cpp
)
add_library (store MODULE ${store_SOURCES})
-target_link_libraries (store qpidbroker ${Boost_PROGRAM_OPTIONS_LIBRARY})
+target_link_libraries (store qpidbroker qpidcommon ${Boost_PROGRAM_OPTIONS_LIBRARY})
if (CMAKE_COMPILER_IS_GNUCXX)
set (GCC_CATCH_UNDEFINED "-Wl,--no-undefined")
# gcc on SunOS uses native linker whose "-z defs" is too fussy
diff --git a/qpid/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp b/qpid/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp
index 90785263d3..512e71230b 100644
--- a/qpid/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp
+++ b/qpid/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp
@@ -34,7 +34,6 @@
#include <qpid/store/StorageProvider.h>
#include <qpid/sys/Mutex.h>
#include <boost/foreach.hpp>
-#include <boost/make_shared.hpp>
// From ms-sql...
#include "BlobAdapter.h"
@@ -356,7 +355,7 @@ MSSqlClfsProvider::finalizeMe()
MSSqlClfsProvider::MSSqlClfsProvider()
: options("MS SQL/CLFS Provider options")
{
- transactions = boost::make_shared<TransactionLog>();
+ transactions.reset(new TransactionLog());
}
MSSqlClfsProvider::~MSSqlClfsProvider()
diff --git a/qpid/cpp/src/qpid/sys/Condition.h b/qpid/cpp/src/qpid/sys/Condition.h
new file mode 100644
index 0000000000..9be4b357fe
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/Condition.h
@@ -0,0 +1,33 @@
+#ifndef _sys_Condition_h
+#define _sys_Condition_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#ifdef USE_APR_PLATFORM
+#include "apr/Condition.h"
+#elif defined (_WIN32)
+#include "windows/Condition.h"
+#else
+#include "posix/Condition.h"
+#endif
+
+#endif /*!_sys_Condition_h*/
diff --git a/qpid/cpp/src/qpid/sys/ExceptionHolder.h b/qpid/cpp/src/qpid/sys/ExceptionHolder.h
new file mode 100644
index 0000000000..4bc934cf75
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/ExceptionHolder.h
@@ -0,0 +1,71 @@
+#ifndef QPID_EXCEPTIONHOLDER_H
+#define QPID_EXCEPTIONHOLDER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace qpid {
+namespace sys {
+
+struct Raisable {
+ virtual ~Raisable() {};
+ virtual void raise() const=0;
+ virtual std::string what() const=0;
+};
+
+/**
+ * Holder for exceptions. Allows the thread that notices an error condition to
+ * create an exception and store it to be thrown by another thread.
+ */
+class ExceptionHolder : public Raisable {
+ public:
+ ExceptionHolder() {}
+ // Use default copy & assign.
+
+ /** Take ownership of ex */
+ template <class Ex> ExceptionHolder(Ex* ex) { wrap(ex); }
+ template <class Ex> ExceptionHolder& operator=(Ex* ex) { wrap(ex); return *this; }
+
+ void raise() const { if (wrapper.get()) wrapper->raise() ; }
+ std::string what() const { return wrapper.get() ? wrapper->what() : std::string(); }
+ bool empty() const { return !wrapper.get(); }
+ operator bool() const { return !empty(); }
+ void reset() { wrapper.reset(); }
+
+ private:
+ template <class Ex> struct Wrapper : public Raisable {
+ Wrapper(Ex* ptr) : exception(ptr) {}
+ void raise() const { throw *exception; }
+ std::string what() const { return exception->what(); }
+ boost::shared_ptr<Ex> exception;
+ };
+ template <class Ex> void wrap(Ex* ex) { wrapper.reset(new Wrapper<Ex>(ex)); }
+ boost::shared_ptr<Raisable> wrapper;
+};
+
+
+}} // namespace qpid::sys
+
+
+#endif /*!QPID_EXCEPTIONHOLDER_H*/
diff --git a/qpid/cpp/src/qpid/sys/IOHandle.h b/qpid/cpp/src/qpid/sys/IOHandle.h
new file mode 100644
index 0000000000..06ae65f879
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/IOHandle.h
@@ -0,0 +1,36 @@
+#ifndef _sys_IOHandle_h
+#define _sys_IOHandle_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+namespace qpid {
+namespace sys {
+
+/**
+ * This is a class intended to abstract the Unix concept of file descriptor
+ * or the Windows concept of HANDLE
+ */
+class IOHandle;
+
+}}
+
+#endif // _sys_IOHandle_h
diff --git a/qpid/cpp/src/qpid/sys/Monitor.h b/qpid/cpp/src/qpid/sys/Monitor.h
new file mode 100644
index 0000000000..123bf92dcb
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/Monitor.h
@@ -0,0 +1,49 @@
+#ifndef _sys_Monitor_h
+#define _sys_Monitor_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/sys/Condition.h"
+
+namespace qpid {
+namespace sys {
+
+/**
+ * A monitor is a condition variable and a mutex
+ */
+class Monitor : public Mutex, public Condition {
+ public:
+ inline void wait();
+ inline bool wait(const AbsTime& absoluteTime);
+};
+
+
+void Monitor::wait() {
+ Condition::wait(*this);
+}
+
+bool Monitor::wait(const AbsTime& absoluteTime) {
+ return Condition::wait(*this, absoluteTime);
+}
+
+}}
+#endif /*!_sys_Monitor_h*/
diff --git a/qpid/cpp/src/qpid/sys/Mutex.h b/qpid/cpp/src/qpid/sys/Mutex.h
new file mode 100644
index 0000000000..e718586a39
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/Mutex.h
@@ -0,0 +1,91 @@
+#ifndef _sys_Mutex_h
+#define _sys_Mutex_h
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace qpid {
+namespace sys {
+
+/**
+ * Scoped lock template: calls lock() in ctor, unlock() in dtor.
+ * L can be any class with lock() and unlock() functions.
+ */
+template <class L>
+class ScopedLock
+{
+ public:
+ ScopedLock(L& l) : mutex(l) { mutex.lock(); }
+ ~ScopedLock() { mutex.unlock(); }
+ private:
+ L& mutex;
+};
+
+template <class L>
+class ScopedUnlock
+{
+ public:
+ ScopedUnlock(L& l) : mutex(l) { mutex.unlock(); }
+ ~ScopedUnlock() { mutex.lock(); }
+ private:
+ L& mutex;
+};
+
+template <class L>
+class ScopedRlock
+{
+ public:
+ ScopedRlock(L& l) : mutex(l) { mutex.rlock(); }
+ ~ScopedRlock() { mutex.unlock(); }
+ private:
+ L& mutex;
+};
+
+template <class L>
+class ScopedWlock
+{
+ public:
+ ScopedWlock(L& l) : mutex(l) { mutex.wlock(); }
+ ~ScopedWlock() { mutex.unlock(); }
+ private:
+ L& mutex;
+};
+
+template <class L>
+class ConditionalScopedLock
+{
+ public:
+ ConditionalScopedLock(L& l) : mutex(l) { acquired = mutex.trylock(); }
+ ~ConditionalScopedLock() { if (acquired) mutex.unlock(); }
+ bool lockAcquired() { return acquired; }
+ private:
+ L& mutex;
+ bool acquired;
+};
+
+}}
+
+#ifdef USE_APR_PLATFORM
+#include "apr/Mutex.h"
+#elif defined (_WIN32)
+#include "windows/Mutex.h"
+#else
+#include "posix/Mutex.h"
+#endif
+
+#endif /*!_sys_Mutex_h*/
diff --git a/qpid/cpp/src/qpid/console/Package.cpp b/qpid/cpp/src/qpid/sys/Runnable.h
index e5d6fa29fd..fed7663cb6 100644
--- a/qpid/cpp/src/qpid/console/Package.cpp
+++ b/qpid/cpp/src/qpid/sys/Runnable.h
@@ -1,3 +1,5 @@
+#ifndef _Runnable_
+#define _Runnable_
/*
*
* 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
@@ -19,23 +21,31 @@
*
*/
-#include "qpid/console/Package.h"
+#include <boost/function.hpp>
+#include "qpid/CommonImportExport.h"
-using namespace qpid::console;
+namespace qpid {
+namespace sys {
-SchemaClass* Package::getClass(const std::string& className, uint8_t* hash)
-{
- NameHash key(className, hash);
- ClassMap::iterator iter = classes.find(key);
- if (iter != classes.end())
- return iter->second;
- return 0;
-}
-
-void Package::addClass(const std::string& className, uint8_t* hash, SchemaClass* schemaClass)
+/**
+ * Interface for objects that can be run, e.g. in a thread.
+ */
+class QPID_COMMON_CLASS_EXTERN Runnable
{
- NameHash key(className, hash);
- ClassMap::iterator iter = classes.find(key);
- if (iter == classes.end())
- classes[key] = schemaClass;
-}
+ public:
+ /** Type to represent a runnable as a Functor */
+ typedef boost::function0<void> Functor;
+
+ QPID_COMMON_EXTERN virtual ~Runnable();
+
+ /** Derived classes override run(). */
+ virtual void run() = 0;
+
+ /** Create a functor object that will call this->run(). */
+ Functor functor();
+};
+
+}}
+
+
+#endif
diff --git a/qpid/cpp/src/qmf/engine/MessageImpl.h b/qpid/cpp/src/qpid/sys/StrError.h
index b91291d2e4..36489dd0fc 100644
--- a/qpid/cpp/src/qmf/engine/MessageImpl.h
+++ b/qpid/cpp/src/qpid/sys/StrError.h
@@ -1,7 +1,8 @@
-#ifndef _QmfEngineMessageImpl_
-#define _QmfEngineMessageImpl_
+#ifndef _sys_StrError_h
+#define _sys_StrError_h
/*
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -9,36 +10,27 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
+ *
*/
-#include "qmf/engine/Message.h"
#include <string>
-#include <boost/shared_ptr.hpp>
+#include "qpid/CommonImportExport.h"
-namespace qmf {
-namespace engine {
+namespace qpid {
+namespace sys {
- struct MessageImpl {
- typedef boost::shared_ptr<MessageImpl> Ptr;
- std::string body;
- std::string destination;
- std::string routingKey;
- std::string replyExchange;
- std::string replyKey;
- std::string userId;
+/** Get the error message for a system number err, e.g. errno. */
+QPID_COMMON_EXTERN std::string strError(int err);
- Message copy();
- };
-}
-}
+}} // namespace qpid
-#endif
+#endif // _sys_StrError_h
diff --git a/qpid/cpp/src/qpid/sys/SystemInfo.h b/qpid/cpp/src/qpid/sys/SystemInfo.h
new file mode 100644
index 0000000000..1b5720a5f0
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/SystemInfo.h
@@ -0,0 +1,109 @@
+#ifndef QPID_SYS_SYSTEMINFO_H
+#define QPID_SYS_SYSTEMINFO_H
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/sys/IntegerTypes.h"
+#include "qpid/Address.h"
+#include "qpid/CommonImportExport.h"
+#include <vector>
+
+namespace qpid {
+namespace sys {
+
+/**
+ * Retrieve information about the system we are running on.
+ * Results may be dependent on OS/hardware.
+ */
+namespace SystemInfo {
+/**
+ * Estimate available concurrency, e.g. number of CPU cores.
+ * -1 means estimate not available on this platform.
+ */
+QPID_COMMON_EXTERN long concurrency();
+
+/**
+ * Get the local host name and set it in the specified.
+ * Returns false if it can't be obtained and sets errno to any error value.
+ */
+QPID_COMMON_EXTERN bool getLocalHostname (Address &address);
+
+/**
+ * Get the names of all the network interfaces connected to
+ * this host.
+ * @param names Receives the list of interface names
+ */
+QPID_COMMON_EXTERN void getInterfaceNames(std::vector<std::string>& names );
+
+/**
+ * Get strings for each of the IP addresses associated with a named network
+ * interface.
+ * If there is no interface of that name an empty list will be returned.
+ *
+ * @param interface The name of the network interface
+ * @param addresses The list of the strings for the IP addresses are pushed on the back of this parameter
+ * to get just the list you need to clear the vector before using it.
+ * @return true if an interface of the correct name was found, false otherwise
+ */
+QPID_COMMON_EXTERN bool getInterfaceAddresses(const std::string& interface, std::vector<std::string>& addresses);
+
+/**
+ * Retrieve system identifiers and versions. This is information that can
+ * generally be retrieved via POSIX uname().
+ *
+ * @param osName Receives the OS name; e.g., GNU/Linux or Windows
+ * @param nodeName Receives the nodename. This may or may not match the
+ * set hostname from getLocalHostname().
+ * @param release Receives the OS release identifier.
+ * @param version Receives the OS release version (kernel, build, sp, etc.)
+ * @param machine Receives the hardware type.
+ */
+QPID_COMMON_EXTERN void getSystemId (std::string &osName,
+ std::string &nodeName,
+ std::string &release,
+ std::string &version,
+ std::string &machine);
+
+/**
+ * Get the process ID of the current process.
+ */
+QPID_COMMON_EXTERN uint32_t getProcessId();
+
+/**
+ * Get the process ID of the parent of the current process.
+ */
+QPID_COMMON_EXTERN uint32_t getParentProcessId();
+
+/**
+ * Get the name of the current process (i.e. the name of the executable)
+ */
+QPID_COMMON_EXTERN std::string getProcessName();
+
+/**
+ * Can thread related primitives be trusted during runtime house-cleaning?
+ * (i.e. static destructors, atexit()).
+ */
+QPID_COMMON_EXTERN bool threadSafeShutdown();
+
+
+}}} // namespace qpid::sys::SystemInfo
+
+#endif /*!QPID_SYS_SYSTEMINFO_H*/
diff --git a/qpid/cpp/src/qpid/sys/Thread.h b/qpid/cpp/src/qpid/sys/Thread.h
new file mode 100644
index 0000000000..f556612908
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/Thread.h
@@ -0,0 +1,71 @@
+#ifndef _sys_Thread_h
+#define _sys_Thread_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include <boost/shared_ptr.hpp>
+#include "qpid/CommonImportExport.h"
+
+#ifdef _WIN32
+# ifdef _MSC_VER
+# define QPID_TSS __declspec(thread)
+# else
+# define QPID_TSS __thread
+# endif
+#elif defined (__GNUC__)
+# define QPID_TSS __thread
+#elif defined (__SUNPRO_CC)
+# define QPID_TSS __thread
+#else
+# error "Dont know how to define QPID_TSS for this platform"
+#endif
+
+namespace qpid {
+namespace sys {
+
+class Runnable;
+class ThreadPrivate;
+
+class Thread
+{
+ boost::shared_ptr<ThreadPrivate> impl;
+
+ public:
+ QPID_COMMON_EXTERN Thread();
+ QPID_COMMON_EXTERN explicit Thread(qpid::sys::Runnable*);
+ QPID_COMMON_EXTERN explicit Thread(qpid::sys::Runnable&);
+
+ QPID_COMMON_EXTERN operator bool();
+ QPID_COMMON_EXTERN bool operator==(const Thread&) const;
+ QPID_COMMON_EXTERN bool operator!=(const Thread&) const;
+
+ QPID_COMMON_EXTERN void join();
+
+ QPID_COMMON_EXTERN static Thread current();
+
+ /** ID of current thread for logging.
+ * Workaround for broken Thread::current() in APR
+ */
+ QPID_COMMON_EXTERN static unsigned long logId();
+};
+
+}}
+#endif /*!_sys_Thread_h*/
diff --git a/qpid/cpp/src/qpid/sys/Time.h b/qpid/cpp/src/qpid/sys/Time.h
new file mode 100644
index 0000000000..2ccff92e7c
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/Time.h
@@ -0,0 +1,176 @@
+#ifndef _sys_Time_h
+#define _sys_Time_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/sys/IntegerTypes.h"
+/*
+ * The platform defines its notion of time as a TimePrivate type. The
+ * platform's implementation knows how to handle this type.
+ */
+#if defined (_WIN32)
+# include "windows/Time.h"
+#else
+# include "posix/Time.h"
+#endif
+
+#include "qpid/CommonImportExport.h"
+
+#include <limits>
+#include <iosfwd>
+
+namespace qpid {
+namespace sys {
+
+class Duration;
+
+/**
+ * @class AbsTime
+ *
+ * Class to represent an instant in time.
+ *
+ * The time resolution is in nanosecs, and this is held with 64 bits
+ * giving a total time span from about 25 million years ago to 25 million
+ * years hence. As an aside the internal time can sensibly be negative
+ * meaning before the epoch (probably 1/1/1970 although this class doesn't
+ * care).
+ *
+ * The AbsTime class is a value class and so you don't need to add any
+ * accessors to its internal state. If you think you want to replace its value,
+ * you need to construct a new AbsTime and assign it, viz:
+ *
+ * AbsTime when = now();
+ * ...
+ * when = AbsTime(when, 2*TIME_SEC); // Advance timer 2 secs
+ *
+ * AbsTime is not intended to be used to represent calendar dates/times
+ * but you can construct a Duration since the Unix Epoch, 1970-1-1-00:00,
+ * so that you can convert to a date/time if needed:
+ *
+ * int64_t nanosec_since_epoch = Duration(EPOCH, now());
+ *
+ * There are some sensible operations that are currently missing from
+ * AbsTime, but nearly all that's needed can be done with a mixture of
+ * AbsTimes and Durations.
+ *
+ * For example, convenience operators to add a Duration and AbsTime returning
+ * an AbsTime would fit here (although you can already perform the operation
+ * with one of the AbsTime constructors). However trying to add 2 AbsTimes
+ * doesn't make sense.
+ */
+class AbsTime {
+ friend class Duration;
+ friend class Condition;
+
+ TimePrivate timepoint;
+
+public:
+
+ inline AbsTime() : timepoint() {}
+ QPID_COMMON_EXTERN AbsTime(const AbsTime& time0, const Duration& duration);
+ // Default assignment operation fine
+ // Default copy constructor fine
+
+ QPID_COMMON_EXTERN static AbsTime now();
+ QPID_COMMON_EXTERN static AbsTime FarFuture();
+ QPID_COMMON_EXTERN static AbsTime Epoch();
+
+ bool operator==(const AbsTime& t) const { return t.timepoint == timepoint; }
+
+ friend bool operator<(const AbsTime& a, const AbsTime& b);
+ friend bool operator>(const AbsTime& a, const AbsTime& b);
+ QPID_COMMON_EXTERN friend std::ostream& operator << (std::ostream&, const AbsTime&);
+};
+
+QPID_COMMON_EXTERN std::ostream& operator << (std::ostream&, const AbsTime&);
+
+/**
+ * @class Duration
+ * Class to represent the duration between instants of time.
+ *
+ * As AbsTime, this class also uses nanosecs for its time
+ * resolution where possible. For the most part a duration can be dealt
+ * with like a 64 bit integer, and indeed there is an implicit conversion which
+ * makes this quite convenient.
+ */
+class Duration {
+ static int64_t max() { return std::numeric_limits<int64_t>::max(); }
+ int64_t nanosecs;
+
+ friend class AbsTime;
+
+public:
+ QPID_COMMON_INLINE_EXTERN inline Duration(int64_t time0 = 0);
+ QPID_COMMON_EXTERN explicit Duration(const AbsTime& start, const AbsTime& finish);
+ inline operator int64_t() const;
+};
+
+QPID_COMMON_EXTERN std::ostream& operator << (std::ostream&, const Duration&);
+QPID_COMMON_EXTERN std::istream& operator >> (std::istream&, Duration&);
+
+inline AbsTime now() { return AbsTime::now(); }
+
+inline bool operator<(const AbsTime& a, const AbsTime& b)
+{ return a.timepoint < b.timepoint; }
+inline bool operator>(const AbsTime& a, const AbsTime& b)
+{ return a.timepoint > b.timepoint; }
+
+Duration::Duration(int64_t time0) :
+ nanosecs(time0)
+{}
+
+Duration::operator int64_t() const
+{ return nanosecs; }
+
+/** Nanoseconds per second. */
+const Duration TIME_SEC = 1000*1000*1000;
+/** Nanoseconds per millisecond */
+const Duration TIME_MSEC = 1000*1000;
+/** Nanoseconds per microseconds. */
+const Duration TIME_USEC = 1000;
+/** Nanoseconds per nanosecond. */
+const Duration TIME_NSEC = 1;
+
+/** Value to represent an infinite timeout */
+const Duration TIME_INFINITE = std::numeric_limits<int64_t>::max();
+
+/** Absolute time point for the Unix epoch: 1970-01-01T00:00:00 */
+const AbsTime EPOCH = AbsTime::Epoch();
+
+/** Time greater than any other time */
+const AbsTime FAR_FUTURE = AbsTime::FarFuture();
+
+/** Portable sleep for a number of seconds */
+QPID_COMMON_EXTERN void sleep(int secs);
+
+/** Portable sleep for a number of microseconds */
+QPID_COMMON_EXTERN void usleep(uint64_t usecs);
+
+/** Output formatted date/time for now*/
+void outputFormattedNow(std::ostream&);
+
+/** Output unformatted nanosecond-resolution time for now */
+void outputHiresNow(std::ostream&);
+
+}}
+
+#endif /*!_sys_Time_h*/
diff --git a/qpid/cpp/src/qpid/sys/posix/Condition.h b/qpid/cpp/src/qpid/sys/posix/Condition.h
new file mode 100644
index 0000000000..36e7557ffd
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/posix/Condition.h
@@ -0,0 +1,86 @@
+#ifndef _sys_posix_Condition_h
+#define _sys_posix_Condition_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/sys/posix/PrivatePosix.h"
+
+#include "qpid/sys/Mutex.h"
+#include "qpid/sys/Time.h"
+
+#include <time.h>
+#include <sys/errno.h>
+#include <boost/noncopyable.hpp>
+
+namespace qpid {
+namespace sys {
+
+/**
+ * A condition variable for thread synchronization.
+ */
+class Condition
+{
+ public:
+ inline Condition();
+ inline ~Condition();
+ inline void wait(Mutex&);
+ inline bool wait(Mutex&, const AbsTime& absoluteTime);
+ inline void notify();
+ inline void notifyAll();
+
+ private:
+ pthread_cond_t condition;
+};
+
+Condition::Condition() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_cond_init(&condition, 0));
+}
+
+Condition::~Condition() {
+ QPID_POSIX_ABORT_IF(pthread_cond_destroy(&condition));
+}
+
+void Condition::wait(Mutex& mutex) {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_cond_wait(&condition, &mutex.mutex));
+}
+
+bool Condition::wait(Mutex& mutex, const AbsTime& absoluteTime){
+ struct timespec ts;
+ toTimespec(ts, Duration(EPOCH, absoluteTime));
+ int status = pthread_cond_timedwait(&condition, &mutex.mutex, &ts);
+ if (status != 0) {
+ if (status == ETIMEDOUT) return false;
+ throw QPID_POSIX_ERROR(status);
+ }
+ return true;
+}
+
+void Condition::notify(){
+ QPID_POSIX_ASSERT_THROW_IF(pthread_cond_signal(&condition));
+}
+
+void Condition::notifyAll(){
+ QPID_POSIX_ASSERT_THROW_IF(pthread_cond_broadcast(&condition));
+}
+
+}}
+#endif /*!_sys_posix_Condition_h*/
diff --git a/qpid/cpp/src/qpid/sys/posix/Mutex.h b/qpid/cpp/src/qpid/sys/posix/Mutex.h
new file mode 100644
index 0000000000..e2b21b5a56
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/posix/Mutex.h
@@ -0,0 +1,158 @@
+#ifndef _sys_posix_Mutex_h
+#define _sys_posix_Mutex_h
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/sys/posix/check.h"
+
+#include <pthread.h>
+#include <boost/noncopyable.hpp>
+
+namespace qpid {
+namespace sys {
+
+class Condition;
+
+/**
+ * Mutex lock.
+ */
+class Mutex : private boost::noncopyable {
+ friend class Condition;
+ static const pthread_mutexattr_t* getAttribute();
+
+public:
+ typedef ::qpid::sys::ScopedLock<Mutex> ScopedLock;
+ typedef ::qpid::sys::ScopedUnlock<Mutex> ScopedUnlock;
+
+ inline Mutex();
+ inline ~Mutex();
+ inline void lock();
+ inline void unlock();
+ inline bool trylock();
+
+
+protected:
+ pthread_mutex_t mutex;
+};
+
+/**
+ * RW lock.
+ */
+class RWlock : private boost::noncopyable {
+ friend class Condition;
+
+public:
+ typedef ::qpid::sys::ScopedRlock<RWlock> ScopedRlock;
+ typedef ::qpid::sys::ScopedWlock<RWlock> ScopedWlock;
+
+ inline RWlock();
+ inline ~RWlock();
+ inline void wlock(); // will write-lock
+ inline void rlock(); // will read-lock
+ inline void unlock();
+ inline void trywlock(); // will write-try
+ inline void tryrlock(); // will read-try
+
+protected:
+ pthread_rwlock_t rwlock;
+};
+
+
+/**
+ * PODMutex is a POD, can be static-initialized with
+ * PODMutex m = QPID_PODMUTEX_INITIALIZER
+ */
+struct PODMutex
+{
+ typedef ::qpid::sys::ScopedLock<PODMutex> ScopedLock;
+
+ inline void lock();
+ inline void unlock();
+ inline bool trylock();
+
+ // Must be public to be a POD:
+ pthread_mutex_t mutex;
+};
+
+#define QPID_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
+
+void PODMutex::lock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_mutex_lock(&mutex));
+}
+
+void PODMutex::unlock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_mutex_unlock(&mutex));
+}
+
+bool PODMutex::trylock() {
+ return pthread_mutex_trylock(&mutex) == 0;
+}
+
+Mutex::Mutex() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_mutex_init(&mutex, getAttribute()));
+}
+
+Mutex::~Mutex(){
+ QPID_POSIX_ABORT_IF(pthread_mutex_destroy(&mutex));
+}
+
+void Mutex::lock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_mutex_lock(&mutex));
+}
+
+void Mutex::unlock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_mutex_unlock(&mutex));
+}
+
+bool Mutex::trylock() {
+ return pthread_mutex_trylock(&mutex) == 0;
+}
+
+
+RWlock::RWlock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_rwlock_init(&rwlock, NULL));
+}
+
+RWlock::~RWlock(){
+ QPID_POSIX_ABORT_IF(pthread_rwlock_destroy(&rwlock));
+}
+
+void RWlock::wlock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_rwlock_wrlock(&rwlock));
+}
+
+void RWlock::rlock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_rwlock_rdlock(&rwlock));
+}
+
+void RWlock::unlock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_rwlock_unlock(&rwlock));
+}
+
+void RWlock::trywlock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_rwlock_trywrlock(&rwlock));
+}
+
+void RWlock::tryrlock() {
+ QPID_POSIX_ASSERT_THROW_IF(pthread_rwlock_tryrdlock(&rwlock));
+}
+
+
+}}
+#endif /*!_sys_posix_Mutex_h*/
diff --git a/qpid/cpp/src/qpid/sys/posix/PrivatePosix.h b/qpid/cpp/src/qpid/sys/posix/PrivatePosix.h
new file mode 100644
index 0000000000..0f59fe3176
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/posix/PrivatePosix.h
@@ -0,0 +1,65 @@
+#ifndef _sys_posix_PrivatePosix_h
+#define _sys_posix_PrivatePosix_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/sys/Time.h"
+
+struct timespec;
+struct timeval;
+struct addrinfo;
+
+namespace qpid {
+namespace sys {
+
+// Private Time related implementation details
+struct timespec& toTimespec(struct timespec& ts, const Duration& t);
+struct timeval& toTimeval(struct timeval& tv, const Duration& t);
+Duration toTime(const struct timespec& ts);
+
+// Private SocketAddress details
+class SocketAddress;
+const struct addrinfo& getAddrInfo(const SocketAddress&);
+
+// Posix fd as an IOHandle
+class IOHandle {
+public:
+ IOHandle(int fd0 = -1) :
+ fd(fd0)
+ {}
+
+ int fd;
+};
+
+// Dummy IOHandle for places it's required in the API
+// but we promise not to actually try to do any operations on the IOHandle
+class NullIOHandle : public IOHandle {
+public:
+ NullIOHandle()
+ {}
+};
+
+extern NullIOHandle DummyIOHandle;
+
+}}
+
+#endif /*!_sys_posix_PrivatePosix_h*/
diff --git a/qpid/cpp/src/qpid/sys/posix/Time.h b/qpid/cpp/src/qpid/sys/posix/Time.h
new file mode 100755
index 0000000000..62d734c816
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/posix/Time.h
@@ -0,0 +1,34 @@
+#ifndef QPID_SYS_POSIX_TIME_H
+#define QPID_SYS_POSIX_TIME_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/sys/IntegerTypes.h"
+
+namespace qpid {
+namespace sys {
+
+/**
+ * Class to represent an instant in time.
+ */
+typedef int64_t TimePrivate;
+
+}} // namespace qpid::sys
+
+#endif /*!QPID_SYS_POSIX_TIME_H*/
diff --git a/qpid/cpp/src/qpid/sys/posix/check.h b/qpid/cpp/src/qpid/sys/posix/check.h
new file mode 100644
index 0000000000..1bfe5d6d78
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/posix/check.h
@@ -0,0 +1,53 @@
+#ifndef _posix_check_h
+#define _posix_check_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/Exception.h"
+#include "qpid/Msg.h"
+
+#include <cerrno>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define QPID_POSIX_ERROR(ERRNO) qpid::Exception(QPID_MSG(qpid::sys::strError(ERRNO)))
+
+/** THROW QPID_POSIX_ERROR(errno) if RESULT is less than zero */
+#define QPID_POSIX_CHECK(RESULT) \
+ if ((RESULT) < 0) throw QPID_POSIX_ERROR((errno))
+
+/** Throw a posix error if ERRNO is non-zero */
+#define QPID_POSIX_THROW_IF(ERRNO) \
+ do { int e=(ERRNO); if (e) throw QPID_POSIX_ERROR(e); } while(0)
+
+/** Same as _THROW_IF in a release build, but abort a debug build */
+#ifdef NDEBUG
+#define QPID_POSIX_ASSERT_THROW_IF(ERRNO) QPID_POSIX_THROW_IF(ERRNO)
+#else
+#define QPID_POSIX_ASSERT_THROW_IF(ERRNO) \
+ do { int e=(ERRNO); if (e) { errno=e; ::perror(0); assert(0); } } while(0)
+#endif
+
+#define QPID_POSIX_ABORT_IF(ERRNO) if ((int) ERRNO) { errno=ERRNO; ::perror(0); abort(); }
+
+#endif /*!_posix_check_h*/
diff --git a/qpid/cpp/src/qpid/sys/windows/Condition.h b/qpid/cpp/src/qpid/sys/windows/Condition.h
new file mode 100755
index 0000000000..cd5aebbf09
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/windows/Condition.h
@@ -0,0 +1,77 @@
+#ifndef _sys_windows_Condition_h
+#define _sys_windows_Condition_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/sys/Mutex.h"
+#include "qpid/sys/Time.h"
+
+#include <time.h>
+#include <boost/noncopyable.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <windows.h>
+
+namespace qpid {
+namespace sys {
+
+/**
+ * A condition variable for thread synchronization.
+ */
+class Condition : private boost::noncopyable
+{
+ public:
+ inline Condition();
+ inline ~Condition();
+ inline void wait(Mutex&);
+ inline bool wait(Mutex&, const AbsTime& absoluteTime);
+ inline void notify();
+ inline void notifyAll();
+
+ private:
+ boost::condition_variable_any condition;
+};
+
+Condition::Condition() {
+}
+
+Condition::~Condition() {
+}
+
+void Condition::wait(Mutex& mutex) {
+ condition.wait(mutex.mutex);
+}
+
+bool Condition::wait(Mutex& mutex, const AbsTime& absoluteTime){
+ return condition.timed_wait(mutex.mutex, absoluteTime.timepoint);
+}
+
+void Condition::notify(){
+ condition.notify_one();
+}
+
+void Condition::notifyAll(){
+ condition.notify_all();
+}
+
+}}
+#endif /*!_sys_windows_Condition_h*/
diff --git a/qpid/cpp/src/qpid/sys/windows/Mutex.h b/qpid/cpp/src/qpid/sys/windows/Mutex.h
new file mode 100755
index 0000000000..5dcc69e836
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/windows/Mutex.h
@@ -0,0 +1,188 @@
+#ifndef _sys_windows_Mutex_h
+#define _sys_windows_Mutex_h
+
+/*
+ *
+ * Copyright (c) 2008 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/sys/windows/check.h"
+
+#include <boost/version.hpp>
+#if (BOOST_VERSION < 103500)
+#error The Windows port requires Boost version 1.35.0 or later
+#endif
+
+#include <boost/noncopyable.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/thread/tss.hpp>
+
+namespace qpid {
+namespace sys {
+
+class Condition;
+
+/**
+ * Mutex lock.
+ */
+class Mutex : private boost::noncopyable {
+ friend class Condition;
+
+public:
+ typedef ::qpid::sys::ScopedLock<Mutex> ScopedLock;
+ typedef ::qpid::sys::ScopedUnlock<Mutex> ScopedUnlock;
+
+ inline Mutex();
+ inline ~Mutex();
+ inline void lock();
+ inline void unlock();
+ inline bool trylock();
+
+
+protected:
+ boost::recursive_mutex mutex;
+};
+
+/**
+ * RW lock.
+ */
+class RWlock : private boost::noncopyable {
+ friend class Condition;
+
+public:
+ typedef ::qpid::sys::ScopedRlock<RWlock> ScopedRlock;
+ typedef ::qpid::sys::ScopedWlock<RWlock> ScopedWlock;
+
+ inline RWlock();
+ inline ~RWlock();
+ inline void wlock(); // will write-lock
+ inline void rlock(); // will read-lock
+ inline void unlock();
+ inline void trywlock(); // will write-try
+ inline void tryrlock(); // will read-try
+
+protected:
+ boost::shared_mutex rwMutex;
+ boost::thread_specific_ptr<bool> haveWrite;
+
+ inline bool &write (void);
+};
+
+
+/**
+ * PODMutex is a POD, can be static-initialized with
+ * PODMutex m = QPID_PODMUTEX_INITIALIZER
+ */
+struct PODMutex
+{
+ typedef ::qpid::sys::ScopedLock<PODMutex> ScopedLock;
+
+ inline void lock();
+ inline void unlock();
+ inline bool trylock();
+
+ // Must be public to be a POD:
+ boost::recursive_mutex mutex;
+};
+
+#define QPID_MUTEX_INITIALIZER 0
+
+void PODMutex::lock() {
+ mutex.lock();
+}
+
+void PODMutex::unlock() {
+ mutex.unlock();
+}
+
+bool PODMutex::trylock() {
+ return mutex.try_lock();
+}
+
+Mutex::Mutex() {
+}
+
+Mutex::~Mutex(){
+}
+
+void Mutex::lock() {
+ mutex.lock();
+}
+
+void Mutex::unlock() {
+ mutex.unlock();
+}
+
+bool Mutex::trylock() {
+ return mutex.try_lock();
+}
+
+
+RWlock::RWlock() {
+}
+
+RWlock::~RWlock(){
+}
+
+void RWlock::wlock() {
+ bool &writer = write();
+ rwMutex.lock();
+ writer = true; // Remember this thread has write lock held.
+}
+
+void RWlock::rlock() {
+ bool &writer = write();
+ rwMutex.lock_shared();
+ writer = false; // Remember this thread has shared lock held.
+}
+
+void RWlock::unlock() {
+ bool &writer = write();
+ if (writer)
+ rwMutex.unlock();
+ else
+ rwMutex.unlock_shared();
+}
+
+void RWlock::trywlock() {
+ bool &writer = write();
+ // shared_mutex::try_lock() seems to not be available... emulate it with
+ // a timed lock().
+ boost::system_time now = boost::get_system_time();
+ if (rwMutex.timed_lock(now))
+ writer = true;
+}
+
+void RWlock::tryrlock() {
+ bool &writer = write();
+ if (rwMutex.try_lock_shared())
+ writer = false;
+}
+
+bool & RWlock::write (void) {
+ // Accessing thread-specific and stack-local info, so no locks needed.
+ bool *writePtr = haveWrite.get();
+ if (writePtr == 0) {
+ writePtr = new bool(false);
+ haveWrite.reset(writePtr);
+ }
+ return *writePtr;
+}
+
+}}
+#endif /*!_sys_windows_Mutex_h*/
diff --git a/qpid/cpp/src/qpid/sys/windows/Time.h b/qpid/cpp/src/qpid/sys/windows/Time.h
new file mode 100644
index 0000000000..2987b1c8b2
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/windows/Time.h
@@ -0,0 +1,36 @@
+#ifndef QPID_SYS_WINDOWS_TIME_H
+#define QPID_SYS_WINDOWS_TIME_H
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+namespace qpid {
+namespace sys {
+
+/**
+ * Class to represent an instant in time. Boost has this stuff already done
+ * so just reuse it. We can also grab this for quick use with the Condition
+ * wait operations.
+ */
+typedef boost::posix_time::ptime TimePrivate;
+
+}} // namespace qpid::sys
+
+#endif /*!QPID_SYS_WINDOWS_TIME_H*/
diff --git a/qpid/cpp/src/qpid/sys/windows/check.h b/qpid/cpp/src/qpid/sys/windows/check.h
new file mode 100755
index 0000000000..2a8e439bed
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/windows/check.h
@@ -0,0 +1,49 @@
+#ifndef _windows_check_h
+#define _windows_check_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/Exception.h"
+#include "qpid/Msg.h"
+#include "qpid/sys/StrError.h"
+
+#define QPID_WINDOWS_ERROR(ERRVAL) qpid::Exception(QPID_MSG(qpid::sys::strError(ERRVAL)))
+#define QPID_WINDOWS_CRT_ERROR(ERRNO) qpid::Exception(QPID_MSG(qpid::sys::strError(ERRNO)))
+
+/** THROW QPID_WINDOWS_ERROR(::GetLastError()) if RESULT is NULL */
+#define QPID_WINDOWS_CHECK_NULL(RESULT) \
+ if ((RESULT) == NULL) throw QPID_WINDOWS_ERROR((::GetLastError()))
+
+#define QPID_WINDOWS_CHECK_NOT(RESULT,VAL) \
+ if ((RESULT) == (VAL)) throw QPID_WINDOWS_ERROR((::GetLastError()))
+
+#define QPID_WINDOWS_CHECK_ASYNC_START(STATUS) \
+ if (!(STATUS) && ::WSAGetLastError() != ERROR_IO_PENDING) \
+ throw QPID_WINDOWS_ERROR((::WSAGetLastError()))
+
+#define QPID_WINDOWS_CHECK_CRT_NZ(VAL) \
+ if ((VAL) == 0) throw QPID_WINDOWS_CRT_ERROR(errno)
+
+#define QPID_WINSOCK_CHECK(OP) \
+ if ((OP) == SOCKET_ERROR) throw QPID_WINDOWS_ERROR((::WSAGetLastError()))
+
+#endif /*!_windows_check_h*/
diff --git a/qpid/cpp/src/qpid/types/Uuid.cpp b/qpid/cpp/src/qpid/types/Uuid.cpp
index 1d6fbf430a..875e5925a9 100644
--- a/qpid/cpp/src/qpid/types/Uuid.cpp
+++ b/qpid/cpp/src/qpid/types/Uuid.cpp
@@ -52,6 +52,11 @@ Uuid::Uuid(const unsigned char* uuid)
::memcpy(bytes, uuid, Uuid::SIZE);
}
+Uuid::Uuid(const char* uuid)
+{
+ ::memcpy(bytes, uuid, Uuid::SIZE);
+}
+
Uuid& Uuid::operator=(const Uuid& other)
{
if (this == &other) return *this;
diff --git a/qpid/cpp/src/qpid/types/Variant.cpp b/qpid/cpp/src/qpid/types/Variant.cpp
index 7a5f36851a..292bb5ef09 100644
--- a/qpid/cpp/src/qpid/types/Variant.cpp
+++ b/qpid/cpp/src/qpid/types/Variant.cpp
@@ -36,6 +36,7 @@ const std::string PREFIX("invalid conversion: ");
}
InvalidConversion::InvalidConversion(const std::string& msg) : Exception(PREFIX + msg) {}
+InvalidConversion::~InvalidConversion() throw() {}
class VariantImpl
{
diff --git a/qpid/cpp/src/qpid/types/encodings.h b/qpid/cpp/src/qpid/types/encodings.h
new file mode 100644
index 0000000000..827b6964b9
--- /dev/null
+++ b/qpid/cpp/src/qpid/types/encodings.h
@@ -0,0 +1,33 @@
+#ifndef QPID_TYPES_ENCODINGS_H
+#define QPID_TYPES_ENCODINGS_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+namespace qpid {
+namespace types {
+namespace encodings {
+const std::string BINARY("binary");
+const std::string UTF8("utf8");
+const std::string ASCII("ascii");
+}
+}} // namespace qpid::types
+
+#endif /*!QPID_TYPES_ENCODINGS_H*/
diff --git a/qpid/cpp/src/qpid/xml/XmlExchange.cpp b/qpid/cpp/src/qpid/xml/XmlExchange.cpp
index 29ab859591..3802ec5f7f 100644
--- a/qpid/cpp/src/qpid/xml/XmlExchange.cpp
+++ b/qpid/cpp/src/qpid/xml/XmlExchange.cpp
@@ -372,6 +372,8 @@ bool XmlExchange::isBound(Queue::shared_ptr queue, const std::string* const bind
XmlExchange::~XmlExchange()
{
+ if (mgmtExchange != 0)
+ mgmtExchange->debugStats("destroying");
bindingsMap.clear();
}
diff --git a/qpid/cpp/src/rdma.cmake b/qpid/cpp/src/rdma.cmake
index 8c019020f1..7c0ec66bf9 100644
--- a/qpid/cpp/src/rdma.cmake
+++ b/qpid/cpp/src/rdma.cmake
@@ -78,7 +78,7 @@ if (BUILD_RDMA)
COMPONENT ${QPID_COMPONENT_COMMON})
add_library (rdma MODULE qpid/sys/RdmaIOPlugin.cpp)
- target_link_libraries (rdma qpidbroker rdmawrap)
+ target_link_libraries (rdma qpidbroker qpidcommon rdmawrap)
set_target_properties (rdma PROPERTIES
COMPILE_DEFINITIONS _IN_QPID_BROKER
LINK_FLAGS "${CATCH_UNDEFINED}"
@@ -94,7 +94,7 @@ if (BUILD_RDMA)
COMPONENT ${QPID_COMPONENT_BROKER})
add_library (rdmaconnector MODULE qpid/client/RdmaConnector.cpp)
- target_link_libraries (rdmaconnector qpidclient rdmawrap)
+ target_link_libraries (rdmaconnector qpidclient qpidcommon rdmawrap)
set_target_properties (rdmaconnector PROPERTIES
LINK_FLAGS "${CATCH_UNDEFINED}"
PREFIX "")
diff --git a/qpid/cpp/src/ssl.mk b/qpid/cpp/src/ssl.mk
deleted file mode 100644
index 9a92c7abc7..0000000000
--- a/qpid/cpp/src/ssl.mk
+++ /dev/null
@@ -1,47 +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.
-#
-#
-# Makefile fragment, conditionally included in Makefile.am
-#
-libqpidcommon_la_SOURCES += \
- qpid/sys/ssl/check.h \
- qpid/sys/ssl/check.cpp \
- qpid/sys/ssl/util.h \
- qpid/sys/ssl/util.cpp \
- qpid/sys/ssl/SslSocket.h \
- qpid/sys/ssl/SslSocket.cpp
-
-libqpidcommon_la_LIBADD += -lnss3 -lssl3 -lnspr4
-libqpidcommon_la_CXXFLAGS += $(SSL_CFLAGS)
-
-libqpidbroker_la_SOURCES += \
- qpid/sys/SslPlugin.cpp
-
-libqpidbroker_la_CXXFLAGS += $(SSL_CFLAGS)
-
-libqpidclient_la_SOURCES += \
- qpid/client/SslConnector.cpp
-
-libqpidclient_la_CXXFLAGS += $(SSL_CFLAGS)
-
-if HAVE_PROTON
-libqpidclient_la_SOURCES += \
- qpid/messaging/amqp/SslTransport.cpp \
- qpid/messaging/amqp/SslTransport.h
-endif #HAVE_PROTON
diff --git a/qpid/cpp/src/tests/BrokerFixture.h b/qpid/cpp/src/tests/BrokerFixture.h
index bc23867ee1..b7b0f9d34b 100644
--- a/qpid/cpp/src/tests/BrokerFixture.h
+++ b/qpid/cpp/src/tests/BrokerFixture.h
@@ -42,11 +42,45 @@ namespace tests {
struct BrokerFixture : private boost::noncopyable {
typedef qpid::broker::Broker Broker;
typedef boost::intrusive_ptr<Broker> BrokerPtr;
+ typedef std::vector<std::string> Args;
BrokerPtr broker;
+ uint16_t port;
qpid::sys::Thread brokerThread;
- BrokerFixture(Broker::Options opts=Broker::Options(), bool enableMgmt=false) {
+ BrokerFixture(const Args& args=Args(), const Broker::Options& opts=Broker::Options(),
+ bool isExternalPort_=false, uint16_t externalPort_=0)
+ {
+ init(args, opts, isExternalPort_, externalPort_);
+ }
+
+ BrokerFixture(const Broker::Options& opts,
+ bool isExternalPort_=false, uint16_t externalPort_=0)
+ {
+ init(Args(), opts, isExternalPort_, externalPort_);
+ }
+
+ void shutdownBroker() {
+ if (broker) {
+ broker->shutdown();
+ brokerThread.join();
+ broker = BrokerPtr();
+ }
+ }
+
+ ~BrokerFixture() { shutdownBroker(); }
+
+ /** Open a connection to the broker. */
+ void open(qpid::client::Connection& c) {
+ c.open("localhost", getPort());
+ }
+
+ uint16_t getPort() { return port; }
+
+ private:
+ void init(const Args& args, Broker::Options opts,
+ bool isExternalPort=false, uint16_t externalPort=0)
+ {
// Keep the tests quiet unless logging env. vars have been set by user.
if (!::getenv("QPID_LOG_ENABLE") && !::getenv("QPID_TRACE")) {
qpid::log::Options logOpts;
@@ -55,38 +89,28 @@ struct BrokerFixture : private boost::noncopyable {
logOpts.selectors.push_back("error+");
qpid::log::Logger::instance().configure(logOpts);
}
+ // Default options, may be over-ridden when we parse args.
opts.port=0;
opts.listenInterfaces.push_back("127.0.0.1");
- // Management doesn't play well with multiple in-process brokers.
- opts.enableMgmt=enableMgmt;
opts.workerThreads=1;
opts.dataDir="";
opts.auth=false;
+
+ // Argument parsing
+ std::vector<const char*> argv(args.size());
+ std::transform(args.begin(), args.end(), argv.begin(),
+ boost::bind(&std::string::c_str, _1));
+ Plugin::addOptions(opts);
+ opts.parse(argv.size(), &argv[0]);
broker = Broker::create(opts);
// TODO aconway 2007-12-05: At one point BrokerFixture
// tests could hang in Connection ctor if the following
// line is removed. This may not be an issue anymore.
broker->accept();
- broker->getPort(qpid::broker::Broker::TCP_TRANSPORT);
+ if (isExternalPort) port = externalPort;
+ else port = broker->getPort(qpid::broker::Broker::TCP_TRANSPORT);
brokerThread = qpid::sys::Thread(*broker);
};
-
- void shutdownBroker() {
- if (broker) {
- broker->shutdown();
- brokerThread.join();
- broker = BrokerPtr();
- }
- }
-
- ~BrokerFixture() { shutdownBroker(); }
-
- /** Open a connection to the broker. */
- void open(qpid::client::Connection& c) {
- c.open("localhost", broker->getPort(qpid::broker::Broker::TCP_TRANSPORT));
- }
-
- uint16_t getPort() { return broker->getPort(qpid::broker::Broker::TCP_TRANSPORT); }
};
/** Connection that opens in its constructor */
@@ -125,8 +149,8 @@ template <class ConnectionType, class SessionType=qpid::client::Session>
struct SessionFixtureT : BrokerFixture, ClientT<ConnectionType,SessionType> {
SessionFixtureT(Broker::Options opts=Broker::Options()) :
- BrokerFixture(opts),
- ClientT<ConnectionType,SessionType>(broker->getPort(qpid::broker::Broker::TCP_TRANSPORT))
+ BrokerFixture(BrokerFixture::Args(), opts),
+ ClientT<ConnectionType,SessionType>(getPort())
{}
};
diff --git a/qpid/cpp/src/tests/BrokerMgmtAgent.cpp b/qpid/cpp/src/tests/BrokerMgmtAgent.cpp
index 29c3faf809..bad7e768a6 100644
--- a/qpid/cpp/src/tests/BrokerMgmtAgent.cpp
+++ b/qpid/cpp/src/tests/BrokerMgmtAgent.cpp
@@ -63,6 +63,7 @@ class AgentFixture
qpid::broker::Broker::Options opts = qpid::broker::Broker::Options())
{
opts.enableMgmt=true;
+ opts.qmf1Support=!qmfV2;
opts.qmf2Support=qmfV2;
opts.mgmtPubInterval=pubInterval;
mFix = new MessagingFixture(opts, true);
diff --git a/qpid/cpp/src/tests/CMakeLists.txt b/qpid/cpp/src/tests/CMakeLists.txt
index 4763bc0b80..281464e65a 100644
--- a/qpid/cpp/src/tests/CMakeLists.txt
+++ b/qpid/cpp/src/tests/CMakeLists.txt
@@ -108,7 +108,6 @@ set(all_unit_tests
ClientMessage
ClientMessageTest
ClientSessionTest
- ConsoleTest
DeliveryRecordTest
DtxWorkRecordTest
exception_test
@@ -147,6 +146,7 @@ set(all_unit_tests
TimerTest
TopicExchangeTest
TxBufferTest
+ TransactionObserverTest
Url
Uuid
Variant
@@ -171,7 +171,7 @@ add_executable (unit_test unit_test
${actual_unit_tests} ${platform_test_additions})
target_link_libraries (unit_test
${qpid_test_boost_libs}
- qpidmessaging qpidbroker qmfconsole)
+ qpidmessaging qpidtypes qpidbroker qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
set_target_properties (unit_test PROPERTIES COMPILE_DEFINITIONS _IN_QPID_BROKER)
remember_location(unit_test)
@@ -191,105 +191,104 @@ endif (BUILD_SASL)
# Other test programs
#
add_executable (qpid-perftest qpid-perftest.cpp ${platform_test_additions})
-target_link_libraries (qpid-perftest qpidclient)
+target_link_libraries (qpid-perftest qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#qpid_perftest_SOURCES=qpid-perftest.cpp test_tools.h TestOptions.h ConnectionOptions.h
remember_location(qpid-perftest)
add_executable (qpid-txtest qpid-txtest.cpp ${platform_test_additions})
-target_link_libraries (qpid-txtest qpidclient)
+target_link_libraries (qpid-txtest qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#qpid_txtest_SOURCES=qpid-txtest.cpp TestOptions.h ConnectionOptions.h
remember_location(qpid-txtest)
add_executable (qpid-latency-test qpid-latency-test.cpp ${platform_test_additions})
-target_link_libraries (qpid-latency-test qpidclient)
+target_link_libraries (qpid-latency-test qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#qpid_latencytest_SOURCES=qpid-latency-test.cpp TestOptions.h ConnectionOptions.h
remember_location(qpid-latency-test)
add_executable (echotest echotest.cpp ${platform_test_additions})
-target_link_libraries (echotest qpidclient)
+target_link_libraries (echotest qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#echotest_SOURCES=echotest.cpp TestOptions.h ConnectionOptions.h
remember_location(echotest)
add_executable (qpid-client-test qpid-client-test.cpp ${platform_test_additions})
-target_link_libraries (qpid-client-test qpidclient)
+target_link_libraries (qpid-client-test qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#qpid_client_test_SOURCES=qpid-client-test.cpp TestOptions.h ConnectionOptions.h
remember_location(qpid-client-test)
add_executable (qpid-topic-listener qpid-topic-listener.cpp ${platform_test_additions})
-target_link_libraries (qpid-topic-listener qpidclient)
+target_link_libraries (qpid-topic-listener qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#qpid_topic_listener_SOURCES=qpid-topic-listener.cpp TestOptions.h ConnectionOptions.h
remember_location(qpid-topic-listener)
add_executable (qpid-topic-publisher qpid-topic-publisher.cpp ${platform_test_additions})
-target_link_libraries (qpid-topic-publisher qpidclient)
+target_link_libraries (qpid-topic-publisher qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#qpid_topic_publisher_SOURCES=qpid-topic-publisher.cpp TestOptions.h ConnectionOptions.h
remember_location(qpid-topic-publisher)
add_executable (publish publish.cpp ${platform_test_additions})
-target_link_libraries (publish qpidclient)
+target_link_libraries (publish qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#publish_SOURCES=publish.cpp TestOptions.h ConnectionOptions.h
remember_location(publish)
add_executable (consume consume.cpp ${platform_test_additions})
-target_link_libraries (consume qpidclient)
+target_link_libraries (consume qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#consume_SOURCES=consume.cpp TestOptions.h ConnectionOptions.h
remember_location(consume)
add_executable (header_test header_test.cpp ${platform_test_additions})
-target_link_libraries (header_test qpidclient)
+target_link_libraries (header_test qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#header_test_SOURCES=header_test.cpp TestOptions.h ConnectionOptions.h
remember_location(header_test)
add_executable (declare_queues declare_queues.cpp ${platform_test_additions})
-target_link_libraries (declare_queues qpidclient)
+target_link_libraries (declare_queues qpidclient qpidcommon)
remember_location(declare_queues)
add_executable (replaying_sender replaying_sender.cpp ${platform_test_additions})
-target_link_libraries (replaying_sender qpidclient)
+target_link_libraries (replaying_sender qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
remember_location(replaying_sender)
add_executable (resuming_receiver resuming_receiver.cpp ${platform_test_additions})
-target_link_libraries (resuming_receiver qpidclient)
+target_link_libraries (resuming_receiver qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
remember_location(resuming_receiver)
add_executable (txshift txshift.cpp ${platform_test_additions})
-target_link_libraries (txshift qpidclient)
+target_link_libraries (txshift qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#txshift_SOURCES=txshift.cpp TestOptions.h ConnectionOptions.h
remember_location(txshift)
add_executable (txjob txjob.cpp ${platform_test_additions})
-target_link_libraries (txjob qpidclient)
+target_link_libraries (txjob qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
#txjob_SOURCES=txjob.cpp TestOptions.h ConnectionOptions.h
remember_location(txjob)
add_executable (receiver receiver.cpp ${platform_test_additions})
-target_link_libraries (receiver qpidclient)
-#receiver_SOURCES=receiver.cpp TestOptions.h ConnectionOptions.h
+target_link_libraries (receiver qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
remember_location(receiver)
+# This is bizarre - using both messaging and client libraries
add_executable (sender sender.cpp Statistics.cpp ${platform_test_additions})
-target_link_libraries (sender qpidmessaging)
-#sender_SOURCES=sender.cpp TestOptions.h ConnectionOptions.h
+target_link_libraries (sender qpidmessaging qpidtypes qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
remember_location(sender)
add_executable (qpid-receive qpid-receive.cpp Statistics.cpp ${platform_test_additions})
-target_link_libraries (qpid-receive qpidmessaging)
+target_link_libraries (qpid-receive qpidmessaging qpidtypes qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
remember_location(qpid-receive)
add_executable (qpid-send qpid-send.cpp Statistics.cpp ${platform_test_additions})
-target_link_libraries (qpid-send qpidmessaging)
+target_link_libraries (qpid-send qpidmessaging qpidtypes qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
remember_location(qpid-send)
add_executable (qpid-ping qpid-ping.cpp ${platform_test_additions})
-target_link_libraries (qpid-ping qpidclient)
+target_link_libraries (qpid-ping qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
remember_location(qpid-ping)
add_executable (datagen datagen.cpp ${platform_test_additions})
-target_link_libraries (datagen qpidclient)
+target_link_libraries (datagen qpidclient qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
remember_location(datagen)
add_executable (msg_group_test msg_group_test.cpp ${platform_test_additions})
-target_link_libraries (msg_group_test qpidmessaging)
+target_link_libraries (msg_group_test qpidmessaging qpidtypes qpidcommon "${Boost_PROGRAM_OPTIONS_LIBRARY}")
remember_location(msg_group_test)
if (BUILD_SASL)
@@ -357,6 +356,7 @@ if (PYTHON_EXECUTABLE)
if (BUILD_AMQP)
add_test (interlink_tests ${test_wrap} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/interlink_tests.py)
endif (BUILD_AMQP)
+ add_test (swig_python_tests ${test_wrap} ${CMAKE_CURRENT_SOURCE_DIR}/swig_python_tests${test_script_suffix})
endif (PYTHON_EXECUTABLE)
add_test (ipv6_test ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/ipv6_test${test_script_suffix})
add_test (federation_tests ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_federation_tests${test_script_suffix})
@@ -378,24 +378,7 @@ add_test (queue_redirect ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_queue_redirect
add_library(test_store MODULE test_store.cpp)
target_link_libraries (test_store qpidbroker qpidcommon)
-set_target_properties (test_store PROPERTIES
- COMPILE_DEFINITIONS _IN_QPID_BROKER
- PREFIX "")
+set_target_properties (test_store PROPERTIES PREFIX "" COMPILE_DEFINITIONS _IN_QPID_BROKER)
add_library (dlclose_noop MODULE dlclose_noop.c)
-#libdlclose_noop_la_LDFLAGS = -module -rpath $(abs_builddir)
-
-#CLEANFILES+=valgrind.out *.log *.vglog* dummy_test $(unit_wrappers)
-#
-## Longer running stability tests, not run by default check: target.
-## Not run under valgrind, too slow
-#LONG_TESTS=fanout_perftest shared_perftest multiq_perftest topic_perftest
-#EXTRA_DIST+=$(LONG_TESTS) run_perftest
-#check-long:
-# $(MAKE) check TESTS="start_broker $(LONG_TESTS) stop_broker" VALGRIND=
-
-#
-# legacystore
-#
-# add_subdirectory(legacystore)
diff --git a/qpid/cpp/src/tests/ClientSessionTest.cpp b/qpid/cpp/src/tests/ClientSessionTest.cpp
index 2da96bf30c..2236882eed 100644
--- a/qpid/cpp/src/tests/ClientSessionTest.cpp
+++ b/qpid/cpp/src/tests/ClientSessionTest.cpp
@@ -37,6 +37,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/format.hpp>
#include <vector>
diff --git a/qpid/cpp/src/tests/Makefile.am b/qpid/cpp/src/tests/Makefile.am
deleted file mode 100644
index 808d9f9731..0000000000
--- a/qpid/cpp/src/tests/Makefile.am
+++ /dev/null
@@ -1,410 +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.
-#
-
-AM_CXXFLAGS = $(WARNING_CFLAGS) -DBOOST_TEST_DYN_LINK -D_IN_QPID_BROKER
-INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src
-PUBLIC_INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include # Use public API only
-QMF_GEN=$(top_srcdir)/managementgen/qmf-gen
-
-abs_builddir=@abs_builddir@
-abs_srcdir=@abs_srcdir@
-
-extra_libs =
-lib_client = $(abs_builddir)/../libqpidclient.la
-lib_messaging = $(abs_builddir)/../libqpidmessaging.la
-lib_types = $(abs_builddir)/../libqpidtypes.la
-lib_common = $(abs_builddir)/../libqpidcommon.la
-lib_broker = $(abs_builddir)/../libqpidbroker.la
-lib_console = $(abs_builddir)/../libqmfconsole.la
-lib_qmf2 = $(abs_builddir)/../libqmf2.la
-# lib_amqp_0_10 = $(abs_builddir)/../libqpidamqp_0_10.la
-
-#
-# Initialize variables that are incremented with +=
-#
-check_PROGRAMS=
-check_LTLIBRARIES=
-TESTS=
-EXTRA_DIST=
-CLEANFILES=
-LONG_TESTS=
-CLEAN_LOCAL=
-
-#
-# Destination for intalled programs and tests defined here
-#
-qpidexecdir = $(libexecdir)/qpid
-qpidexec_PROGRAMS =
-qpidexec_SCRIPTS =
-qpidexectestdir = $(qpidexecdir)/tests
-qpidexectest_PROGRAMS =
-qpidexectest_SCRIPTS =
-tmoduledir = $(libdir)/qpid/tests
-tmodule_LTLIBRARIES=
-
-#
-# Unit test program
-#
-# Unit tests are built as a single program to reduce valgrind overhead
-# when running the tests. If you want to build a subset of the tests do
-# rm -f unit_test; make unit_test unit_test_OBJECTS="unit_test.o SelectedTest.o"
-#
-
-TESTS+=unit_test
-check_PROGRAMS+=unit_test
-unit_test_LDADD=-lboost_unit_test_framework -lpthread \
- $(lib_messaging) $(lib_broker) $(lib_console) $(lib_qmf2)
-
-unit_test_SOURCES= unit_test.cpp unit_test.h \
- MessagingSessionTests.cpp \
- MessagingThreadTests.cpp \
- MessagingFixture.h \
- ClientSessionTest.cpp \
- BrokerFixture.h \
- exception_test.cpp \
- RefCounted.cpp \
- SessionState.cpp logging.cpp \
- AsyncCompletion.cpp \
- Url.cpp Uuid.cpp \
- Shlib.cpp FieldValue.cpp FieldTable.cpp Array.cpp \
- QueueOptionsTest.cpp \
- InlineAllocator.cpp \
- InlineVector.cpp \
- SequenceSet.cpp \
- StringUtils.cpp \
- RangeSet.cpp \
- AtomicValue.cpp \
- QueueTest.cpp \
- AccumulatedAckTest.cpp \
- DtxWorkRecordTest.cpp \
- DeliveryRecordTest.cpp \
- ExchangeTest.cpp \
- HeadersExchangeTest.cpp \
- MessageTest.cpp \
- QueueDepth.cpp \
- QueueRegistryTest.cpp \
- QueuePolicyTest.cpp \
- QueueFlowLimitTest.cpp \
- FramingTest.cpp \
- HeaderTest.cpp \
- SequenceNumberTest.cpp \
- TimerTest.cpp \
- TopicExchangeTest.cpp \
- TxBufferTest.cpp \
- ConnectionOptions.h \
- ManagementTest.cpp \
- MessageReplayTracker.cpp \
- ConsoleTest.cpp \
- ProxyTest.cpp \
- RetryList.cpp \
- FrameDecoder.cpp \
- ClientMessageTest.cpp \
- PollableCondition.cpp \
- Variant.cpp \
- Address.cpp \
- ClientMessage.cpp \
- Qmf2.cpp \
- BrokerOptions.cpp \
- Selector.cpp \
- SystemInfo.cpp
-
-if HAVE_XML
-unit_test_SOURCES+= XmlClientSessionTest.cpp
-endif
-
-TESTLIBFLAGS = -module -rpath $(abs_builddir)
-
-check_LTLIBRARIES += libshlibtest.la
-libshlibtest_la_LDFLAGS = $(TESTLIBFLAGS)
-libshlibtest_la_SOURCES = shlibtest.cpp
-
-tmodule_LTLIBRARIES += test_store.la
-test_store_la_SOURCES = test_store.cpp
-test_store_la_LIBADD = $(lib_broker)
-test_store_la_LDFLAGS = -module
-
-include sasl.mk
-if SSL
-include ssl.mk
-endif
-
-# Test programs that are installed and therefore built as part of make, not make check
-
-qpidexectest_SCRIPTS += qpid-cpp-benchmark qpid-cluster-benchmark install_env.sh qpidt
-EXTRA_DIST += qpid-cpp-benchmark qpid-cluster-benchmark install_env.sh qpidt
-
-qpidexectest_PROGRAMS += receiver
-receiver_SOURCES = \
- receiver.cpp \
- TestOptions.h \
- ConnectionOptions.h
-receiver_LDADD = $(lib_client) -lboost_program_options $(lib_common)
-
-qpidexectest_PROGRAMS += sender
-sender_SOURCES = \
- sender.cpp \
- TestOptions.h \
- ConnectionOptions.h \
- Statistics.cpp
-sender_LDADD = $(lib_messaging) -lboost_program_options $(lib_common) $(lib_types) $(lib_client)
-
-qpidexectest_PROGRAMS += qpid-receive
-qpid_receive_SOURCES = \
- qpid-receive.cpp \
- TestOptions.h \
- ConnectionOptions.h \
- Statistics.h \
- Statistics.cpp
-qpid_receive_LDADD = $(lib_messaging) -lboost_program_options $(lib_common) $(lib_types)
-
-qpidexectest_PROGRAMS += qpid-send
-qpid_send_SOURCES = \
- qpid-send.cpp \
- TestOptions.h \
- ConnectionOptions.h \
- Statistics.h \
- Statistics.cpp
-qpid_send_LDADD = $(lib_messaging) -lboost_program_options $(lib_common) $(lib_types)
-
-qpidexectest_PROGRAMS+=qpid-perftest
-qpid_perftest_SOURCES=qpid-perftest.cpp test_tools.h TestOptions.h ConnectionOptions.h
-qpid_perftest_INCLUDES=$(PUBLIC_INCLUDES)
-qpid_perftest_LDADD=$(lib_client) -lboost_program_options $(lib_common)
-
-qpidexectest_PROGRAMS+=qpid-txtest
-qpid_txtest_INCLUDES=$(PUBLIC_INCLUDES)
-qpid_txtest_SOURCES=qpid-txtest.cpp TestOptions.h ConnectionOptions.h
-qpid_txtest_LDADD=$(lib_client) -lboost_program_options $(lib_common)
-
-qpidexectest_PROGRAMS+=qpid-latency-test
-qpid_latency_test_INCLUDES=$(PUBLIC_INCLUDES)
-qpid_latency_test_SOURCES=qpid-latency-test.cpp TestOptions.h ConnectionOptions.h
-qpid_latency_test_LDADD=$(lib_client) -lboost_program_options $(lib_common)
-
-qpidexectest_PROGRAMS+=qpid-client-test
-qpid_client_test_INCLUDES=$(PUBLIC_INCLUDES)
-qpid_client_test_SOURCES=qpid-client-test.cpp TestOptions.h ConnectionOptions.h
-qpid_client_test_LDADD=$(lib_client) -lboost_program_options $(lib_common)
-
-qpidexectest_PROGRAMS+=qpid-topic-listener
-qpid_topic_listener_INCLUDES=$(PUBLIC_INCLUDES)
-qpid_topic_listener_SOURCES=qpid-topic-listener.cpp TestOptions.h ConnectionOptions.h
-qpid_topic_listener_LDADD=$(lib_client) -lboost_program_options $(lib_common)
-
-qpidexectest_PROGRAMS+=qpid-topic-publisher
-qpid_topic_publisher_INCLUDES=$(PUBLIC_INCLUDES)
-qpid_topic_publisher_SOURCES=qpid-topic-publisher.cpp TestOptions.h ConnectionOptions.h
-qpid_topic_publisher_LDADD=$(lib_client) -lboost_program_options $(lib_common)
-
-qpidexectest_PROGRAMS+=qpid-ping
-qpid_ping_INCLUDES=$(PUBLIC_INCLUDES)
-qpid_ping_SOURCES=qpid-ping.cpp test_tools.h TestOptions.h ConnectionOptions.h
-qpid_ping_LDADD=$(lib_client) -lboost_program_options $(lib_common)
-
-#
-# Other test programs
-#
-
-check_PROGRAMS+=echotest
-echotest_INCLUDES=$(PUBLIC_INCLUDES)
-echotest_SOURCES=echotest.cpp TestOptions.h ConnectionOptions.h
-echotest_LDADD=$(lib_client)
-
-check_PROGRAMS+=publish
-publish_INCLUDES=$(PUBLIC_INCLUDES)
-publish_SOURCES=publish.cpp TestOptions.h ConnectionOptions.h
-publish_LDADD=$(lib_client)
-
-check_PROGRAMS+=consume
-consume_INCLUDES=$(PUBLIC_INCLUDES)
-consume_SOURCES=consume.cpp TestOptions.h ConnectionOptions.h
-consume_LDADD=$(lib_client)
-
-check_PROGRAMS+=header_test
-header_test_INCLUDES=$(PUBLIC_INCLUDES)
-header_test_SOURCES=header_test.cpp TestOptions.h ConnectionOptions.h
-header_test_LDADD=$(lib_client)
-
-check_PROGRAMS+=declare_queues
-declare_queues_INCLUDES=$(PUBLIC_INCLUDES)
-declare_queues_SOURCES=declare_queues.cpp
-declare_queues_LDADD=$(lib_client)
-
-check_PROGRAMS+=replaying_sender
-replaying_sender_INCLUDES=$(PUBLIC_INCLUDES)
-replaying_sender_SOURCES=replaying_sender.cpp
-replaying_sender_LDADD=$(lib_client)
-
-check_PROGRAMS+=resuming_receiver
-resuming_receiver_INCLUDES=$(PUBLIC_INCLUDES)
-resuming_receiver_SOURCES=resuming_receiver.cpp
-resuming_receiver_LDADD=$(lib_client)
-
-check_PROGRAMS+=txshift
-txshift_INCLUDES=$(PUBLIC_INCLUDES)
-txshift_SOURCES=txshift.cpp TestOptions.h ConnectionOptions.h
-txshift_LDADD=$(lib_client)
-
-check_PROGRAMS+=txjob
-txjob_INCLUDES=$(PUBLIC_INCLUDES)
-txjob_SOURCES=txjob.cpp TestOptions.h ConnectionOptions.h
-txjob_LDADD=$(lib_client)
-
-check_PROGRAMS+=PollerTest
-PollerTest_SOURCES=PollerTest.cpp
-PollerTest_LDADD=$(lib_common) $(lib_client) $(SOCKLIBS)
-
-check_PROGRAMS+=DispatcherTest
-DispatcherTest_SOURCES=DispatcherTest.cpp
-DispatcherTest_LDADD=$(lib_common) $(lib_client) $(SOCKLIBS)
-
-check_PROGRAMS+=datagen
-datagen_SOURCES=datagen.cpp
-datagen_LDADD=$(lib_common) $(lib_client)
-
-check_PROGRAMS+=qpid-stream
-qpid_stream_INCLUDES=$(PUBLIC_INCLUDES)
-qpid_stream_SOURCES=qpid-stream.cpp
-qpid_stream_LDADD=$(lib_messaging)
-
-check_PROGRAMS+=msg_group_test
-msg_group_test_INCLUDES=$(PUBLIC_INCLUDES)
-msg_group_test_SOURCES=msg_group_test.cpp
-msg_group_test_LDADD=$(lib_messaging)
-
-TESTS_ENVIRONMENT = \
- VALGRIND=$(VALGRIND) \
- LIBTOOL="$(LIBTOOL)" \
- QPID_DATA_DIR= \
- $(srcdir)/run_test
-
-system_tests = qpid-client-test quick_perftest quick_topictest run_header_test quick_txtest \
- run_msg_group_tests
-TESTS += start_broker $(system_tests) python_tests stop_broker \
- run_ha_tests run_interlink_tests run_federation_tests run_federation_sys_tests \
- run_acl_tests run_cli_tests dynamic_log_level_test \
- dynamic_log_hires_timestamp run_queue_flow_limit_tests ipv6_test
-
-EXTRA_DIST += \
- run_test vg_check \
- run-unit-tests start_broker python_tests stop_broker \
- quick_topictest \
- quick_perftest \
- quick_txtest \
- topictest \
- run_header_test \
- header_test.py \
- ssl_test \
- ping_broker \
- config.null \
- run_federation_tests \
- run_federation_sys_tests \
- run_long_federation_sys_tests \
- run_cli_tests \
- run_acl_tests \
- .valgrind.supp \
- MessageUtils.h \
- TestMessageStore.h \
- TxMocks.h \
- run_perftest \
- ring_queue_test \
- run_ring_queue_test \
- run_paged_queue_tests \
- dynamic_log_level_test \
- dynamic_log_hires_timestamp \
- qpid-ctrl \
- CMakeLists.txt \
- windows/DisableWin32ErrorWindows.cpp \
- background.ps1 \
- find_prog.ps1 \
- python_tests.ps1 \
- quick_topictest.ps1 \
- run_federation_tests.ps1 \
- run_header_test.ps1 \
- run_test.ps1 \
- start_broker.ps1 \
- stop_broker.ps1 \
- topictest.ps1 \
- run_queue_flow_limit_tests \
- run_msg_group_tests \
- ipv6_test \
- run_ha_tests \
- ha_test.py \
- ha_tests.py \
- run_interlink_tests \
- interlink_tests.py \
- brokertest.py \
- test_env.ps1.in
-
-check_LTLIBRARIES += libdlclose_noop.la
-libdlclose_noop_la_LDFLAGS = -module -rpath $(abs_builddir)
-libdlclose_noop_la_SOURCES = dlclose_noop.c
-
-CLEANFILES+=valgrind.out *.log *.vglog* dummy_test qpidd.port $(unit_wrappers)
-
-# Longer running stability tests, not run by default check: target.
-# Not run under valgrind, too slow
-
-LONG_TESTS+=start_broker \
- fanout_perftest shared_perftest multiq_perftest topic_perftest run_ring_queue_test run_paged_queue_tests\
- run_msg_group_tests_soak \
- stop_broker \
- run_long_federation_sys_tests
-
-EXTRA_DIST+= \
- fanout_perftest \
- shared_perftest \
- multiq_perftest \
- topic_perftest \
- sasl_test_setup.sh \
- run_msg_group_tests_soak \
- qpidd-empty.conf \
- qpidd-p0
-
-check-long:
- $(MAKE) check TESTS="$(LONG_TESTS)" VALGRIND=
-
-# Things that should be built before the check target runs.
-check-am: python_prep test_env.sh install_env.sh sasl_config
-
-PYTHON_SRC_DIR=$(abs_srcdir)/../../../python
-PYTHON_BLD_DIR=$(abs_builddir)/python
-
-# Generate python client as part of the all-am target so it gets built before tests.
-all-am: python_prep
-
-python_prep:
- if test -d $(PYTHON_SRC_DIR); \
- then cd $(PYTHON_SRC_DIR) && python $(PYTHON_SRC_DIR)/setup.py install \
- --prefix=$(PYTHON_BLD_DIR) --install-lib=$(PYTHON_BLD_DIR) \
- --install-scripts=$(PYTHON_BLD_DIR)/commands; \
- else echo "WARNING: python client not built, missing $(PYTHON_SRC_DIR)"; fi
-
-sasl_config: sasl_test_setup.sh
- sh $(srcdir)/sasl_test_setup.sh
- touch sasl_config
-
-CLEAN_LOCAL += sasl_config
-
-clean-local:
- rm -rf $(CLEAN_LOCAL)
-
-include testagent.mk
-include brokermgmt.mk
-
diff --git a/qpid/cpp/src/tests/ManagementTest.cpp b/qpid/cpp/src/tests/ManagementTest.cpp
index 8944c084c0..98ef591fae 100644
--- a/qpid/cpp/src/tests/ManagementTest.cpp
+++ b/qpid/cpp/src/tests/ManagementTest.cpp
@@ -21,7 +21,6 @@
#include "qpid/management/ManagementObject.h"
#include "qpid/framing/Buffer.h"
-#include "qpid/console/ObjectId.h"
#include "unit_test.h"
namespace qpid {
@@ -93,32 +92,6 @@ QPID_AUTO_TEST_CASE(testObjectIdCreate) {
BOOST_CHECK_EQUAL(oid.getV2Key(), "an-object-name");
}
-QPID_AUTO_TEST_CASE(testConsoleObjectId) {
- qpid::console::ObjectId oid1, oid2;
-
- oid1.setValue(1, 2);
- oid2.setValue(3, 4);
-
- BOOST_CHECK(oid1 < oid2);
- BOOST_CHECK(oid1 <= oid2);
- BOOST_CHECK(oid2 > oid1);
- BOOST_CHECK(oid2 >= oid1);
- BOOST_CHECK(oid1 != oid2);
- BOOST_CHECK(oid1 == oid1);
-
- oid1.setValue(3, 6);
- oid2.setValue(3, 4);
-
- BOOST_CHECK(oid1 > oid2);
- BOOST_CHECK(oid1 >= oid2);
- BOOST_CHECK(oid2 < oid1);
- BOOST_CHECK(oid2 <= oid1);
- BOOST_CHECK(oid1 != oid2);
-
- oid2.setValue(3, 6);
- BOOST_CHECK(oid1 == oid2);
-}
-
QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/qpid/cpp/src/tests/MessageReplayTracker.cpp b/qpid/cpp/src/tests/MessageReplayTracker.cpp
index e35f673683..c0778247f0 100644
--- a/qpid/cpp/src/tests/MessageReplayTracker.cpp
+++ b/qpid/cpp/src/tests/MessageReplayTracker.cpp
@@ -23,6 +23,8 @@
#include "qpid/client/MessageReplayTracker.h"
#include "qpid/sys/Time.h"
+#include <boost/format.hpp>
+
namespace qpid {
namespace tests {
diff --git a/qpid/cpp/src/tests/MessagingFixture.h b/qpid/cpp/src/tests/MessagingFixture.h
index 2312a87e9d..1d70d4cfa6 100644
--- a/qpid/cpp/src/tests/MessagingFixture.h
+++ b/qpid/cpp/src/tests/MessagingFixture.h
@@ -35,6 +35,8 @@
#include "qpid/messaging/Message.h"
#include "qpid/types/Variant.h"
+#include <boost/format.hpp>
+
namespace qpid {
namespace tests {
@@ -115,6 +117,7 @@ struct MessagingFixture : public BrokerFixture
(boost::format("amqp:tcp:localhost:%1%") % (port)).str());
connection.open();
return connection;
+
}
/** Open a connection to the broker. */
@@ -231,9 +234,10 @@ inline void receive(messaging::Receiver& receiver, uint count = 1, uint start =
class MethodInvoker
{
public:
- MethodInvoker(messaging::Session& session) : replyTo("#; {create:always, node:{x-declare:{auto-delete:true}}}"),
- sender(session.createSender("qmf.default.direct/broker")),
- receiver(session.createReceiver(replyTo)) {}
+ MethodInvoker(messaging::Session session) :
+ replyTo("#; {create:always, node:{x-declare:{auto-delete:true}}}"),
+ sender(session.createSender("qmf.default.direct/broker")),
+ receiver(session.createReceiver(replyTo)) {}
void createExchange(const std::string& name, const std::string& type, bool durable=false)
{
@@ -292,11 +296,14 @@ class MethodInvoker
methodRequest("delete", params);
}
- void methodRequest(const std::string& method, const Variant::Map& inParams, Variant::Map* outParams = 0)
+ void methodRequest(
+ const std::string& method,
+ const Variant::Map& inParams, Variant::Map* outParams = 0,
+ const std::string& objectName="org.apache.qpid.broker:broker:amqp-broker")
{
Variant::Map content;
Variant::Map objectId;
- objectId["_object_name"] = "org.apache.qpid.broker:broker:amqp-broker";
+ objectId["_object_name"] = objectName;;
content["_object_id"] = objectId;
content["_method_name"] = method;
content["_arguments"] = inParams;
diff --git a/qpid/cpp/src/tests/MessagingSessionTests.cpp b/qpid/cpp/src/tests/MessagingSessionTests.cpp
index b388f2c13a..5cc595c56f 100644
--- a/qpid/cpp/src/tests/MessagingSessionTests.cpp
+++ b/qpid/cpp/src/tests/MessagingSessionTests.cpp
@@ -1289,6 +1289,95 @@ QPID_AUTO_TEST_CASE(testSimpleRequestResponse)
BOOST_CHECK_EQUAL(m.getSubject(), original.getSubject());
}
+QPID_AUTO_TEST_CASE(testSelfDestructQueue)
+{
+ MessagingFixture fix;
+ Session other = fix.connection.createSession();
+ Receiver r1 = other.createReceiver("amq.fanout; {link:{reliability:at-least-once, x-declare:{arguments:{qpid.max_count:10,qpid.policy_type:self-destruct}}}}");
+ Receiver r2 = fix.session.createReceiver("amq.fanout");
+ //send request
+ Sender s = fix.session.createSender("amq.fanout");
+ for (uint i = 0; i < 20; ++i) {
+ s.send(Message((boost::format("MSG_%1%") % (i+1)).str()));
+ }
+ try {
+ ScopedSuppressLogging sl;
+ for (uint i = 0; i < 20; ++i) {
+ r1.fetch(Duration::SECOND);
+ }
+ BOOST_FAIL("Expected exception.");
+ } catch (const qpid::messaging::MessagingException&) {
+ }
+
+ for (uint i = 0; i < 20; ++i) {
+ BOOST_CHECK_EQUAL(r2.fetch(Duration::SECOND).getContent(), (boost::format("MSG_%1%") % (i+1)).str());
+ }
+}
+
+QPID_AUTO_TEST_CASE(testReroutingRingQueue)
+{
+ MessagingFixture fix;
+ Receiver r1 = fix.session.createReceiver("my-queue; {create:always, node:{x-declare:{alternate-exchange:amq.fanout, auto-delete:True, arguments:{qpid.max_count:10,qpid.policy_type:ring}}}}");
+ Receiver r2 = fix.session.createReceiver("amq.fanout");
+
+ Sender s = fix.session.createSender("my-queue");
+ for (uint i = 0; i < 20; ++i) {
+ s.send(Message((boost::format("MSG_%1%") % (i+1)).str()));
+ }
+ for (uint i = 10; i < 20; ++i) {
+ BOOST_CHECK_EQUAL(r1.fetch(Duration::SECOND).getContent(), (boost::format("MSG_%1%") % (i+1)).str());
+ }
+ for (uint i = 0; i < 10; ++i) {
+ BOOST_CHECK_EQUAL(r2.fetch(Duration::SECOND).getContent(), (boost::format("MSG_%1%") % (i+1)).str());
+ }
+}
+
+QPID_AUTO_TEST_CASE(testReleaseOnPriorityQueue)
+{
+ MessagingFixture fix;
+ std::string queue("queue; {create:always, node:{x-declare:{auto-delete:True, arguments:{qpid.priorities:10}}}}");
+ std::string text("my message");
+ Sender sender = fix.session.createSender(queue);
+ sender.send(Message(text));
+ Receiver receiver = fix.session.createReceiver(queue);
+ Message msg;
+ for (uint i = 0; i < 10; ++i) {
+ if (receiver.fetch(msg, Duration::SECOND)) {
+ BOOST_CHECK_EQUAL(msg.getContent(), text);
+ fix.session.release(msg);
+ } else {
+ BOOST_FAIL("Released message not redelivered as expected.");
+ }
+ }
+ fix.session.acknowledge();
+}
+
+QPID_AUTO_TEST_CASE(testRollbackWithFullPrefetch)
+{
+ QueueFixture fix;
+ std::string first("first");
+ std::string second("second");
+ Sender sender = fix.session.createSender(fix.queue);
+ for (uint i = 0; i < 10; ++i) {
+ sender.send(Message((boost::format("MSG_%1%") % (i+1)).str()));
+ }
+ Session txsession = fix.connection.createTransactionalSession();
+ Receiver receiver = txsession.createReceiver(fix.queue);
+ receiver.setCapacity(9);
+ Message msg;
+ for (uint i = 0; i < 10; ++i) {
+ if (receiver.fetch(msg, Duration::SECOND)) {
+ BOOST_CHECK_EQUAL(msg.getContent(), std::string("MSG_1"));
+ txsession.rollback();
+ } else {
+ BOOST_FAIL("Released message not redelivered as expected.");
+ break;
+ }
+ }
+ txsession.acknowledge();
+ txsession.commit();
+}
+
QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/qpid/cpp/src/tests/QueuePolicyTest.cpp b/qpid/cpp/src/tests/QueuePolicyTest.cpp
index 00e964602a..ce1b0addea 100644
--- a/qpid/cpp/src/tests/QueuePolicyTest.cpp
+++ b/qpid/cpp/src/tests/QueuePolicyTest.cpp
@@ -28,6 +28,8 @@
#include "qpid/framing/reply_exceptions.h"
#include "BrokerFixture.h"
+#include <boost/format.hpp>
+
using namespace qpid::broker;
using namespace qpid::client;
using namespace qpid::framing;
diff --git a/qpid/cpp/src/tests/Shlib.cpp b/qpid/cpp/src/tests/Shlib.cpp
index d8ad4c14d8..7f01323e3c 100644
--- a/qpid/cpp/src/tests/Shlib.cpp
+++ b/qpid/cpp/src/tests/Shlib.cpp
@@ -35,13 +35,7 @@ typedef void (*CallMe)(int*);
QPID_AUTO_TEST_CASE(testShlib) {
- // The CMake-based build passes in the shared lib suffix; if it's not
- // there, this is a Linux/UNIX libtool-based build.
-#if defined (QPID_SHLIB_PREFIX) && defined (QPID_SHLIB_SUFFIX)
Shlib sh("./" QPID_SHLIB_PREFIX "shlibtest" QPID_SHLIB_POSTFIX QPID_SHLIB_SUFFIX);
-#else
- Shlib sh(".libs/libshlibtest.so");
-#endif
// Double cast to avoid ISO warning.
CallMe callMe=sh.getSymbol<CallMe>("callMe");
BOOST_REQUIRE(callMe != 0);
@@ -59,11 +53,7 @@ QPID_AUTO_TEST_CASE(testShlib) {
QPID_AUTO_TEST_CASE(testAutoShlib) {
int unloaded = 0;
{
-#if defined (QPID_SHLIB_PREFIX) && defined (QPID_SHLIB_SUFFIX)
AutoShlib sh("./" QPID_SHLIB_PREFIX "shlibtest" QPID_SHLIB_POSTFIX QPID_SHLIB_SUFFIX);
-#else
- AutoShlib sh(".libs/libshlibtest.so");
-#endif
CallMe callMe=sh.getSymbol<CallMe>("callMe");
BOOST_REQUIRE(callMe != 0);
callMe(&unloaded);
diff --git a/qpid/cpp/src/tests/TransactionObserverTest.cpp b/qpid/cpp/src/tests/TransactionObserverTest.cpp
new file mode 100644
index 0000000000..fd1c331ae7
--- /dev/null
+++ b/qpid/cpp/src/tests/TransactionObserverTest.cpp
@@ -0,0 +1,144 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "unit_test.h"
+#include "test_tools.h"
+#include "MessagingFixture.h"
+#include "qpid/broker/BrokerObserver.h"
+#include "qpid/broker/TransactionObserver.h"
+#include "qpid/broker/TxBuffer.h"
+#include "qpid/broker/Queue.h"
+#include "qpid/ha/types.h"
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/lexical_cast.hpp>
+#include <iostream>
+#include <vector>
+
+namespace qpid {
+namespace tests {
+
+using framing::SequenceSet;
+using messaging::Message;
+using boost::shared_ptr;
+
+using namespace boost::assign;
+using namespace boost;
+using namespace broker;
+using namespace std;
+using namespace messaging;
+using namespace types;
+
+QPID_AUTO_TEST_SUITE(TransactionalObserverTest)
+
+Message msg(string content) { return Message(content); }
+
+struct MockTransactionObserver : public TransactionObserver {
+ bool prep;
+ vector<string> events;
+
+ MockTransactionObserver(bool prep_=true) : prep(prep_) {}
+
+ void record(const string& e) { events.push_back(e); }
+
+ void enqueue(const shared_ptr<Queue>& q, const broker::Message& m) {
+ record("enqueue "+q->getName()+" "+m.getContent());
+ }
+ void dequeue(const Queue::shared_ptr& q, SequenceNumber p, SequenceNumber r) {
+ record("dequeue "+q->getName()+" "+
+ lexical_cast<string>(p)+" "+lexical_cast<string>(r));
+ }
+ bool prepare() { record("prepare"); return prep; }
+ void commit() { record("commit"); }
+ void rollback() {record("rollback"); }
+};
+
+struct MockBrokerObserver : public BrokerObserver {
+ bool prep;
+ shared_ptr<MockTransactionObserver> tx;
+
+ MockBrokerObserver(bool prep_=true) : prep(prep_) {}
+
+ void startTx(const shared_ptr<TxBuffer>& buffer) {
+ tx.reset(new MockTransactionObserver(prep));
+ buffer->setObserver(tx);
+ }
+};
+
+Session simpleTxTransaction(MessagingFixture& fix) {
+ fix.session.createSender("q1;{create:always}").send(msg("foo")); // Not in TX
+ // Transaction with 1 enqueue and 1 dequeue.
+ Session txSession = fix.connection.createTransactionalSession();
+ BOOST_CHECK_EQUAL("foo", txSession.createReceiver("q1").fetch().getContent());
+ txSession.acknowledge();
+ txSession.createSender("q2;{create:always}").send(msg("bar"));
+ return txSession;
+}
+
+QPID_AUTO_TEST_CASE(tesTxtCommit) {
+ MessagingFixture fix;
+ shared_ptr<MockBrokerObserver> brokerObserver(new MockBrokerObserver);
+ fix.broker->getBrokerObservers().add(brokerObserver);
+ Session txSession = simpleTxTransaction(fix);
+ txSession.commit();
+ // Note on ordering: observers see enqueues as they happen, but dequeues just
+ // before prepare.
+ BOOST_CHECK_EQUAL(
+ list_of<string>("enqueue q2 bar")("dequeue q1 1 0")("prepare")("commit"),
+ brokerObserver->tx->events
+ );
+}
+
+QPID_AUTO_TEST_CASE(testTxFail) {
+ MessagingFixture fix;
+ shared_ptr<MockBrokerObserver> brokerObserver(new MockBrokerObserver(false));
+ fix.broker->getBrokerObservers().add(brokerObserver);
+ Session txSession = simpleTxTransaction(fix);
+ try {
+ txSession.commit();
+ BOOST_FAIL("Expected exception");
+ } catch(...) {}
+
+ BOOST_CHECK_EQUAL(
+ list_of<string>("enqueue q2 bar")("dequeue q1 1 0")("prepare")("rollback"),
+ brokerObserver->tx->events
+ );
+}
+
+QPID_AUTO_TEST_CASE(testTxRollback) {
+ MessagingFixture fix;
+ shared_ptr<MockBrokerObserver> brokerObserver(new MockBrokerObserver(false));
+ fix.broker->getBrokerObservers().add(brokerObserver);
+ Session txSession = simpleTxTransaction(fix);
+ txSession.rollback();
+ // Note: The dequeue does not appear here. This is because TxAccepts
+ // (i.e. dequeues) are not enlisted until SemanticState::commit and are
+ // never enlisted if the transaction is rolled back.
+ BOOST_CHECK_EQUAL(
+ list_of<string>("enqueue q2 bar")("rollback"),
+ brokerObserver->tx->events
+ );
+}
+
+QPID_AUTO_TEST_SUITE_END()
+
+}} // namespace qpid::tests
diff --git a/qpid/cpp/src/tests/TxMocks.h b/qpid/cpp/src/tests/TxMocks.h
index bf21104f70..8b54e7484b 100644
--- a/qpid/cpp/src/tests/TxMocks.h
+++ b/qpid/cpp/src/tests/TxMocks.h
@@ -103,6 +103,9 @@ public:
if(!debugName.empty()) std::cout << std::endl << "MockTxOp[" << debugName << "]::rollback()" << std::endl;
actual.push_back(ROLLBACK);
}
+
+ void callObserver(const boost::shared_ptr<TransactionObserver>&) {}
+
MockTxOp& expectPrepare(){
expected.push_back(PREPARE);
return *this;
diff --git a/qpid/cpp/src/tests/brokermgmt.mk b/qpid/cpp/src/tests/brokermgmt.mk
deleted file mode 100644
index cf9a47200c..0000000000
--- a/qpid/cpp/src/tests/brokermgmt.mk
+++ /dev/null
@@ -1,44 +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.
-#
-
-# Build a unit test for the broker's internal management agent.
-
-BROKERMGMT_GEN_SRC= \
- brokermgmt_gen/qmf/org/apache/qpid/broker/mgmt/test/Package.cpp \
- brokermgmt_gen/qmf/org/apache/qpid/broker/mgmt/test/Package.h \
- brokermgmt_gen/qmf/org/apache/qpid/broker/mgmt/test/TestObject.h \
- brokermgmt_gen/qmf/org/apache/qpid/broker/mgmt/test/TestObject.cpp
-
-$(BROKERMGMT_GEN_SRC): brokermgmt_gen.timestamp
-
-if GENERATE
-BROKERMGMT_DEPS=../mgen.timestamp
-endif # GENERATE
-brokermgmt_gen.timestamp: BrokerMgmtAgent.xml ${BROKERMGMT_DEPS}
- $(QMF_GEN) -b -o brokermgmt_gen/qmf $(srcdir)/BrokerMgmtAgent.xml
- touch $@
-
-BrokerMgmtAgent.$(OBJEXT): $(BROKERMGMT_GEN_SRC)
-
-CLEANFILES+=$(BROKERMGMT_GEN_SRC) brokermgmt_gen.timestamp
-
-unit_test_SOURCES+=BrokerMgmtAgent.cpp ${BROKERMGMT_GEN_SRC}
-INCLUDES+= -Ibrokermgmt_gen
-
-EXTRA_DIST+=BrokerMgmtAgent.xml
diff --git a/qpid/cpp/src/tests/brokertest.py b/qpid/cpp/src/tests/brokertest.py
index 15372b312d..2786454399 100644
--- a/qpid/cpp/src/tests/brokertest.py
+++ b/qpid/cpp/src/tests/brokertest.py
@@ -78,7 +78,7 @@ def error_line(filename, n=1):
except: return ""
return ":\n" + "".join(result)
-def retry(function, timeout=10, delay=.01, max_delay=1):
+def retry(function, timeout=10, delay=.001, max_delay=1):
"""Call function until it returns a true value or timeout expires.
Double the delay for each retry up to max_delay.
Returns what function returns if true, None if timeout expires."""
@@ -141,7 +141,7 @@ class Popen(subprocess.Popen):
finally: f.close()
log.debug("Started process %s: %s" % (self.pname, " ".join(self.cmd)))
- def __str__(self): return "Popen<%s>"%(self.pname)
+ def __repr__(self): return "Popen<%s>"%(self.pname)
def outfile(self, ext): return "%s.%s" % (self.pname, ext)
@@ -242,16 +242,12 @@ class Broker(Popen):
_broker_count = 0
_log_count = 0
- def __str__(self): return "Broker<%s %s :%d>"%(self.log, self.pname, self.port())
-
- def find_log(self):
- self.log = "%03d:%s.log" % (Broker._log_count, self.name)
- Broker._log_count += 1
+ def __repr__(self): return "<Broker:%s:%d>"%(self.log, self.port())
def get_log(self):
return os.path.abspath(self.log)
- def __init__(self, test, args=[], name=None, expect=EXPECT_RUNNING, port=0, log_level=None, wait=None, show_cmd=False):
+ def __init__(self, test, args=[], test_store=False, name=None, expect=EXPECT_RUNNING, port=0, log_level=None, wait=None, show_cmd=False):
"""Start a broker daemon. name determines the data-dir and log
file names."""
@@ -273,11 +269,18 @@ class Broker(Popen):
else:
self.name = "broker%d" % Broker._broker_count
Broker._broker_count += 1
- self.find_log()
+
+ self.log = "%03d:%s.log" % (Broker._log_count, self.name)
+ self.store_log = "%03d:%s.store.log" % (Broker._log_count, self.name)
+ Broker._log_count += 1
+
cmd += ["--log-to-file", self.log]
cmd += ["--log-to-stderr=no"]
cmd += ["--log-enable=%s"%(log_level or "info+") ]
+ if test_store: cmd += ["--load-module", BrokerTest.test_store_lib,
+ "--test-store-events", self.store_log]
+
self.datadir = self.name
cmd += ["--data-dir", self.datadir]
if show_cmd: print cmd
@@ -285,7 +288,6 @@ class Broker(Popen):
test.cleanup_stop(self)
self._host = "127.0.0.1"
log.debug("Started broker %s (%s, %s)" % (self.name, self.pname, self.log))
- self._log_ready = False
def startQmf(self, handler=None):
self.qmf_session = qmf.console.Session(handler)
@@ -363,29 +365,21 @@ class Broker(Popen):
def host_port(self): return "%s:%s" % (self.host(), self.port())
- def log_contains(self, str, timeout=1):
- """Wait for str to appear in the log file up to timeout. Return true if found"""
- return retry(lambda: find_in_file(str, self.log), timeout)
-
- def log_ready(self):
- """Return true if the log file exists and contains a broker ready message"""
- if not self._log_ready:
- self._log_ready = find_in_file("notice Broker running", self.log)
- return self._log_ready
-
def ready(self, timeout=30, **kwargs):
"""Wait till broker is ready to serve clients"""
- # First make sure the broker is listening by checking the log.
- if not retry(self.log_ready, timeout=timeout):
- raise Exception(
- "Timed out waiting for broker %s%s"%(self.name, error_line(self.log,5)))
- # Create a connection and a session.
- try:
- c = self.connect(**kwargs)
- try: c.session()
- finally: c.close()
- except Exception,e: raise RethrownException(
- "Broker %s not responding: (%s)%s"%(self.name,e,error_line(self.log, 5)))
+ deadline = time.time()+timeout
+ while True:
+ try:
+ c = self.connect(timeout=timeout, **kwargs)
+ try:
+ c.session()
+ return # All good
+ finally: c.close()
+ except Exception,e: # Retry up to timeout
+ if time.time() > deadline:
+ raise RethrownException(
+ "Broker %s not responding: (%s)%s"%(
+ self.name,e,error_line(self.log, 5)))
def browse(session, queue, timeout=0, transform=lambda m: m.content):
"""Return a list with the contents of each message on queue."""
@@ -407,7 +401,7 @@ def assert_browse(session, queue, expect_contents, timeout=0, transform=lambda m
if msg: msg = "%s: %r != %r"%(msg, expect_contents, actual_contents)
assert expect_contents == actual_contents, msg
-def assert_browse_retry(session, queue, expect_contents, timeout=1, delay=.01, transform=lambda m:m.content, msg="browse failed"):
+def assert_browse_retry(session, queue, expect_contents, timeout=1, delay=.001, transform=lambda m:m.content, msg="browse failed"):
"""Wait up to timeout for contents of queue to match expect_contents"""
test = lambda: browse(session, queue, 0, transform=transform) == expect_contents
retry(test, timeout, delay)
@@ -421,6 +415,10 @@ class BrokerTest(TestCase):
Provides a well-known working directory for each test.
"""
+ def __init__(self, *args, **kwargs):
+ self.longMessage = True # Enable long messages for assert*(..., msg=xxx)
+ TestCase.__init__(self, *args, **kwargs)
+
# Environment settings.
qpidd_exec = os.path.abspath(checkenv("QPIDD_EXEC"))
ha_lib = os.getenv("HA_LIB")
@@ -480,7 +478,7 @@ class BrokerTest(TestCase):
def assert_browse(self, *args, **kwargs): assert_browse(*args, **kwargs)
def assert_browse_retry(self, *args, **kwargs): assert_browse_retry(*args, **kwargs)
-def join(thread, timeout=10):
+def join(thread, timeout=30):
thread.join(timeout)
if thread.isAlive(): raise Exception("Timed out joining thread %s"%thread)
diff --git a/qpid/cpp/src/tests/cli_tests.py b/qpid/cpp/src/tests/cli_tests.py
index dceafc5427..eee9bc648c 100755
--- a/qpid/cpp/src/tests/cli_tests.py
+++ b/qpid/cpp/src/tests/cli_tests.py
@@ -69,47 +69,39 @@ class CliTests(TestBase010):
self.startBrokerAccess()
queue1 = self.makeQueue("test_queue_params1", "--limit-policy none")
queue2 = self.makeQueue("test_queue_params2", "--limit-policy reject")
- queue3 = self.makeQueue("test_queue_params3", "--limit-policy flow-to-disk")
- queue4 = self.makeQueue("test_queue_params4", "--limit-policy ring")
- queue5 = self.makeQueue("test_queue_params5", "--limit-policy ring-strict")
+ queue3 = self.makeQueue("test_queue_params3", "--limit-policy ring")
LIMIT = "qpid.policy_type"
assert LIMIT not in queue1.arguments
self.assertEqual(queue2.arguments[LIMIT], "reject")
- self.assertEqual(queue3.arguments[LIMIT], "flow_to_disk")
- self.assertEqual(queue4.arguments[LIMIT], "ring")
- self.assertEqual(queue5.arguments[LIMIT], "ring_strict")
+ self.assertEqual(queue3.arguments[LIMIT], "ring")
- queue6 = self.makeQueue("test_queue_params6", "--lvq-key lkey")
+ queue4 = self.makeQueue("test_queue_params4", "--lvq-key lkey")
LVQKEY = "qpid.last_value_queue_key"
- assert LVQKEY not in queue5.arguments
- assert LVQKEY in queue6.arguments
- assert queue6.arguments[LVQKEY] == "lkey"
+ assert LVQKEY not in queue3.arguments
+ assert LVQKEY in queue4.arguments
+ assert queue4.arguments[LVQKEY] == "lkey"
def test_queue_params_api(self):
self.startBrokerAccess()
queue1 = self.makeQueue("test_queue_params_api1", "--limit-policy none", True)
queue2 = self.makeQueue("test_queue_params_api2", "--limit-policy reject", True)
- queue3 = self.makeQueue("test_queue_params_api3", "--limit-policy flow-to-disk", True)
- queue4 = self.makeQueue("test_queue_params_api4", "--limit-policy ring", True)
- queue5 = self.makeQueue("test_queue_params_api5", "--limit-policy ring-strict", True)
+ queue3 = self.makeQueue("test_queue_params_api3", "--limit-policy ring", True)
LIMIT = "qpid.policy_type"
assert LIMIT not in queue1.arguments
self.assertEqual(queue2.arguments[LIMIT], "reject")
- self.assertEqual(queue3.arguments[LIMIT], "flow_to_disk")
- self.assertEqual(queue4.arguments[LIMIT], "ring")
- self.assertEqual(queue5.arguments[LIMIT], "ring_strict")
+ self.assertEqual(queue3.arguments[LIMIT], "ring")
- queue6 = self.makeQueue("test_queue_params_api6", "--lvq-key lkey")
+ queue4 = self.makeQueue("test_queue_params_api4", "--lvq-key lkey")
LVQKEY = "qpid.last_value_queue_key"
- assert LVQKEY not in queue5.arguments
- assert LVQKEY in queue6.arguments
- assert queue6.arguments[LVQKEY] == "lkey"
+ assert LVQKEY not in queue3.arguments
+ assert LVQKEY in queue4.arguments
+ assert queue4.arguments[LVQKEY] == "lkey"
def test_qpid_config(self):
diff --git a/qpid/cpp/src/tests/failing-amqp0-10-python-tests b/qpid/cpp/src/tests/failing-amqp0-10-python-tests
new file mode 100644
index 0000000000..cb742a25e5
--- /dev/null
+++ b/qpid/cpp/src/tests/failing-amqp0-10-python-tests
@@ -0,0 +1,7 @@
+#The following four tests fail the because pure python client excludes
+#the node type for queues from the reply-to address, weheras the swigged
+#client does not (as that prevents it resolving the node on every send)
+qpid.tests.messaging.message.MessageEchoTests.testReplyTo
+qpid.tests.messaging.message.MessageEchoTests.testReplyToQueue
+qpid.tests.messaging.message.MessageEchoTests.testReplyToQueueSubject
+qpid.tests.messaging.message.MessageEchoTests.testProperties
diff --git a/qpid/cpp/src/tests/failing-amqp1.0-python-tests b/qpid/cpp/src/tests/failing-amqp1.0-python-tests
new file mode 100644
index 0000000000..2cae7b6306
--- /dev/null
+++ b/qpid/cpp/src/tests/failing-amqp1.0-python-tests
@@ -0,0 +1,2 @@
+qpid_tests.broker_0_10.new_api.GeneralTests.test_qpid_3481_acquired_to_alt_exchange_2_consumers
+qpid_tests.broker_0_10.new_api.GeneralTests.test_qpid_3481_acquired_to_alt_exchange
diff --git a/qpid/cpp/src/tests/ha_test.py b/qpid/cpp/src/tests/ha_test.py
index f2fc50054f..3b5874875a 100755
--- a/qpid/cpp/src/tests/ha_test.py
+++ b/qpid/cpp/src/tests/ha_test.py
@@ -48,6 +48,24 @@ class QmfAgent(object):
address, client_properties={"qpid.ha-admin":1}, **kwargs)
self._agent = BrokerAgent(self._connection)
+ def queues(self):
+ return [q.values['name'] for q in self._agent.getAllQueues()]
+
+ def repsub_queue(self, sub):
+ """If QMF subscription sub is a replicating subscription return
+ the name of the replicated queue, else return None"""
+ session_name = self.getSession(sub.sessionRef).name
+ m = re.search("qpid.ha-q:(.*)\.", session_name)
+ return m and m.group(1)
+
+ def repsub_queues(self):
+ """Return queue names for all replicating subscriptions"""
+ return filter(None, [self.repsub_queue(s) for s in self.getAllSubscriptions()])
+
+ def tx_queues(self):
+ """Return names of all tx-queues"""
+ return [q for q in self.queues() if q.startswith("qpid.ha-tx")]
+
def __getattr__(self, name):
a = getattr(self._agent, name)
return a
@@ -101,6 +119,9 @@ class HaBroker(Broker):
"""Start a broker with HA enabled
@param client_cred: (user, password, mechanism) for admin clients started by the HaBroker.
"""
+
+ heartbeat=2
+
def __init__(self, test, ha_port=None, args=[], brokers_url=None, ha_cluster=True,
ha_replicate="all", client_credentials=None, **kwargs):
assert BrokerTest.ha_lib, "Cannot locate HA plug-in"
@@ -112,7 +133,7 @@ class HaBroker(Broker):
"--link-maintenance-interval=0.1",
# Heartbeat and negotiate time are needed so that a broker wont
# stall on an address that doesn't currently have a broker running.
- "--link-heartbeat-interval=1",
+ "--link-heartbeat-interval=%s"%(HaBroker.heartbeat),
"--max-negotiate-time=1000",
"--ha-cluster=%s"%ha_cluster]
if ha_replicate is not None:
@@ -139,15 +160,18 @@ acl allow all all
self.client_credentials = client_credentials
self.ha_port = ha_port
- def __str__(self): return Broker.__str__(self)
+ def __repr__(self): return "<HaBroker:%s:%d>"%(self.log, self.port())
def qpid_ha(self, args):
- cred = self.client_credentials
- url = self.host_port()
- if cred:
- url =cred.add_user(url)
- args = args + ["--sasl-mechanism", cred.mechanism]
- self.qpid_ha_script.main_except(["", "-b", url]+args)
+ try:
+ cred = self.client_credentials
+ url = self.host_port()
+ if cred:
+ url =cred.add_user(url)
+ args = args + ["--sasl-mechanism", cred.mechanism]
+ self.qpid_ha_script.main_except(["", "-b", url]+args)
+ except Exception, e:
+ raise Exception("Error in qpid_ha -b %s %s: %s"%(url, args,e))
def promote(self): self.ready(); self.qpid_ha(["promote"])
def set_public_url(self, url): self.qpid_ha(["set", "--public-url", url])
@@ -221,6 +245,12 @@ acl allow all all
def wait_backup(self, address): self.wait_address(address)
+ def browse(self, queue, timeout=0, transform=lambda m: m.content):
+ c = self.connect_admin()
+ try:
+ return browse(c.session(), queue, timeout, transform)
+ finally: c.close()
+
def assert_browse(self, queue, expected, **kwargs):
"""Verify queue contents by browsing."""
bs = self.connect().session()
@@ -247,8 +277,10 @@ acl allow all all
try: return self.connect()
except ConnectionError: return None
- def ready(self):
- return Broker.ready(self, client_properties={"qpid.ha-admin":1})
+ def ready(self, *args, **kwargs):
+ if not 'client_properties' in kwargs: kwargs['client_properties'] = {}
+ kwargs['client_properties']['qpid.ha-admin'] = True
+ return Broker.ready(self, *args, **kwargs)
def kill(self, final=True):
if final: self.ha_port.stop()
@@ -259,16 +291,19 @@ acl allow all all
class HaCluster(object):
_cluster_count = 0
- def __init__(self, test, n, promote=True, wait=True, args=[], **kwargs):
+ def __init__(self, test, n, promote=True, wait=True, args=[], s_args=[], **kwargs):
"""Start a cluster of n brokers.
@test: The test being run
@n: start n brokers
@promote: promote self[0] to primary
@wait: wait for primary active and backups ready. Ignored if promote=False
+ @args: args for all brokers in the cluster.
+ @s_args: args for specific brokers: s_args[i] for broker i.
"""
self.test = test
- self.args = args
+ self.args = copy(args)
+ self.s_args = copy(s_args)
self.kwargs = kwargs
self._ports = [HaPort(test) for i in xrange(n)]
self._set_url()
@@ -288,10 +323,13 @@ class HaCluster(object):
self.broker_id += 1
return name
- def _ha_broker(self, ha_port, name):
+ def _ha_broker(self, i, name):
+ args = self.args
+ if i < len(self.s_args): args += self.s_args[i]
+ ha_port = self._ports[i]
b = HaBroker(ha_port.test, ha_port, brokers_url=self.url, name=name,
- args=self.args, **self.kwargs)
- b.ready()
+ args=args, **self.kwargs)
+ b.ready(timeout=5)
return b
def start(self):
@@ -302,7 +340,7 @@ class HaCluster(object):
self._ports.append(HaPort(self.test))
self._set_url()
self._update_urls()
- b = self._ha_broker(self._ports[i], self.next_name())
+ b = self._ha_broker(i, self.next_name())
self._brokers.append(b)
return b
@@ -328,7 +366,7 @@ class HaCluster(object):
a separate log file: foo.n.log"""
if self._ports[i].stopped: raise Exception("Restart after final kill: %s"%(self))
b = self._brokers[i]
- self._brokers[i] = self._ha_broker(self._ports[i], b.name)
+ self._brokers[i] = self._ha_broker(i, b.name)
self._brokers[i].ready()
def bounce(self, i, promote_next=True):
diff --git a/qpid/cpp/src/tests/ha_tests.py b/qpid/cpp/src/tests/ha_tests.py
index 293712fe80..6941a2b545 100755
--- a/qpid/cpp/src/tests/ha_tests.py
+++ b/qpid/cpp/src/tests/ha_tests.py
@@ -20,7 +20,7 @@
import os, signal, sys, time, imp, re, subprocess, glob, random, logging, shutil, math, unittest
import traceback
-from qpid.messaging import Message, SessionError, NotFound, ConnectionError, ReceiverError, Connection, Timeout, Disposition, REJECTED, Empty
+from qpid.messaging import Message, SessionError, NotFound, ConnectionError, ReceiverError, Connection, Timeout, Disposition, REJECTED, Empty, ServerError
from qpid.datatypes import uuid4, UUID
from brokertest import *
from ha_test import *
@@ -37,6 +37,7 @@ def grep(filename, regexp):
class HaBrokerTest(BrokerTest):
"""Base class for HA broker tests"""
+
def assert_log_no_errors(self, broker):
log = broker.get_log()
if grep(log, re.compile("] error|] critical")):
@@ -219,7 +220,8 @@ class ReplicationTests(HaBrokerTest):
backup.connect_admin().close()
# Test discovery: should connect to primary after reject by backup
- c = backup.connect(reconnect_urls=[primary.host_port(), backup.host_port()], reconnect=True)
+ c = backup.connect(reconnect_urls=[primary.host_port(), backup.host_port()],
+ reconnect=True)
s = c.session()
sender = s.sender("q;{create:always}")
backup.wait_backup("q")
@@ -561,9 +563,9 @@ class ReplicationTests(HaBrokerTest):
return
acl=os.path.join(os.getcwd(), "policy.acl")
aclf=file(acl,"w")
- # Verify that replication works with auth=yes and HA user has at least the following
- # privileges:
+ # Minimum set of privileges required for the HA user.
aclf.write("""
+# HA user
acl allow zag@QPID access queue
acl allow zag@QPID create queue
acl allow zag@QPID consume queue
@@ -575,6 +577,9 @@ acl allow zag@QPID publish exchange
acl allow zag@QPID delete exchange
acl allow zag@QPID access method
acl allow zag@QPID create link
+# Normal user
+acl allow zig@QPID all all
+
acl deny all all
""")
aclf.close()
@@ -585,14 +590,16 @@ acl deny all all
"--ha-username=zag", "--ha-password=zag", "--ha-mechanism=PLAIN"
],
client_credentials=Credentials("zag", "zag", "PLAIN"))
- s0 = cluster[0].connect(username="zag", password="zag").session();
- s0.receiver("q;{create:always}")
- s0.receiver("ex;{create:always,node:{type:topic,x-declare:{type:'fanout'},x-bindings:[{exchange:'ex',queue:'q'}]}}")
- cluster[1].wait_backup("q")
- cluster[1].wait_backup("ex")
- s1 = cluster[1].connect_admin().session(); # Uses Credentials above.
- s1.sender("ex").send("foo");
- self.assertEqual(s1.receiver("q").fetch().content, "foo")
+ c = cluster[0].connect(username="zig", password="zig")
+ s0 = c.session();
+ s0.sender("q;{create:always}")
+ s0.sender("ex;{create:always,node:{type:topic,x-declare:{type:'fanout'},x-bindings:[{exchange:'ex',queue:'q'}]}}")
+ s0.sender("ex").send("foo");
+ s1 = c.session(transactional=True)
+ s1.sender("ex").send("foo-tx");
+ cluster[1].assert_browse_backup("q", ["foo"])
+ s1.commit()
+ cluster[1].assert_browse_backup("q", ["foo", "foo-tx"])
def test_alternate_exchange(self):
"""Verify that alternate-exchange on exchanges and queues is propagated
@@ -927,20 +934,22 @@ class LongTests(HaBrokerTest):
if d: return float(d)*60
else: return 3 # Default is to be quick
- # FIXME aconway 2013-06-27: skip this test pending a fix for
- # https://issues.apache.org/jira/browse/QPID-4944
- def skip_test_failover_send_receive(self):
+ def test_failover_send_receive(self):
"""Test failover with continuous send-receive"""
brokers = HaCluster(self, 3)
# Start sender and receiver threads
n = 10
- senders = [NumberedSender(brokers[0], url=brokers.url,
- max_depth=1024, failover_updates=False,
- queue="test%s"%(i)) for i in xrange(n)]
- receivers = [NumberedReceiver(brokers[0], url=brokers.url, sender=senders[i],
- failover_updates=False,
- queue="test%s"%(i)) for i in xrange(n)]
+ senders = [
+ NumberedSender(
+ brokers[0], url=brokers.url,max_depth=50, failover_updates=False,
+ queue="test%s"%(i), args=["--capacity=10"]) for i in xrange(n)]
+
+ receivers = [
+ NumberedReceiver(
+ brokers[0], url=brokers.url, sender=senders[i],failover_updates=False,
+ queue="test%s"%(i), args=["--capacity=10"]) for i in xrange(n)]
+
for r in receivers: r.start()
for s in senders: s.start()
@@ -991,7 +1000,7 @@ class LongTests(HaBrokerTest):
finally:
for s in senders: s.stop()
for r in receivers: r.stop()
- dead = filter(lambda i: not brokers[i].is_running(), xrange(3))
+ dead = filter(lambda b: not b.is_running(), brokers)
if dead: raise Exception("Brokers not running: %s"%dead)
def test_qmf_order(self):
@@ -1200,7 +1209,7 @@ class ConfigurationTests(HaBrokerTest):
cluster[0].set_brokers_url(cluster.url+",xxx:1234")
self.assertRaises(Empty, r.fetch, 0) # Not updated for brokers URL
-class StoreTests(BrokerTest):
+class StoreTests(HaBrokerTest):
"""Test for HA with persistence."""
def check_skip(self):
@@ -1248,7 +1257,7 @@ class StoreTests(BrokerTest):
doing catch-up from the primary."""
if self.check_skip(): return
cluster = HaCluster(self, 2)
- sn = cluster[0].connect(heartbeat=1).session()
+ sn = cluster[0].connect(heartbeat=HaBroker.heartbeat).session()
s1 = sn.sender("q1;{create:always,node:{durable:true}}")
for m in ["foo","bar"]: s1.send(Message(m, durable=True))
s2 = sn.sender("q2;{create:always,node:{durable:true}}")
@@ -1259,7 +1268,7 @@ class StoreTests(BrokerTest):
cluster[1].assert_browse_backup("q2", ["hello"])
# Make changes that the backup doesn't see
cluster.kill(1, promote_next=False, final=False)
- r1 = cluster[0].connect(heartbeat=1).session().receiver("q1")
+ r1 = cluster[0].connect(heartbeat=HaBroker.heartbeat).session().receiver("q1")
for m in ["foo", "bar"]: self.assertEqual(r1.fetch().content, m)
r1.session.acknowledge()
for m in ["x","y","z"]: s1.send(Message(m, durable=True))
@@ -1278,7 +1287,7 @@ class StoreTests(BrokerTest):
cluster[0].assert_browse("q1", ["x","y","z"])
cluster[1].assert_browse_backup("q1", ["x","y","z"])
- sn = cluster[0].connect(heartbeat=1).session() # FIXME aconway 2012-09-25: should fail over!
+ sn = cluster[0].connect(heartbeat=HaBroker.heartbeat).session()
sn.sender("ex/k1").send("boo")
cluster[0].assert_browse_backup("q1", ["x","y","z", "boo"])
cluster[1].assert_browse_backup("q1", ["x","y","z", "boo"])
@@ -1287,6 +1296,185 @@ class StoreTests(BrokerTest):
cluster[0].assert_browse("q2", ["hello", "end"])
cluster[1].assert_browse_backup("q2", ["hello", "end"])
+def open_read(name):
+ try:
+ f = open(name)
+ return f.read()
+ finally: f.close()
+
+class TransactionTests(HaBrokerTest):
+
+ load_store=["--load-module", BrokerTest.test_store_lib]
+
+ def tx_simple_setup(self, broker):
+ """Start a transaction, remove messages from queue a, add messages to queue b"""
+ c = broker.connect()
+ # Send messages to a, no transaction.
+ sa = c.session().sender("a;{create:always,node:{durable:true}}")
+ tx_msgs = ["x","y","z"]
+ for m in tx_msgs: sa.send(Message(content=m, durable=True))
+
+ # Receive messages from a, in transaction.
+ tx = c.session(transactional=True)
+ txr = tx.receiver("a")
+ tx_msgs2 = [txr.fetch(1).content for i in xrange(3)]
+ self.assertEqual(tx_msgs, tx_msgs2)
+
+ # Send messages to b, transactional, mixed with non-transactional.
+ sb = c.session().sender("b;{create:always,node:{durable:true}}")
+ txs = tx.sender("b")
+ msgs = [str(i) for i in xrange(3)]
+ for tx_m,m in zip(tx_msgs2, msgs):
+ txs.send(tx_m);
+ sb.send(m)
+ return tx
+
+ def tx_subscriptions(self, broker):
+ """Return list of queue names for tx subscriptions"""
+ return [q for q in broker.agent().repsub_queues()
+ if q.startswith("qpid.ha-tx")]
+
+ def test_tx_simple_commit(self):
+ cluster = HaCluster(self, 2, test_store=True)
+ tx = self.tx_simple_setup(cluster[0])
+ tx.sync()
+ tx_queues = cluster[0].agent().tx_queues()
+
+ # NOTE: backup does not process transactional dequeues until prepare
+ cluster[1].assert_browse_backup("a", ["x","y","z"])
+ cluster[1].assert_browse_backup("b", ['0', '1', '2'])
+
+ tx.acknowledge()
+ tx.commit()
+ tx.sync()
+
+ for b in cluster: self.assert_simple_commit_outcome(b, tx_queues)
+
+ def assert_tx_cleanup(self, b, tx_queues):
+ """Verify that there are no transaction artifacts
+ (exchanges, queues, subscriptions) on b."""
+
+ self.assertEqual(0, len(b.agent().tx_queues()), msg=b)
+ self.assertEqual(0, len(self.tx_subscriptions(b)), msg=b)
+
+ # TX exchanges don't show up in management so test for existence by name.
+ s = b.connect_admin().session()
+ try:
+ for q in tx_queues:
+ try:
+ s.sender("%s;{node:{type:topic}}"%q)
+ self.fail("Found tx exchange %s on %s "%(q,b))
+ except NotFound: pass
+ finally: s.connection.close()
+
+ def assert_simple_commit_outcome(self, b, tx_queues):
+ b.assert_browse_backup("a", [], msg=b)
+ b.assert_browse_backup("b", ['0', '1', '2', 'x', 'y', 'z'], msg=b)
+ # Check for expected actions on the store
+ expect = """<enqueue a x>
+<enqueue a y>
+<enqueue a z>
+<begin tx 1>
+<dequeue a x tx=1>
+<dequeue a y tx=1>
+<dequeue a z tx=1>
+<commit tx=1>
+"""
+ self.assertEqual(expect, open_read(b.store_log), msg=b)
+ self.assert_tx_cleanup(b, tx_queues)
+
+ def test_tx_simple_rollback(self):
+ cluster = HaCluster(self, 2, test_store=True)
+ tx = self.tx_simple_setup(cluster[0])
+ tx.sync()
+ tx_queues = cluster[0].agent().tx_queues()
+ tx.acknowledge()
+ tx.rollback()
+ for b in cluster: self.assert_simple_rollback_outcome(b, tx_queues)
+
+ def assert_simple_rollback_outcome(self, b, tx_queues):
+ b.assert_browse_backup("a", ["x","y","z"], msg=b)
+ b.assert_browse_backup("b", ['0', '1', '2'], msg=b)
+ # Check for expected actions on the store
+ expect = """<enqueue a x>
+<enqueue a y>
+<enqueue a z>
+"""
+ self.assertEqual(open_read(b.store_log), expect, msg=b)
+ self.assert_tx_cleanup(b, tx_queues)
+
+ def test_tx_simple_failover(self):
+ cluster = HaCluster(self, 3, test_store=True)
+ tx = self.tx_simple_setup(cluster[0])
+ tx.sync()
+ tx_queues = cluster[0].agent().tx_queues()
+ tx.acknowledge()
+ cluster.bounce(0) # Should cause roll-back
+ cluster[0].wait_status("ready") # Restarted.
+ cluster[1].wait_status("active") # Promoted.
+ cluster[2].wait_status("ready") # Failed over.
+ for b in cluster: self.assert_simple_rollback_outcome(b, tx_queues)
+
+ def test_tx_no_backups(self):
+ """Test the special case of a TX where there are no backups"""
+
+ # Test commit
+ cluster = HaCluster(self, 1, test_store=True)
+ tx = self.tx_simple_setup(cluster[0])
+ tx.acknowledge()
+ tx.commit()
+ tx.sync()
+ tx_queues = cluster[0].agent().tx_queues()
+ self.assert_simple_commit_outcome(cluster[0], tx_queues)
+
+ # Test rollback
+ cluster = HaCluster(self, 1, test_store=True)
+ tx = self.tx_simple_setup(cluster[0])
+ tx.sync()
+ tx_queues = cluster[0].agent().tx_queues()
+ tx.acknowledge()
+ tx.rollback()
+ tx.sync()
+ self.assert_simple_rollback_outcome(cluster[0], tx_queues)
+
+
+ def test_tx_backup_fail(self):
+ cluster = HaCluster(
+ self, 2, test_store=True, s_args=[[],["--test-store-throw=bang"]])
+ c = cluster[0].connect()
+ tx = c.session(transactional=True)
+ s = tx.sender("q;{create:always,node:{durable:true}}")
+ for m in ["foo","bang","bar"]: s.send(Message(m, durable=True))
+ self.assertRaises(ServerError, tx.commit)
+ for b in cluster: b.assert_browse_backup("q", [])
+ self.assertEqual(open_read(cluster[0].store_log), "<begin tx 1>\n<abort tx=1>\n")
+ self.assertEqual(open_read(cluster[1].store_log), "<begin tx 1>\n<enqueue q foo tx=1>\n<enqueue q bang tx=1>\n<abort tx=1>\n")
+
+ def test_tx_join_leave(self):
+ """Test cluster members joining/leaving cluster.
+ Also check that tx-queues are cleaned up at end of transaction."""
+
+ cluster = HaCluster(self, 3)
+
+ # Leaving
+ tx = cluster[0].connect().session(transactional=True)
+ s = tx.sender("q;{create:always}")
+ s.send("a", sync=True)
+ self.assertEqual([1,1,1], [len(b.agent().tx_queues()) for b in cluster])
+ cluster[1].kill(final=False)
+ s.send("b")
+ self.assertRaises(ServerError, tx.commit)
+ self.assertEqual([[],[]], [b.agent().tx_queues() for b in [cluster[0],cluster[2]]])
+
+ # Joining
+ tx = cluster[0].connect().session(transactional=True)
+ s = tx.sender("q;{create:always}")
+ s.send("foo")
+ cluster.restart(1)
+ tx.commit()
+ # The new member is not in the tx but receives the results normal replication.
+ for b in cluster: b.assert_browse_backup("q", ["foo"], msg=b)
+
if __name__ == "__main__":
outdir = "ha_tests.tmp"
shutil.rmtree(outdir, True)
diff --git a/qpid/cpp/src/tests/interlink_tests.py b/qpid/cpp/src/tests/interlink_tests.py
index 129283ac24..608d4ac890 100755
--- a/qpid/cpp/src/tests/interlink_tests.py
+++ b/qpid/cpp/src/tests/interlink_tests.py
@@ -22,6 +22,7 @@ import os, signal, sys, time, imp, re, subprocess, glob, random, logging, shutil
import traceback
from qpid.messaging import Message, SessionError, NotFound, ConnectionError, ReceiverError, Connection, Timeout, Disposition, REJECTED, Empty
from brokertest import *
+from ha_test import HaPort
from threading import Thread, Lock, Condition
from logging import getLogger, WARN, ERROR, DEBUG, INFO
from qpidtoollibs import BrokerAgent, BrokerObject
@@ -46,7 +47,8 @@ class AmqpBrokerTest(BrokerTest):
def setUp(self):
BrokerTest.setUp(self)
os.putenv("QPID_LOAD_MODULE", BrokerTest.amqpc_lib)
- self.broker = self.amqp_broker()
+ self.port_holder = HaPort(self)
+ self.broker = self.amqp_broker(port_holder=self.port_holder)
self.default_config = Config(self.broker)
self.agent = BrokerAgent(self.broker.connect())
@@ -126,6 +128,9 @@ class AmqpBrokerTest(BrokerTest):
def test_translate2(self):
self.send_and_receive(send_config=Config(self.broker, version="amqp0-10"))
+ def test_translate_with_large_routingkey(self):
+ self.send_and_receive(send_config=Config(self.broker, address="amq.topic/a.%s" % ("x" * 256), version="amqp1.0"), recv_config=Config(self.broker, address="amq.topic/a.*", version="amqp0-10"), wait_for_receiver=True)
+
def send_and_receive_empty(self, send_config=None, recv_config=None):
sconfig = send_config or self.default_config
rconfig = recv_config or self.default_config
@@ -218,16 +223,22 @@ class AmqpBrokerTest(BrokerTest):
assert len(domains) == 1
assert domains[0].name == "BrokerB"
- def test_incoming_link(self):
+ def incoming_link(self, mechanism):
brokerB = self.amqp_broker()
agentB = BrokerAgent(brokerB.connect())
self.agent.create("queue", "q")
agentB.create("queue", "q")
- self.agent.create("domain", "BrokerB", {"url":brokerB.host_port(), "sasl_mechanisms":"NONE"})
+ self.agent.create("domain", "BrokerB", {"url":brokerB.host_port(), "sasl_mechanisms":mechanism})
self.agent.create("incoming", "Link1", {"domain":"BrokerB","source":"q","target":"q"})
#send to brokerB, receive from brokerA
self.send_and_receive(send_config=Config(brokerB))
+ def test_incoming_link_anonymous(self):
+ self.incoming_link("ANONYMOUS")
+
+ def test_incoming_link_nosasl(self):
+ self.incoming_link("NONE")
+
def test_outgoing_link(self):
brokerB = self.amqp_broker()
agentB = BrokerAgent(brokerB.connect())
@@ -246,14 +257,73 @@ class AmqpBrokerTest(BrokerTest):
#send to q on broker B through brokerA
self.send_and_receive(send_config=Config(self.broker, address="q@BrokerB"), recv_config=Config(brokerB))
+ def test_reconnect(self):
+ receiver_cmd = ["qpid-receive",
+ "--broker", self.broker.host_port(),
+ "--address=amq.fanout",
+ "--connection-options={protocol:amqp1.0, reconnect:True,container_id:receiver}",
+ "--timeout=10", "--print-content=true", "--print-headers=false"
+ ]
+ receiver = self.popen(receiver_cmd, stdout=PIPE)
+
+ sender_cmd = ["qpid-send",
+ "--broker", self.broker.host_port(),
+ "--address=amq.fanout",
+ "--connection-options={protocol:amqp1.0,reconnect:True,container_id:sender}",
+ "--content-stdin", "--send-eos=1"
+ ]
+ sender = self.popen(sender_cmd, stdin=PIPE)
+ sender._set_cloexec_flag(sender.stdin) #required for older python, see http://bugs.python.org/issue4112
+
+
+ batch1 = ["message-%s" % (i+1) for i in range(10000)]
+ for m in batch1:
+ sender.stdin.write(m + "\n")
+ sender.stdin.flush()
+
+ self.broker.kill()
+ self.broker = self.amqp_broker(port_holder=self.port_holder)
+
+ batch2 = ["message-%s" % (i+1) for i in range(10000, 20000)]
+ for m in batch2:
+ sender.stdin.write(m + "\n")
+ sender.stdin.flush()
+
+ sender.stdin.close()
+
+ last = None
+ m = receiver.stdout.readline().rstrip()
+ while len(m):
+ last = m
+ m = receiver.stdout.readline().rstrip()
+ assert last == "message-20000", (last)
+
""" Create and return a broker with AMQP 1.0 support """
def amqp_broker(self):
assert BrokerTest.amqp_lib, "Cannot locate AMQP 1.0 plug-in"
+ self.port_holder = HaPort(self) #reserve port
args = ["--load-module", BrokerTest.amqp_lib,
- "--max-negotiate-time=600000",
+ "--socket-fd=%s" % self.port_holder.fileno,
+ "--listen-disable=tcp",
"--log-enable=trace+:Protocol",
"--log-enable=info+"]
- return BrokerTest.broker(self, args)
+ return BrokerTest.broker(self, args, port=self.port_holder.port)
+
+ def amqp_broker(self, port_holder=None):
+ assert BrokerTest.amqp_lib, "Cannot locate AMQP 1.0 plug-in"
+ if port_holder:
+ args = ["--load-module", BrokerTest.amqp_lib,
+ "--socket-fd=%s" % port_holder.fileno,
+ "--listen-disable=tcp",
+ "--log-enable=trace+:Protocol",
+ "--log-enable=info+"]
+ return BrokerTest.broker(self, args, port=port_holder.port)
+ else:
+ args = ["--load-module", BrokerTest.amqp_lib,
+ "--log-enable=trace+:Protocol",
+ "--log-enable=info+"]
+ return BrokerTest.broker(self, args)
+
if __name__ == "__main__":
shutil.rmtree("brokertest.tmp", True)
diff --git a/qpid/cpp/src/tests/qpid-cluster-lag.py b/qpid/cpp/src/tests/qpid-cluster-lag.py
deleted file mode 100755
index 5b24353241..0000000000
--- a/qpid/cpp/src/tests/qpid-cluster-lag.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-"""%prog [options] broker...
-Check for brokers that lag behind other brokers in a cluster."""
-
-import os, os.path, sys, socket, time, re
-from qpid.messaging import *
-from optparse import OptionParser
-from threading import Thread
-
-class Browser(Thread):
- def __init__(self, broker, queue, timeout):
- Thread.__init__(self)
- self.broker = broker
- self.queue = queue
- self.timeout = timeout
- self.error = None
- self.time = None
-
- def run(self):
- try:
- self.connection = Connection(self.broker)
- self.connection.open()
- self.session = self.connection.session()
- self.receiver = self.session.receiver("%s;{mode:browse}"%self.queue)
- self.msg = self.receiver.fetch(timeout=self.timeout)
- self.time = time.time()
- if (self.msg.content != self.queue):
- raise Exception("Wrong message content, expected '%s' found '%s'"%
- (self.queue, self.msg.content))
- except Empty:
- self.error = "No message on queue %s"%self.queue
- except Exception, e:
- self.error = "Error: %s"%e
-
-def main(argv):
- op = OptionParser(usage=__doc__)
- op.add_option("--timeout", type="float", default=None, metavar="TIMEOUT",
- help="Give up after TIMEOUT milliseconds, default never timeout")
- (opts, args) = op.parse_args(argv)
- if (len(args) <= 1): op.error("No brokers were specified")
- brokers = args[1:]
-
- # Put a message on a uniquely named queue.
- queue = "%s:%s:%s"%(os.path.basename(args[0]), socket.gethostname(), os.getpid())
- connection = Connection(brokers[0])
- connection.open()
- session = connection.session()
- sender = session.sender(
- "%s;{create:always,delete:always,node:{durable:False}}"%queue)
- sender.send(Message(content=queue))
- start = time.time()
- # Browse for the message on each broker
- if opts.timeout: opts.timeout
- threads = [Browser(b, queue, opts.timeout) for b in brokers]
- for t in threads: t.start()
- delays=[]
-
- for t in threads:
- t.join()
- if t.error:
- delay=t.error
- else:
- delay = t.time-start
- delays.append([delay, t.broker])
- print "%s: %s"%(t.broker,delay)
- if delays:
- delays.sort()
- print "lag: %s (%s-%s)"%(delays[-1][0] - delays[0][0], delays[-1][1], delays[0][1])
- # Clean up
- sender.close()
- session.close()
- connection.close()
-
-if __name__ == "__main__": sys.exit(main(sys.argv))
diff --git a/qpid/cpp/src/tests/qpid-receive.cpp b/qpid/cpp/src/tests/qpid-receive.cpp
index 510e9be42c..ab26d3d9b5 100644
--- a/qpid/cpp/src/tests/qpid-receive.cpp
+++ b/qpid/cpp/src/tests/qpid-receive.cpp
@@ -69,11 +69,12 @@ struct Options : public qpid::Options
string readyAddress;
uint receiveRate;
std::string replyto;
+ bool noReplies;
Options(const std::string& argv0=std::string())
: qpid::Options("Options"),
help(false),
- url("amqp:tcp:127.0.0.1"),
+ url("127.0.0.1"),
timeout(0),
forever(false),
messages(0),
@@ -91,7 +92,8 @@ struct Options : public qpid::Options
reportTotal(false),
reportEvery(0),
reportHeader(true),
- receiveRate(0)
+ receiveRate(0),
+ noReplies(false)
{
addOptions()
("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to")
@@ -116,6 +118,7 @@ struct Options : public qpid::Options
("ready-address", qpid::optValue(readyAddress, "ADDRESS"), "send a message to this address when ready to receive")
("receive-rate", qpid::optValue(receiveRate,"N"), "Receive at rate of N messages/second. 0 means receive as fast as possible.")
("reply-to", qpid::optValue(replyto, "REPLY-TO"), "specify reply-to address on response messages")
+ ("ignore-reply-to", qpid::optValue(noReplies), "Do not send replies even if reply-to is set")
("help", qpid::optValue(help), "print this usage statement");
add(log);
}
@@ -222,6 +225,7 @@ int main(int argc, char ** argv)
if (opts.printHeaders) {
if (msg.getSubject().size()) std::cout << "Subject: " << msg.getSubject() << std::endl;
if (msg.getReplyTo()) std::cout << "ReplyTo: " << msg.getReplyTo() << std::endl;
+ if (msg.getMessageId().size()) std::cout << "MessageId: " << msg.getMessageId() << std::endl;
if (msg.getCorrelationId().size()) std::cout << "CorrelationId: " << msg.getCorrelationId() << std::endl;
if (msg.getUserId().size()) std::cout << "UserId: " << msg.getUserId() << std::endl;
if (msg.getTtl().getMilliseconds()) std::cout << "TTL: " << msg.getTtl().getMilliseconds() << std::endl;
@@ -231,8 +235,10 @@ int main(int argc, char ** argv)
std::cout << "Properties: " << msg.getProperties() << std::endl;
std::cout << std::endl;
}
- if (opts.printContent)
- std::cout << msg.getContent() << std::endl;//TODO: handle map or list messages
+ if (opts.printContent) {
+ if (!msg.getContentObject().isVoid()) std::cout << msg.getContentObject() << std::endl;
+ else std::cout << msg.getContent() << std::endl;
+ }
if (opts.messages && count >= opts.messages) done = true;
}
}
@@ -245,7 +251,7 @@ int main(int argc, char ** argv)
} else if (opts.ackFrequency && (count % opts.ackFrequency == 0)) {
session.acknowledge();
}
- if (msg.getReplyTo()) { // Echo message back to reply-to address.
+ if (msg.getReplyTo() && !opts.noReplies) { // Echo message back to reply-to address.
Sender& s = replyTo[msg.getReplyTo().str()];
if (s.isNull()) {
s = session.createSender(msg.getReplyTo());
@@ -260,8 +266,6 @@ int main(int argc, char ** argv)
int64_t delay = qpid::sys::Duration(qpid::sys::now(), waitTill);
if (delay > 0) qpid::sys::usleep(delay/qpid::sys::TIME_USEC);
}
- // Clear out message properties & content for next iteration.
- msg = Message(); // TODO aconway 2010-12-01: should be done by fetch
}
if (opts.reportTotal) reporter.report();
if (opts.tx) {
diff --git a/qpid/cpp/src/tests/qpid-send.cpp b/qpid/cpp/src/tests/qpid-send.cpp
index c3bba31e3b..f912b84e8e 100644
--- a/qpid/cpp/src/tests/qpid-send.cpp
+++ b/qpid/cpp/src/tests/qpid-send.cpp
@@ -96,7 +96,7 @@ struct Options : public qpid::Options
Options(const std::string& argv0=std::string())
: qpid::Options("Options"),
help(false),
- url("amqp:tcp:127.0.0.1"),
+ url("127.0.0.1"),
messages(1),
sendEos(0),
durable(false),
@@ -262,9 +262,8 @@ class MapContentGenerator : public ContentGenerator {
public:
MapContentGenerator(const Options& opt) : opts(opt) {}
virtual bool setContent(Message& msg) {
- Variant::Map map;
- opts.setEntries(map);
- encode(map, msg);
+ msg.getContentObject() = qpid::types::Variant::Map();
+ opts.setEntries(msg.getContentObject().asMap());
return true;
}
private:
@@ -371,6 +370,7 @@ int main(int argc, char ** argv)
msg.setReplyTo(Address(opts.replyto));
}
if (!opts.userid.empty()) msg.setUserId(opts.userid);
+ if (!opts.id.empty()) msg.setMessageId(opts.id);
if (!opts.correlationid.empty()) msg.setCorrelationId(opts.correlationid);
opts.setProperties(msg);
uint sent = 0;
diff --git a/qpid/cpp/src/tests/qpidd_qmfv2_tests.py b/qpid/cpp/src/tests/qpidd_qmfv2_tests.py
index 36fbe4b438..55497ccc03 100755
--- a/qpid/cpp/src/tests/qpidd_qmfv2_tests.py
+++ b/qpid/cpp/src/tests/qpidd_qmfv2_tests.py
@@ -39,20 +39,25 @@ class ConsoleTest(BrokerTest):
def setUp(self):
BrokerTest.setUp(self)
- args = ["--mgmt-qmf1=no",
- "--mgmt-pub-interval=%d" % self.PUB_INTERVAL]
+
+ def _startBroker(self, QMFv1=False ):
+ self._broker_is_v1 = QMFv1
+ if self._broker_is_v1:
+ args = ["--mgmt-qmf1=yes", "--mgmt-qmf2=no"]
+ else:
+ args = ["--mgmt-qmf1=no", "--mgmt-qmf2=yes"]
+
+ args.append("--mgmt-pub-interval=%d" % self.PUB_INTERVAL)
self.broker = BrokerTest.broker(self, args)
- def _startQmfV2(self, broker, console=None):
+
+ def _myStartQmf(self, broker, console=None):
# I manually set up the QMF session here rather than call the startQmf
# method from BrokerTest as I can guarantee the console library is used
# (assuming BrokerTest's implementation of startQmf could change)
self.qmf_session = qmf.console.Session(console)
self.qmf_broker = self.qmf_session.addBroker("%s:%s" % (broker.host(),
broker.port()))
- self.assertEqual(self.qmf_broker.getBrokerAgent().isV2, True,
- "Expected broker agent to support QMF V2")
-
def _create_queue( self, q_name, args={} ):
broker = self.qmf_session.getObjects(_class="broker")[0]
@@ -60,11 +65,11 @@ class ConsoleTest(BrokerTest):
self.assertEqual(result.status, 0, result)
- def test_method_call(self):
+ def _test_method_call(self):
""" Verify method calls work, and check the behavior of getObjects()
call
"""
- self._startQmfV2( self.broker )
+ self._myStartQmf( self.broker )
self._create_queue( "fleabag", {"auto-delete":True} )
qObj = None
@@ -76,12 +81,16 @@ class ConsoleTest(BrokerTest):
self.assertNotEqual(qObj, None, "Failed to get queue object")
#print qObj
- def test_unsolicited_updates(self):
+ def _test_unsolicited_updates(self):
""" Verify that the Console callbacks work
"""
class Handler(qmf.console.Console):
def __init__(self):
+ self.v1_oids = 0
+ self.v1_events = 0
+ self.v2_oids = 0
+ self.v2_events = 0
self.broker_info = []
self.broker_conn = []
self.newpackage = []
@@ -109,28 +118,38 @@ class ConsoleTest(BrokerTest):
def event(self, broker, event):
#print "EVENT %s" % event
self.events.append(event)
- def objectProps(self, broker, record):
- #print "ObjProps %s" % record
- assert len(record.getProperties()), "objectProps() invoked with no properties?"
+ if event.isV2:
+ self.v2_events += 1
+ else:
+ self.v1_events += 1
+
+ def heartbeat(self, agent, timestamp):
+ #print "Heartbeat %s" % agent
+ self.heartbeats.append( (agent, timestamp) )
+
+ # generic handler for objectProps and objectStats
+ def _handle_obj_update(self, record):
oid = record.getObjectId()
+ if oid.isV2:
+ self.v2_oids += 1
+ else:
+ self.v1_oids += 1
+
if oid not in self.updates:
self.updates[oid] = record
else:
self.updates[oid].mergeUpdate( record )
+
+ def objectProps(self, broker, record):
+ assert len(record.getProperties()), "objectProps() invoked with no properties?"
+ self._handle_obj_update(record)
+
def objectStats(self, broker, record):
- #print "ObjStats %s" % record
assert len(record.getStatistics()), "objectStats() invoked with no properties?"
- oid = record.getObjectId()
- if oid not in self.updates:
- self.updates[oid] = record
- else:
- self.updates[oid].mergeUpdate( record )
- def heartbeat(self, agent, timestamp):
- #print "Heartbeat %s" % agent
- self.heartbeats.append( (agent, timestamp) )
+ self._handle_obj_update(record)
handler = Handler()
- self._startQmfV2( self.broker, handler )
+ self._myStartQmf( self.broker, handler )
# this should force objectProps, queueDeclare Event callbacks
self._create_queue( "fleabag", {"auto-delete":True} )
# this should force objectStats callback
@@ -163,7 +182,15 @@ class ConsoleTest(BrokerTest):
break
assert msgs == 3, "msgDepth statistics not accurate!"
- def test_async_method(self):
+ # verify that the published objects were of the correct QMF version
+ if self._broker_is_v1:
+ assert handler.v1_oids and handler.v2_oids == 0, "QMFv2 updates received while in V1-only mode!"
+ assert handler.v1_events and handler.v2_events == 0, "QMFv2 events received while in V1-only mode!"
+ else:
+ assert handler.v2_oids and handler.v1_oids == 0, "QMFv1 updates received while in V2-only mode!"
+ assert handler.v2_events and handler.v1_events == 0, "QMFv1 events received while in V2-only mode!"
+
+ def _test_async_method(self):
class Handler (qmf.console.Console):
def __init__(self):
self.cv = Condition()
@@ -207,12 +234,40 @@ class ConsoleTest(BrokerTest):
return "fail (lost=%d, mismatch=%d, spurious=%d)" % (lost, mismatched, spurious)
handler = Handler()
- self._startQmfV2(self.broker, handler)
+ self._myStartQmf(self.broker, handler)
broker = self.qmf_session.getObjects(_class="broker")[0]
handler.request(broker, 20)
sleep(1)
self.assertEqual(handler.check(), "pass")
+ def test_method_call(self):
+ self._startBroker()
+ self._test_method_call()
+
+ def test_unsolicited_updates(self):
+ self._startBroker()
+ self._test_unsolicited_updates()
+
+ def test_async_method(self):
+ self._startBroker()
+ self._test_async_method()
+
+ # For now, include "QMFv1 only" tests. Once QMFv1 is deprecated, these can
+ # be removed
+
+ def test_method_call_v1(self):
+ self._startBroker(QMFv1=True)
+ self._test_method_call()
+
+ def test_unsolicited_updates_v1(self):
+ self._startBroker(QMFv1=True)
+ self._test_unsolicited_updates()
+
+ def test_async_method_v1(self):
+ self._startBroker(QMFv1=True)
+ self._test_async_method()
+
+
if __name__ == "__main__":
shutil.rmtree("brokertest.tmp", True)
diff --git a/qpid/cpp/src/tests/qpidt b/qpid/cpp/src/tests/qpidt
index 5bdfb6eefd..92df9efc8d 100755
--- a/qpid/cpp/src/tests/qpidt
+++ b/qpid/cpp/src/tests/qpidt
@@ -117,7 +117,7 @@ class Manager:
if k == "name":
name = v
elif v:
- if isinstance(v, dict) and v["_object_name"]:
+ if isinstance(v, dict) and "_object_name" in v:
v = v["_object_name"]
details += "%s=%s " %(k,v)
print "%-25s %s" % (name, details)
diff --git a/qpid/cpp/src/tests/queue_flow_limit_tests.py b/qpid/cpp/src/tests/queue_flow_limit_tests.py
index c7361a629e..83e31e979b 100644
--- a/qpid/cpp/src/tests/queue_flow_limit_tests.py
+++ b/qpid/cpp/src/tests/queue_flow_limit_tests.py
@@ -27,6 +27,8 @@ from os import environ, popen
class QueueFlowLimitTests(TestBase010):
+ _timeout = 100
+
def __getattr__(self, name):
if name == "assertGreater":
return lambda a, b: self.failUnless(a > b)
@@ -156,7 +158,7 @@ class QueueFlowLimitTests(TestBase010):
totalMsgs = 1213 + 797 + 331
# wait until flow control is active
- deadline = time() + 10
+ deadline = time() + self._timeout
while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \
time() < deadline:
pass
@@ -209,7 +211,7 @@ class QueueFlowLimitTests(TestBase010):
totalMsgs = 1699 + 1129 + 881
# wait until flow control is active
- deadline = time() + 10
+ deadline = time() + self._timeout
while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \
time() < deadline:
pass
@@ -255,7 +257,7 @@ class QueueFlowLimitTests(TestBase010):
# fill up the queue, waiting until flow control is active
sndr1 = self._start_qpid_send(testq.mgmt.name, count=testq.sendCount, content=testq.content)
- deadline = time() + 10
+ deadline = time() + self._timeout
while (not testq.mgmt.flowStopped) and time() < deadline:
testq.mgmt.update()
@@ -357,7 +359,7 @@ class QueueFlowLimitTests(TestBase010):
sender = BlockedSender(self, "kill-q", count=100)
# wait for flow control
- deadline = time() + 10
+ deadline = time() + self._timeout
while (not q.flowStopped) and time() < deadline:
q.update()
diff --git a/qpid/cpp/src/tests/rsynchosts b/qpid/cpp/src/tests/rsynchosts
index 4f19c3b22a..81c9699ac3 100755
--- a/qpid/cpp/src/tests/rsynchosts
+++ b/qpid/cpp/src/tests/rsynchosts
@@ -27,13 +27,21 @@ abspath() {
}
usage() {
- echo "Usage: $(basename $0) file [file...]
+ echo "Usage: $(basename $0) [-l user] file [file...]
Synchronize the contents of each file or directory to the same absolute path on
each host in \$HOSTS.
"
exit 1
}
+while getopts "l:" opt; do
+ case $opt in
+ l) RSYNC_USER="$OPTARG@" ;;
+ *) usage ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
test "$*" || usage
for f in $*; do FILES="$FILES $(abspath $f)" || exit 1; done
@@ -42,7 +50,7 @@ OK_FILE=`mktemp` # Will be deleted if anything goes wrong.
trap "rm -f $OK_FILE" EXIT
for h in $HOSTS; do
- rsync -aRO --delete $FILES $h:/ || { echo "rsync to $h failed"; rm -f $OK_FILE; } &
+ rsync -vaRO --delete $FILES $RSYNC_USER$h:/ || { echo "rsync to $h failed"; rm -f $OK_FILE; } &
done
wait
test -f $OK_FILE
diff --git a/qpid/cpp/src/tests/run-unit-tests b/qpid/cpp/src/tests/run-unit-tests
deleted file mode 100755
index 5337a3dc22..0000000000
--- a/qpid/cpp/src/tests/run-unit-tests
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-#
-# Library names (without path or .so) and CppUnit test paths can be
-# specified on the command line or in env var UNIT_TESTS. For example:
-#
-# Selected test classes:
-# ./run-unit-tests ValueTest ClientChannelTest
-#
-# Individual test method
-# ./run-unit-tests ValueTest :ValueTest::testStringValueEquals
-#
-# Build and run selected tests:
-# make check TESTS=run-unit-tests UNIT_TESTS=ClientChannelTest
-#
-
-for u in $* $UNIT_TESTS ; do
- case $u in
- :*) TEST_ARGS="$TEST_ARGS $u" ;; # A test path.
- *) TEST_ARGS="$TEST_ARGS .libs/$u.so" ;; # A test library.
- esac
-done
-test -z "$TEST_ARGS" && TEST_ARGS=".libs/*Test.so"
-
-test -z "$srcdir" && srcdir=.
-
-# libdlclose_noop prevents unloading symbols needed for valgrind output.
-export LD_PRELOAD=.libs/libdlclose_noop.so
-source $srcdir/run_test DllPlugInTester -c -b $TEST_ARGS
diff --git a/qpid/cpp/src/tests/run_cli_tests b/qpid/cpp/src/tests/run_cli_tests
index a7f55d58b7..e9590080a1 100755
--- a/qpid/cpp/src/tests/run_cli_tests
+++ b/qpid/cpp/src/tests/run_cli_tests
@@ -44,8 +44,8 @@ start_brokers() {
# look like they're xml related.
# if we start supporting xml on windows, it will need something similar
# here
- if [ -f ../.libs/xml.so ] ; then
- xargs="--load-module ../.libs/xml.so"
+ if [ -f ../xml.so ] ; then
+ xargs="--load-module ../xml.so"
if [ ! -f test.xquery ] ; then
create_test_xquery
fi
diff --git a/qpid/cpp/src/tests/run_federation_tests b/qpid/cpp/src/tests/run_federation_tests
index 09219141ef..bf33f96ebd 100755
--- a/qpid/cpp/src/tests/run_federation_tests
+++ b/qpid/cpp/src/tests/run_federation_tests
@@ -25,7 +25,7 @@ source ./test_env.sh
#set -x
trap stop_brokers INT TERM QUIT
-if [ -f ../.libs/xml.so ] ; then
+if [ -f ../xml.so ] ; then
MODULES="--load-module xml" # Load the XML exchange and run XML exchange federation tests
SKIPTESTS=
else
diff --git a/qpid/cpp/src/tests/run_msg_group_tests.ps1 b/qpid/cpp/src/tests/run_msg_group_tests.ps1
new file mode 100644
index 0000000000..e9cee0a5a0
--- /dev/null
+++ b/qpid/cpp/src/tests/run_msg_group_tests.ps1
@@ -0,0 +1,71 @@
+#
+# 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.
+#
+
+# Simple test of encode/decode of a double in application headers
+# TODO: this should be expanded to cover a wider set of types and go
+# in both directions
+
+$srcdir = Split-Path $myInvocation.InvocationName
+$PYTHON_DIR = "$srcdir\..\..\..\python"
+if (!(Test-Path $PYTHON_DIR -pathType Container)) {
+ "Skipping msg_group test as python libs not found"
+ exit 0
+}
+
+. .\test_env.ps1
+
+if (Test-Path qpidd.port) {
+ set-item -path env:QPID_PORT -value (get-content -path qpidd.port -totalcount 1)
+}
+
+# Test runs from the tests directory but the test executables are in a
+# subdirectory based on the build type. Look around for it before trying
+# to start it.
+. $srcdir\find_prog.ps1 .\msg_group_test.exe
+if (!(Test-Path $prog)) {
+ "Cannot locate msg_group_test.exe"
+ exit 1
+}
+
+$QUEUE_NAME="group-queue"
+$GROUP_KEY="My-Group-Id"
+$BROKER_URL="localhost:$env:QPID_PORT"
+
+$tests=@("python $QPID_CONFIG_EXEC -b $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups",
+ "$prog -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 3",
+ "$prog -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 7 --randomize-group-size",
+ "python $QPID_CONFIG_EXEC -b $BROKER_URL add queue ${QUEUE_NAME}-two --group-header=${GROUP_KEY} --shared-groups",
+ "$prog -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 3 --randomize-group-size",
+ "$prog -b $BROKER_URL -a ${QUEUE_NAME}-two --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 5",
+ "$prog -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 59 --group-size 5 --receivers 2 --senders 3 --capacity 1 --ack-frequency 3 --randomize-group-size",
+ "python $QPID_CONFIG_EXEC -b $BROKER_URL del queue ${QUEUE_NAME}-two --force",
+ "$prog -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 59 --group-size 3 --receivers 2 --senders 3 --capacity 1 --ack-frequency 1 --randomize-group-size",
+ "$prog -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 211 --group-size 13 --receivers 2 --senders 3 --capacity 47 --ack-frequency 79 --interleave 53",
+ "$prog -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10000 --group-size 1 --receivers 0 --senders 1",
+ "$prog -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10000 --receivers 5 --senders 0",
+ "python $QPID_CONFIG_EXEC -b $BROKER_URL del queue $QUEUE_NAME --force")
+
+foreach ($cmd in $tests)
+{
+ Invoke-Expression "$cmd" | Write-Output
+ $ret = $LASTEXITCODE
+ if ($ret -ne 0) {Write-Host "FAILED message group test. Failed command: $cmd"
+ break}
+}
+exit $ret
diff --git a/qpid/cpp/src/tests/sasl.mk b/qpid/cpp/src/tests/sasl.mk
deleted file mode 100644
index 8c31192635..0000000000
--- a/qpid/cpp/src/tests/sasl.mk
+++ /dev/null
@@ -1,44 +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.
-#
-
-# Test that are only relevant if SASL is enabled.
-if HAVE_SASL
-
-# Note: sasl_version is not a test -- it is a tool used by tests.
-check_PROGRAMS+=sasl_version
-sasl_version_SOURCES=sasl_version.cpp
-sasl_version_LDADD=$(lib_client)
-
-TESTS += sasl_fed
- sasl_fed_ex_dynamic
- sasl_fed_ex_link
- sasl_fed_ex_queue
- sasl_fed_ex_route
- sasl_no_dir
-
-EXTRA_DIST += sasl_fed \
- sasl_fed_ex \
- sasl_fed_ex_dynamic \
- sasl_fed_ex_link \
- sasl_fed_ex_queue \
- sasl_fed_ex_route \
- sasl_no_dir
-
-
-endif # HAVE_SASL
diff --git a/qpid/cpp/src/tests/ssl.mk b/qpid/cpp/src/tests/ssl.mk
deleted file mode 100644
index 1544dc5e71..0000000000
--- a/qpid/cpp/src/tests/ssl.mk
+++ /dev/null
@@ -1,22 +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.
-#
-
-TESTS+=ssl_test
-EXTRA_DIST+=ssl_test
-CLEAN_LOCAL += test_cert_dir cert.password
diff --git a/qpid/cpp/src/tests/swig_python_tests b/qpid/cpp/src/tests/swig_python_tests
new file mode 100755
index 0000000000..6f862ffa2d
--- /dev/null
+++ b/qpid/cpp/src/tests/swig_python_tests
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Run the python tests.
+source ./test_env.sh
+trap stop_broker INT TERM QUIT
+
+if [[ -a $AMQP_LIB ]] ; then
+ echo "Found AMQP support: $AMQP_LIB"
+ MODULES="--load-module $AMQP_LIB"
+fi
+
+fail() {
+ echo "FAIL swigged python tests: $1"; exit 1;
+}
+skip() {
+ echo "SKIPPED swigged python tests: $1"; exit 0;
+}
+
+start_broker() {
+ QPID_PORT=$($QPIDD_EXEC --daemon --port 0 --interface 127.0.0.1 --no-data-dir $MODULES --auth no) || fail "Could not start broker"
+}
+
+stop_broker() {
+ $QPIDD_EXEC -q --port $QPID_PORT
+}
+
+test -d $PYTHON_DIR || skip "no python dir"
+test -f $PYTHONSWIGMODULE || skip "no swigged python client"
+
+start_broker
+echo "Running swigged python tests using broker on port $QPID_PORT"
+
+export PYTHONPATH=$PYTHONPATH:$PYTHONPATH_SWIG
+$QPID_PYTHON_TEST -m qpid.tests.messaging.message -m qpid_tests.broker_0_10.priority -m qpid_tests.broker_0_10.lvq -m qpid_tests.broker_0_10.new_api -b localhost:$QPID_PORT -I $srcdir/failing-amqp0-10-python-tests || FAILED=1
+if [[ -a $AMQPC_LIB ]] ; then
+ export QPID_LOAD_MODULE=$AMQPC_LIB
+ $QPID_PYTHON_TEST --define="protocol_version=amqp1.0" -m qpid_tests.broker_1_0 -m qpid_tests.broker_0_10.new_api -b localhost:$QPID_PORT -I $srcdir/failing-amqp1.0-python-tests || FAILED=1
+fi
+stop_broker
+if [[ $FAILED -eq 1 ]]; then
+ fail ""
+fi
+
diff --git a/qpid/cpp/src/tests/test_env.ps1.in b/qpid/cpp/src/tests/test_env.ps1.in
index 5fa3a0ac31..12373b5b35 100644
--- a/qpid/cpp/src/tests/test_env.ps1.in
+++ b/qpid/cpp/src/tests/test_env.ps1.in
@@ -41,7 +41,6 @@ $PYTHON_COMMANDS="$QPID_TOOLS\src\py"
$env:PYTHONPATH="$srcdir;$PYTHON_DIR;$PYTHON_COMMANDS;$QPID_TESTS_PY;$QPID_TOOLS_LIBS;$QMF_LIB;$env:PYTHONPATH"
$QPID_CONFIG_EXEC="$PYTHON_COMMANDS\qpid-config"
$QPID_ROUTE_EXEC="$PYTHON_COMMANDS\qpid-route"
-$QPID_CLUSTER_EXEC="$PYTHON_COMMANDS\qpid-cluster"
$QPID_HA_TOOL_EXEC="$PYTHON_COMMANDS\qpid-ha-tool"
# Executables
diff --git a/qpid/cpp/src/tests/test_env.sh.in b/qpid/cpp/src/tests/test_env.sh.in
index bafdacf944..486034ca3b 100644
--- a/qpid/cpp/src/tests/test_env.sh.in
+++ b/qpid/cpp/src/tests/test_env.sh.in
@@ -25,6 +25,8 @@ builddir=`absdir @abs_builddir@`
top_srcdir=`absdir @abs_top_srcdir@`
top_builddir=`absdir @abs_top_builddir@`
moduledir=$top_builddir/src@builddir_lib_suffix@
+pythonswigdir=$top_builddir/bindings/qpid/python/
+pythonswiglibdir=$top_builddir/bindings/qpid/python@builddir_lib_suffix@
testmoduledir=$builddir@builddir_lib_suffix@
export QPID_INSTALL_PREFIX=@prefix@
@@ -44,7 +46,8 @@ export PYTHONPATH=$srcdir:$PYTHON_DIR:$PYTHON_COMMANDS:$QPID_TESTS_PY:$QMF_LIB:$
export QPID_CONFIG_EXEC=$PYTHON_COMMANDS/qpid-config
export QPID_ROUTE_EXEC=$PYTHON_COMMANDS/qpid-route
export QPID_HA_EXEC=$PYTHON_COMMANDS/qpid-ha
-
+export PYTHONPATH_SWIG=$pythonswigdir:$pythonswiglibdir
+export PYTHONSWIGMODULE=$pythonswigdir/qpid_messaging.py
# Executables
export QPIDD_EXEC=$top_builddir/src/qpidd
@@ -78,5 +81,5 @@ if [ ! -e "$HOME" ]; then
fi
# Options for boost test framework
-export BOOST_TEST_SHOW_PROGRESS=yes
-export BOOST_TEST_CATCH_SYSTEM_ERRORS=no
+test -z "$BOOST_TEST_SHOW_PROGRESS" && export BOOST_TEST_SHOW_PROGRESS=yes
+test -z "$BOOST_TEST_CATCH_SYSTEM_ERRORS" && export BOOST_TEST_CATCH_SYSTEM_ERRORS=no
diff --git a/qpid/cpp/src/tests/test_store.cpp b/qpid/cpp/src/tests/test_store.cpp
index eac4deda2d..e299161c68 100644
--- a/qpid/cpp/src/tests/test_store.cpp
+++ b/qpid/cpp/src/tests/test_store.cpp
@@ -40,14 +40,19 @@
#include "qpid/sys/Thread.h"
#include "qpid/Plugin.h"
#include "qpid/Options.h"
+#include "qpid/RefCounted.h"
+#include "qpid/Msg.h"
#include <boost/cast.hpp>
#include <boost/lexical_cast.hpp>
#include <memory>
+#include <ostream>
#include <fstream>
+#include <sstream>
-using namespace qpid;
-using namespace broker;
using namespace std;
+using namespace boost;
+using namespace qpid;
+using namespace qpid::broker;
using namespace qpid::sys;
namespace qpid {
@@ -57,11 +62,19 @@ struct TestStoreOptions : public Options {
string name;
string dump;
+ string events;
+ vector<string> throwMsg; // Throw exception if message content matches.
TestStoreOptions() : Options("Test Store Options") {
addOptions()
- ("test-store-name", optValue(name, "NAME"), "Name of test store instance.")
- ("test-store-dump", optValue(dump, "FILE"), "File to dump enqueued messages.")
+ ("test-store-name", optValue(name, "NAME"),
+ "Name of test store instance.")
+ ("test-store-dump", optValue(dump, "FILE"),
+ "File to dump enqueued messages.")
+ ("test-store-events", optValue(events, "FILE"),
+ "File to log events, 1 line per event.")
+ ("test-store-throw", optValue(throwMsg, "CONTENT"),
+ "Throw exception if message content matches.")
;
}
};
@@ -82,24 +95,76 @@ class TestStore : public NullMessageStore {
TestStore(const TestStoreOptions& opts, Broker& broker_)
: options(opts), name(opts.name), broker(broker_)
{
- QPID_LOG(info, "TestStore name=" << name << " dump=" << options.dump);
- if (!options.dump.empty())
+ QPID_LOG(info, "TestStore name=" << name
+ << " dump=" << options.dump
+ << " events=" << options.events
+ << " throw messages =" << options.throwMsg.size());
+
+ if (!options.dump.empty())
dump.reset(new ofstream(options.dump.c_str()));
+ if (!options.events.empty())
+ events.reset(new ofstream(options.events.c_str()));
}
~TestStore() {
for_each(threads.begin(), threads.end(), boost::bind(&Thread::join, _1));
}
- virtual bool isNull() const { return false; }
-
- void enqueue(TransactionContext* ,
+ // Dummy transaction context.
+ struct TxContext : public TPCTransactionContext {
+ static int nextId;
+ string id;
+ TxContext() : id(lexical_cast<string>(nextId++)) {}
+ TxContext(string xid) : id(xid) {}
+ };
+
+ static string getId(const TransactionContext& tx) {
+ const TxContext* tc = dynamic_cast<const TxContext*>(&tx);
+ assert(tc);
+ return tc->id;
+ }
+
+
+ bool isNull() const { return false; }
+
+ void log(const string& msg) {
+ QPID_LOG(info, "test_store: " << msg);
+ if (events.get()) *events << msg << endl << std::flush;
+ }
+
+ auto_ptr<TransactionContext> begin() {
+ auto_ptr<TxContext> tx(new TxContext());
+ log(Msg() << "<begin tx " << tx->id << ">");
+ return auto_ptr<TransactionContext>(tx);
+ }
+
+ auto_ptr<TPCTransactionContext> begin(const std::string& xid) {
+ auto_ptr<TxContext> tx(new TxContext(xid));
+ log(Msg() << "<begin tx " << tx->id << ">");
+ return auto_ptr<TPCTransactionContext>(tx);
+ }
+
+ string getContent(const intrusive_ptr<PersistableMessage>& msg) {
+ intrusive_ptr<broker::Message::Encoding> enc(
+ dynamic_pointer_cast<broker::Message::Encoding>(msg));
+ return enc->getContent();
+ }
+
+ void enqueue(TransactionContext* tx,
const boost::intrusive_ptr<PersistableMessage>& pmsg,
- const PersistableQueue& )
+ const PersistableQueue& queue)
{
- qpid::broker::amqp_0_10::MessageTransfer* msg = dynamic_cast<qpid::broker::amqp_0_10::MessageTransfer*>(pmsg.get());
+ QPID_LOG(debug, "TestStore enqueue " << queue.getName());
+ qpid::broker::amqp_0_10::MessageTransfer* msg =
+ dynamic_cast<qpid::broker::amqp_0_10::MessageTransfer*>(pmsg.get());
assert(msg);
+ ostringstream o;
+ o << "<enqueue " << queue.getName() << " " << getContent(msg);
+ if (tx) o << " tx=" << getId(*tx);
+ o << ">";
+ log(o.str());
+
// Dump the message if there is a dump file.
if (dump.get()) {
msg->getFrames().getMethod()->print(*dump);
@@ -113,7 +178,11 @@ class TestStore : public NullMessageStore {
string data = msg->getFrames().getContent();
size_t i = string::npos;
size_t j = string::npos;
- if (strncmp(data.c_str(), TEST_STORE_DO.c_str(), strlen(TEST_STORE_DO.c_str())) == 0
+ const vector<string>& throwMsg(options.throwMsg);
+ if (find(throwMsg.begin(), throwMsg.end(), data) != throwMsg.end()) {
+ throw Exception(QPID_MSG("TestStore " << name << " throwing exception for: " << data));
+ }
+ else if (strncmp(data.c_str(), TEST_STORE_DO.c_str(), strlen(TEST_STORE_DO.c_str())) == 0
&& (i = data.find(name+"[")) != string::npos
&& (j = data.find("]", i)) != string::npos)
{
@@ -144,6 +213,31 @@ class TestStore : public NullMessageStore {
msg->enqueueComplete();
}
+ void dequeue(TransactionContext* tx,
+ const boost::intrusive_ptr<PersistableMessage>& msg,
+ const PersistableQueue& queue)
+ {
+ QPID_LOG(debug, "TestStore dequeue " << queue.getName());
+ ostringstream o;
+ o<< "<dequeue " << queue.getName() << " " << getContent(msg);
+ if (tx) o << " tx=" << getId(*tx);
+ o << ">";
+ log(o.str());
+ }
+
+ void prepare(TPCTransactionContext& txn) {
+ log(Msg() << "<prepare tx=" << getId(txn) << ">");
+ }
+
+ void commit(TransactionContext& txn) {
+ log(Msg() << "<commit tx=" << getId(txn) << ">");
+ }
+
+ void abort(TransactionContext& txn) {
+ log(Msg() << "<abort tx=" << getId(txn) << ">");
+ }
+
+
private:
static const string TEST_STORE_DO, EXCEPTION, EXIT_PROCESS, ASYNC;
TestStoreOptions options;
@@ -151,8 +245,11 @@ class TestStore : public NullMessageStore {
Broker& broker;
vector<Thread> threads;
std::auto_ptr<ofstream> dump;
+ std::auto_ptr<ofstream> events;
};
+int TestStore::TxContext::nextId(1);
+
const string TestStore::TEST_STORE_DO = "TEST_STORE_DO: ";
const string TestStore::EXCEPTION = "exception";
const string TestStore::EXIT_PROCESS = "exit_process";
diff --git a/qpid/cpp/src/tests/test_tools.h b/qpid/cpp/src/tests/test_tools.h
index de672f938a..7950a36913 100644
--- a/qpid/cpp/src/tests/test_tools.h
+++ b/qpid/cpp/src/tests/test_tools.h
@@ -23,7 +23,6 @@
#include <limits.h> // Include before boost/test headers.
#include <boost/test/test_tools.hpp>
#include <boost/assign/list_of.hpp>
-#include <boost/assign/list_of.hpp>
#include <vector>
#include <set>
#include <ostream>
diff --git a/qpid/cpp/src/tests/testagent.cpp b/qpid/cpp/src/tests/testagent.cpp
deleted file mode 100644
index e6010a8e00..0000000000
--- a/qpid/cpp/src/tests/testagent.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include <qpid/management/Manageable.h>
-#include <qpid/management/ManagementObject.h>
-#include <qpid/agent/ManagementAgent.h>
-#include <qpid/sys/Mutex.h>
-#include <qpid/sys/Time.h>
-#include "qmf/org/apache/qpid/agent/example/Parent.h"
-#include "qmf/org/apache/qpid/agent/example/Child.h"
-#include "qmf/org/apache/qpid/agent/example/ArgsParentCreate_child.h"
-#include "qmf/org/apache/qpid/agent/example/EventChildCreated.h"
-#include "qmf/org/apache/qpid/agent/example/Package.h"
-
-#include <signal.h>
-#include <cstdlib>
-#include <iostream>
-
-#include <sstream>
-
-namespace qpid {
-namespace tests {
-
-static bool running = true;
-
-using std::string;
-using qpid::management::ManagementAgent;
-using qpid::management::ManagementObject;
-using qpid::management::Manageable;
-using qpid::management::Args;
-using qpid::sys::Mutex;
-namespace _qmf = qmf::org::apache::qpid::agent::example;
-
-class ChildClass;
-
-//==============================================================
-// CoreClass is the operational class that corresponds to the
-// "Parent" class in the management schema.
-//==============================================================
-class CoreClass : public Manageable
-{
- string name;
- ManagementAgent* agent;
- _qmf::Parent* mgmtObject;
- std::vector<ChildClass*> children;
- Mutex vectorLock;
-
-public:
-
- CoreClass(ManagementAgent* agent, string _name);
- ~CoreClass() { mgmtObject->resourceDestroy(); }
-
- ManagementObject* GetManagementObject(void) const
- { return mgmtObject; }
-
- void doLoop();
- status_t ManagementMethod (uint32_t methodId, Args& args, string& text);
-};
-
-class ChildClass : public Manageable
-{
- string name;
- _qmf::Child* mgmtObject;
-
-public:
-
- ChildClass(ManagementAgent* agent, CoreClass* parent, string name);
- ~ChildClass() { mgmtObject->resourceDestroy(); }
-
- ManagementObject* GetManagementObject(void) const
- { return mgmtObject; }
-
- void doWork()
- {
- mgmtObject->inc_count(2);
- }
-};
-
-CoreClass::CoreClass(ManagementAgent* _agent, string _name) : name(_name), agent(_agent)
-{
- static uint64_t persistId = 0x111222333444555LL;
- mgmtObject = new _qmf::Parent(agent, this, name);
-
- agent->addObject(mgmtObject, persistId++);
- mgmtObject->set_state("IDLE");
-}
-
-void CoreClass::doLoop()
-{
- // Periodically bump a counter to provide a changing statistical value
- while (running) {
- qpid::sys::sleep(1);
- mgmtObject->inc_count();
- mgmtObject->set_state("IN_LOOP");
-
- {
- Mutex::ScopedLock _lock(vectorLock);
-
- for (std::vector<ChildClass*>::iterator iter = children.begin();
- iter != children.end();
- iter++) {
- (*iter)->doWork();
- }
- }
- }
-}
-
-Manageable::status_t CoreClass::ManagementMethod(uint32_t methodId, Args& args, string& /*text*/)
-{
- Mutex::ScopedLock _lock(vectorLock);
-
- switch (methodId) {
- case _qmf::Parent::METHOD_CREATE_CHILD:
- _qmf::ArgsParentCreate_child& ioArgs = (_qmf::ArgsParentCreate_child&) args;
-
- ChildClass *child = new ChildClass(agent, this, ioArgs.i_name);
- ioArgs.o_childRef = child->GetManagementObject()->getObjectId();
-
- children.push_back(child);
-
- agent->raiseEvent(_qmf::EventChildCreated(ioArgs.i_name));
-
- return STATUS_OK;
- }
-
- return STATUS_NOT_IMPLEMENTED;
-}
-
-ChildClass::ChildClass(ManagementAgent* agent, CoreClass* parent, string name)
-{
- mgmtObject = new _qmf::Child(agent, this, parent, name);
-
- agent->addObject(mgmtObject);
-}
-
-
-//==============================================================
-// Main program
-//==============================================================
-
-ManagementAgent::Singleton* singleton;
-
-void shutdown(int)
-{
- running = false;
-}
-
-int main_int(int argc, char** argv)
-{
- singleton = new ManagementAgent::Singleton();
- const char* host = argc>1 ? argv[1] : "127.0.0.1";
- int port = argc>2 ? atoi(argv[2]) : 5672;
-
- signal(SIGINT, shutdown);
-
- // Create the qmf management agent
- ManagementAgent* agent = singleton->getInstance();
-
- // Register the Qmf_example schema with the agent
- _qmf::Package packageInit(agent);
-
- // Start the agent. It will attempt to make a connection to the
- // management broker
- agent->init(host, port, 5, false, ".magentdata");
-
- // Allocate some core objects
- CoreClass core1(agent, "Example Core Object #1");
- CoreClass core2(agent, "Example Core Object #2");
- CoreClass core3(agent, "Example Core Object #3");
-
- core1.doLoop();
-
- // done, cleanup and exit
- delete singleton;
-
- return 0;
-}
-
-}} // namespace qpid::tests
-
-int main(int argc, char** argv)
-{
- try {
- return qpid::tests::main_int(argc, argv);
- } catch(std::exception& e) {
- std::cerr << "Top Level Exception: " << e.what() << std::endl;
- return 1;
- }
-}
-
diff --git a/qpid/cpp/src/tests/testagent.mk b/qpid/cpp/src/tests/testagent.mk
deleted file mode 100644
index 0492f3e3bb..0000000000
--- a/qpid/cpp/src/tests/testagent.mk
+++ /dev/null
@@ -1,51 +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.
-#
-
-# Build a simple qmf agent for test purposes.
-
-TESTAGENT_GEN_SRC= \
- testagent_gen/qmf/org/apache/qpid/agent/example/Parent.h \
- testagent_gen/qmf/org/apache/qpid/agent/example/Child.h \
- testagent_gen/qmf/org/apache/qpid/agent/example/Parent.cpp \
- testagent_gen/qmf/org/apache/qpid/agent/example/Child.cpp \
- testagent_gen/qmf/org/apache/qpid/agent/example/ArgsParentCreate_child.h \
- testagent_gen/qmf/org/apache/qpid/agent/example/EventChildCreated.h \
- testagent_gen/qmf/org/apache/qpid/agent/example/EventChildDestroyed.h \
- testagent_gen/qmf/org/apache/qpid/agent/example/EventChildCreated.cpp \
- testagent_gen/qmf/org/apache/qpid/agent/example/EventChildDestroyed.cpp \
- testagent_gen/qmf/org/apache/qpid/agent/example/Package.h \
- testagent_gen/qmf/org/apache/qpid/agent/example/Package.cpp
-
-$(TESTAGENT_GEN_SRC): testagent_gen.timestamp
-if GENERATE
-TESTAGENT_DEPS=../mgen.timestamp
-endif # GENERATE
-testagent_gen.timestamp: testagent.xml ${TESTAGENT_DEPS}
- $(QMF_GEN) -o testagent_gen/qmf $(srcdir)/testagent.xml
- touch $@
-
-CLEANFILES+=$(TESTAGENT_GEN_SRC) testagent_gen.timestamp
-
-testagent-testagent.$(OBJEXT): $(TESTAGENT_GEN_SRC)
-qpidexectest_PROGRAMS+=testagent
-testagent_CXXFLAGS=$(CXXFLAGS) -Itestagent_gen
-testagent_SOURCES=testagent.cpp $(TESTAGENT_GEN_SRC)
-testagent_LDADD=$(top_builddir)/src/libqmf.la $(top_builddir)/src/libqpidcommon.la $(top_builddir)/src/libqpidtypes.la $(top_builddir)/src/libqpidclient.la
-
-EXTRA_DIST+=testagent.xml
diff --git a/qpid/cpp/src/tests/testagent.xml b/qpid/cpp/src/tests/testagent.xml
deleted file mode 100644
index 0b1436f999..0000000000
--- a/qpid/cpp/src/tests/testagent.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<schema package="org.apache.qpid.agent.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
- 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.
--->
-
- <!--
- ===============================================================
- Parent
- ===============================================================
- -->
- <class name="Parent">
-
- This class represents a parent object
-
- <property name="name" type="lstr" access="RC" index="y"/>
-
- <statistic name="state" type="sstr" desc="Operational state of the link"/>
- <statistic name="count" type="count64" unit="tick" desc="Counter that increases monotonically"/>
-
- <method name="create_child" desc="Create child object">
- <arg name="name" dir="I" type="lstr"/>
- <arg name="childRef" dir="O" type="objId"/>
- </method>
- </class>
-
-
- <!--
- ===============================================================
- Child
- ===============================================================
- -->
- <class name="Child">
- <property name="ParentRef" type="objId" references="Parent" access="RC" index="y" parentRef="y"/>
- <property name="name" type="lstr" access="RC" index="y"/>
-
- <statistic name="count" type="count64" unit="tick" desc="Counter that increases monotonically"/>
-
- <method name="delete"/>
- </class>
-
- <eventArguments>
- <arg name="childName" type="lstr"/>
- </eventArguments>
-
- <event name="ChildCreated" args="childName"/>
- <event name="ChildDestroyed" args="childName"/>
-</schema>
-
diff --git a/qpid/cpp/src/xml.mk b/qpid/cpp/src/xml.mk
deleted file mode 100644
index 9376cfd54a..0000000000
--- a/qpid/cpp/src/xml.mk
+++ /dev/null
@@ -1,29 +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.
-#
-dmoduleexec_LTLIBRARIES += xml.la
-
-xml_la_SOURCES = \
- qpid/xml/XmlExchange.cpp \
- qpid/xml/XmlExchange.h \
- qpid/xml/XmlExchangePlugin.cpp
-
-xml_la_LIBADD = -lxerces-c -lxqilla libqpidbroker.la
-xml_la_CXXFLAGS = $(AM_CXXFLAGS) -D_IN_QPID_BROKER
-xml_la_LDFLAGS = $(PLUGINLDFLAGS)
-